(本文原創,轉載請註明出處)
自《uC/OS-II Windows下虛擬問題》發表以後,很多朋友給我留言,:),在此,謝謝大家的批評指正。希望大家直接在我的Blog上留言,少用QQ留言,這些技術問題,在Blog上討論,會越辯越明。在QQ上留言,很容易一邊倒。
特別是“探路者”網友給我的留言,這裡貼出來,供大家一起研究:
2011-08-27 08:49:22 探路者:
uC/OS-II Windows下虛擬問題:我覺得你的分析存在問題的。
2011-08-27 08:51:47 探路者:
對於Windows和Linux來說,進程是作業系統能夠調度的最小單位,線程是進程能夠調度的最小單位。
2011-08-27 08:54:21 探路者:
ucosii程式,一個整體,是作為作業系統能夠調度的最小單位-進程來啟動並執行,作業系統不會認識到ucosii程式內部的運作,比如多線程。
2011-08-27 09:01:25 探路者:
對於作業系統來說,只有進程切換,而沒有線程切換。
2011-08-27 09:01:52 探路者:
對於單個進程來說,才會存線上程切換。
2011-08-27 10:06:04 探路者:
對於第一個問題:不存在單獨的線程切換,只存在進程的切換。雖然ucosii整體(進程)的即時性得不到最優的保證,但是ucosii整體(進程)的啟動並執行完整性是得到保證的。
2011-08-27 10:09:24 探路者:
對於第二個問題:既然訪問共用資源,那麼就一定會考慮互斥的問題了。訪問windows和linux作業系統的臨界資源的前後,考慮加鎖和解鎖,也是一件正常不過的事情。
2011-08-27 10:14:55 探路者:
請雪松大俠分析清楚,我對這個問題也是很著急,因為我就是這樣在用,而且想應用到一個控制系統中。如果我貿然使用,會出現《驚魂動車組》,就麻煩了。
這裡我不想多說,《uC/OS-II Windows下虛擬問題》中已經說得非常清楚, 這裡舉上一個實際的例子:
void task1(void *param)
{
while (1)
{
printf("Haha....you are in task 1.\n");
OSTimeDly(40);
}
}
void task2(void *param)
{
while(1)
{
printf("Haha, you are in task 2.\n");
OSTimeDly(20);
}
}
void task3(void *param)
{
while(1)
{
printf("Haha, you are in task 3.\n");
OSTimeDly(20);
}
}
這三個任務是再簡單不過的任務了。現在假設任務1的優先順序別最高,任務2的優先順序別次之,任務3的優先順序別最低。printf這個函數都會往螢幕上輸出,windows 為了防止輸出錯亂,printf 函數內部是有一個 windows 的鎖,用來防止輸出到螢幕上的資料錯亂。正因為有了這個鎖,我們看到的輸出資訊不會有類似以下的輸出:
Haha, you are Haha, in task 2.
you are in task 3.
如果在windows上類比,使用了windows庫裡的printf函數,這個鎖是無法規避的。為了便於討論,我們把printf簡化為如下虛擬碼:
int printf(char *fmt, ...)
{
char *lines[MAX_OUTPUT];
*lines = '\0';
...;//output print data to lines;
lockscreen();//acquire lock.
output2screen(lines);
unlockscreen();//release lock.
return ...;
}
本來uC/OS-II運行到任務3的printf語句時如果全部完成,也沒什麼事情。假設如果運行到lockscreen()時,正在ouput2screen()呢。uC/OS-II覺得你的時間到了,運行任務1去了。如果運行到printf中的lockscreen()時,那麼task1就執行不下去了。只能執行其它任務,或者讓任務3執行下去,直到unlockscreen()。task1才能繼續執行。
我們來細細看一下:
lockscreen()並不是uC/OS-II的鎖。
uC/OS-II並不知道task3已經進入了一個臨界地區,在windows下的移植裡,uC/OS-II的核心會調用SuspendThread()掛起task3,task3並不會自己恢複執行,必須 uC/OS-II的調度演算法調用ResumeThread(),task3才能恢複執行。調度演算法調用ResumeThread恢複task1執行時,遇到lockscreen,task1進入阻塞狀態,這個阻塞狀態是windows的阻塞狀態,在uC/OS-II核心裡,task1仍然是運行態。
但實際上task1已經死了,所有低於task1優先順序的任務都Over了。如果 task1是最高優先順序任務,那麼整個uC/OS-II雖然沒有死,但現象就是全部都死了。
我想我講清楚整個過程了吧。模擬這個過程也很簡單,在 VC++上很容易線上這個問題。由於並不是必現的問題,多弄幾個printf任務,增大出現的幾率。通過thread觀察視窗和callstack視窗,可以明顯的看到task1和task3都停在了printf裡面。在windows的系統核心裡停下了。歡迎拍磚!!!
(本文原創,轉載請註明出處)