找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 5309|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

ucos原理--任務(wù)簡(jiǎn)介

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:114320 發(fā)表于 2016-5-10 01:20 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
本以為做個(gè)讀書(shū)筆記,誰(shuí)知不懂的太多,抄書(shū)好了。
來(lái)源:《嵌入式實(shí)時(shí)操作系統(tǒng)-uc/os原理與實(shí)踐》   盧友亮 編著


一:操作系統(tǒng)
1:操作系統(tǒng)基本功能:
     任務(wù)管理
    CPU管理
   內(nèi)存管理 ----給任務(wù)分配內(nèi)存空間,內(nèi)存結(jié)束后釋放內(nèi)存空間
   文件管理----對(duì)文件存儲(chǔ)器的存儲(chǔ)空間進(jìn)行組織,非配和回收,負(fù)責(zé)文件的存儲(chǔ),檢索,共享和保護(hù)
I/O設(shè)備管理


第二章:  實(shí)時(shí)操作系統(tǒng)(RTOS)
一:概述:
(一):定義
是指當(dāng)外界事件或數(shù)據(jù)產(chǎn)生時(shí),能夠接受并以足夠快的速度予以處理,其處理的結(jié)果又能在規(guī)定的時(shí)間之內(nèi)來(lái)控制生產(chǎn)過(guò)程或?qū)μ幚硐到y(tǒng)做出快速響應(yīng),調(diào)度一切可利用的資源完成實(shí)時(shí)任務(wù),并控制所有實(shí)時(shí)任務(wù)協(xié)調(diào)一致運(yùn)行的操作系統(tǒng)。


硬實(shí)時(shí)操作系統(tǒng):要求在規(guī)定的時(shí)間內(nèi)必須完成操作
軟實(shí)時(shí)操作系統(tǒng):只要按照任務(wù)的優(yōu)先級(jí),盡可能快地完成操作


(二):特征:

1:多任務(wù):系統(tǒng)中多個(gè)任務(wù)同時(shí)運(yùn)行。當(dāng)時(shí)cpu只有一個(gè),在某一個(gè)時(shí)刻,只有一個(gè)任務(wù)占有cpu,因此,多任務(wù)操作系統(tǒng)的核心任務(wù)之一是任務(wù)調(diào)度,為任務(wù)分配cpu時(shí)間。

2:多級(jí)中斷機(jī)制:
以確保對(duì)緊迫程度較高的實(shí)時(shí)時(shí)間進(jìn)行及時(shí)響應(yīng)和處理----例如:溫度超高的報(bào)警先處理


3:優(yōu)先級(jí)調(diào)度機(jī)制:
越緊迫的任務(wù)優(yōu)先級(jí)越高
任務(wù)管理模塊必須根據(jù)優(yōu)先級(jí)調(diào)度任務(wù),而又能保證任務(wù)在切換過(guò)程中不被破壞。



(三):任務(wù)

1:任務(wù)簡(jiǎn)介
任務(wù)有 睡眠,就緒,運(yùn)行,阻塞,掛起等多種狀態(tài)
典型的任務(wù)運(yùn)行方式是循環(huán)。

例1:
標(biāo)準(zhǔn)的任務(wù)結(jié)構(gòu):(用戶任務(wù))
void   usertask(void *pParam)    //參數(shù)是指針類(lèi)型的
{
   int  i=*((int *)pParam);             //將指針強(qiáng)制轉(zhuǎn)換為指向整數(shù)類(lèi)型的指針,然后取改指針?biāo)傅膬?nèi)容,將它賦值給一個(gè)局部變量i

for( ; ; )                                    //進(jìn)入無(wú)限循環(huán)
printf("\n\r%d\n",i++);          //在循環(huán)體打印輸出當(dāng)前的計(jì)數(shù)值i


OSTimeDly(OS_TICKS_PER_SEC);    //調(diào)用操作系統(tǒng)演示函數(shù),延時(shí)1s。1s后又可以獲得運(yùn)行,繼續(xù)循環(huán)
}


注:
OSTimeDly首先將本任務(wù) 阻塞掉,這樣,即使該任務(wù)優(yōu)先級(jí)最高,也可以讓低優(yōu)先級(jí)的任務(wù)獲得運(yùn)行的機(jī)會(huì)。操作系統(tǒng)1s后使這個(gè)任務(wù)重新就緒,重新得到運(yùn)行。




2:多任務(wù):
優(yōu)點(diǎn):可以大大提高cpu的利用率,使應(yīng)用程序分成多個(gè)程序模塊,實(shí)現(xiàn)模塊化,應(yīng)用程序更易于設(shè)計(jì)和維護(hù)

例如:在ARM采集處理系統(tǒng)中,同時(shí)采集16路信號(hào),又同時(shí)對(duì)多信號(hào)進(jìn)行處理和傳輸,
可以創(chuàng)建16個(gè)任務(wù)負(fù)責(zé)16路信號(hào)的采集,
創(chuàng)建一個(gè)任務(wù)對(duì)信號(hào)進(jìn)行處理,
再創(chuàng)建一個(gè)任務(wù)負(fù)責(zé)數(shù)據(jù)的傳輸。

例:2:
int main(int argc, char **argv)
{
int  p[2];
p[0]=0;
p[1]=100;

OSInit();                                   //對(duì)ucosii內(nèi)核進(jìn)行初始化
OSTaskCreate(TaskStart,0,&TaskStk[0][TASK_STK_SIZE-1],TaskStart_Prio);   //創(chuàng)建一個(gè)設(shè)置時(shí)鐘中斷的任務(wù)

//創(chuàng)建用戶任務(wù),任務(wù)代碼是例1的usertask,參數(shù)是p,即指向p[0]的指針,優(yōu)先級(jí)是5
OSTaskCreate(
usertask,p,&TaskStk[2][TASK_STK_SIZE-1],5);  
//創(chuàng)建用戶任務(wù),任務(wù)代碼是例1的usertask,參數(shù)是p+1,即指向p[1]的指針,優(yōu)先級(jí)是6
OSTaskCreate(usertask,p+1,&TaskStk[3][TASK_STK_SIZE-1],6);
OSStart();        //開(kāi)始啟動(dòng)多任務(wù)
return 0;

}




分析:
兩個(gè)用戶任務(wù)的優(yōu)先級(jí)雖然不同,但是都執(zhí)行延時(shí)操作,也就是說(shuō)主動(dòng)放棄cpu,因此可以輪流運(yùn)行。
(如果沒(méi)有執(zhí)行延時(shí)操作,把自己阻塞起來(lái),在高優(yōu)先級(jí)任務(wù)結(jié)束前,低優(yōu)先級(jí)的任務(wù)是不能得到運(yùn)行的)


運(yùn)行結(jié)果:  第一個(gè)任務(wù)的參數(shù)是0,從0開(kāi)始計(jì)數(shù),第二個(gè)任務(wù)的參數(shù)是100,從100開(kāi)始計(jì)數(shù)。
兩個(gè)任務(wù)輪流輸出結(jié)果到屏幕,多任務(wù)被調(diào)度運(yùn)行了。

0
100
1
101
2
102
3
103


3:任務(wù)狀態(tài):






1:睡眠態(tài):
在調(diào)用 OSTaskCreate(任務(wù)創(chuàng)建函數(shù))創(chuàng)建之前,處于睡眠狀態(tài)。   
睡眠狀態(tài)的任務(wù)是不會(huì)運(yùn)行的,操作系統(tǒng)也不會(huì)為他設(shè)置運(yùn)行而準(zhǔn)備的數(shù)據(jù)結(jié)構(gòu),沒(méi)有給它配置任務(wù)模塊。
2:就緒態(tài)
當(dāng)操作系統(tǒng)調(diào)用 OSTaskCreate()創(chuàng)建一個(gè)任務(wù)后,任務(wù)進(jìn)入就緒態(tài)。
圖中可以看到,任務(wù)也可以從其他狀態(tài)進(jìn)入就緒態(tài)。

處于就緒態(tài)的任務(wù) :操作系統(tǒng)已經(jīng)為其運(yùn)行配置好了任務(wù)控制模塊等數(shù)據(jù)結(jié)構(gòu)。
當(dāng)沒(méi)有比它優(yōu)先級(jí)更高的任務(wù)或者優(yōu)先級(jí)更高的任務(wù)處于阻塞態(tài)的時(shí)候,就可以被系統(tǒng)調(diào)度進(jìn)入運(yùn)行態(tài),操作系統(tǒng)是調(diào)用任務(wù)切換函數(shù)完成的。


3:運(yùn)行態(tài):
運(yùn)行態(tài)是任務(wù)真正占有cpu,得到運(yùn)行。這時(shí)運(yùn)行的代碼就是任務(wù)的代碼,如usertask。

處于運(yùn)行態(tài)的任務(wù)如果運(yùn)行完成,就會(huì)進(jìn)入睡眠態(tài)。
如果更高優(yōu)先級(jí)的任務(wù)搶占了cpu,就會(huì)轉(zhuǎn)到就緒態(tài)。

如果 因?yàn)榈却骋皇录绲却?s的時(shí)間,OSTimeDly(OS_TICKS_PER_SEC); 需要暫時(shí)放棄cpu的使用權(quán)而讓其他任務(wù)得到運(yùn)行,就進(jìn)入阻塞態(tài)。

當(dāng)由于中斷的到來(lái)而使cpu進(jìn)入中斷服務(wù)函數(shù)ISR,必然使正在運(yùn)行過(guò)得任務(wù)放棄cpu而轉(zhuǎn)入中斷服務(wù)程序,這是被中斷的程序就會(huì)被掛起而進(jìn)入掛起態(tài)。


4:阻塞態(tài):
阻塞態(tài)對(duì)于操作系統(tǒng)的調(diào)度、任務(wù)的協(xié)調(diào)運(yùn)行時(shí)很重要的。
圖中所示:并不是只有一個(gè)高優(yōu)先級(jí)的任務(wù)在運(yùn)行,是因?yàn)閡sertask在沒(méi)有事情可做,在等待1s的時(shí)候,不是強(qiáng)行運(yùn)行代碼,而使把自己阻塞起來(lái),使操作系統(tǒng)可以調(diào)度其他的任務(wù)。OSTimeDly(OS_TICKS_PER_SEC);

當(dāng)任務(wù)在等待某些還沒(méi)有被釋放的資源或等待一定時(shí)間的時(shí)候,要阻塞起來(lái),等到條件滿足的時(shí)候再重新回到就緒態(tài),又能被操作系統(tǒng)調(diào)度以進(jìn)入運(yùn)行態(tài)。這是實(shí)時(shí)操作系統(tǒng)必須實(shí)現(xiàn)的功能之一。

注意:錯(cuò)誤:一些不理解操作系統(tǒng)的讀者編程時(shí)候,在等待的時(shí)候常常使用for循環(huán),不停的執(zhí)行代碼而使cpu的利用率暴增,使系統(tǒng)的運(yùn)行,甚至造成死機(jī),十分惡劣。這樣不可取。

5:掛起態(tài):
當(dāng)任務(wù)在運(yùn)行時(shí),因?yàn)?font color="#ff00">中斷的發(fā)生(例如定時(shí)器中斷每個(gè)時(shí)鐘滴答)中斷一次,被剝奪cpu的使用權(quán)而進(jìn)入掛起狀。在中斷返回的時(shí)候,若該任務(wù)還是最高優(yōu)先級(jí)的,則恢復(fù)運(yùn)行。
如果不是這樣,就回到就緒態(tài)。


4:任務(wù)切換:-----Context Switch
任務(wù)切換時(shí)暫停一個(gè)任務(wù)的運(yùn)行,云更新另一個(gè)處于就緒態(tài)的任務(wù),暫停一個(gè)任務(wù),以后又能恢復(fù)運(yùn)行,必須考慮將這個(gè)任務(wù)的信息保存,而恢復(fù)運(yùn)行的時(shí)候需要將這些信息恢復(fù)到運(yùn)行環(huán)境。

因此,任務(wù)切換必須做環(huán)境的保存和恢復(fù)的操作。
環(huán)境的保存和恢復(fù)與任務(wù)有關(guān),業(yè)余任務(wù)運(yùn)行的硬件環(huán)境有關(guān)(PC和ARM有不同的寄存器,所以不同,因此涉及到匯編語(yǔ)言實(shí)現(xiàn)的最底層代碼。---因此需要一定的計(jì)算機(jī)原理或者嵌入式系統(tǒng)的基本知識(shí)。


多任務(wù)的關(guān)鍵在于.如何將調(diào)度,ucos采用的是可剝奪優(yōu)先級(jí)調(diào)度算法。
多任務(wù)下,個(gè)任務(wù)還要按照一定的次序運(yùn)行,因此存在同步問(wèn)題,因此引入了信號(hào)量的改年來(lái)進(jìn)行同步。

人物間有相互通信的需求,因此操作系統(tǒng)需要有郵箱、消息等用于通信的數(shù)據(jù)結(jié)構(gòu),以便多任務(wù)通信。

多個(gè)任務(wù)可能真多有限的資源而不發(fā)生沖突,因此操作系統(tǒng)還需要管理各任務(wù),使他們能夠充分利用資源而不發(fā)生沖突,因此又產(chǎn)生了互斥,死鎖等概念。





5:可重入函數(shù)  與   不可重入函數(shù)  (任務(wù)應(yīng)該調(diào)用可重入函數(shù))
可重入函數(shù): 指一個(gè)函數(shù)可以被多個(gè)任務(wù)調(diào)用。(不需要擔(dān)心在任務(wù)切換的過(guò)程中,代碼的執(zhí)行會(huì)摻和啥呢個(gè)錯(cuò)誤的結(jié)果)
不可重入函數(shù):如果可能產(chǎn)生錯(cuò)誤的結(jié)果,就是不可重入函數(shù)。


例3:
啟動(dòng)兩個(gè)用戶任務(wù):usertask1和usertask2    兩個(gè)任務(wù)都調(diào)用add2函數(shù)(將返回兩個(gè)參數(shù)相加的結(jié)果),使用了全局變量a和b。

void usertask1(void *pParam)
{
int sum;
for( ; ; )
   {
      printf("\ntask%  call add2(1,2)\n",1);
  sum=add2(1,2);
printf("\ntask%  call add2(1,2)  solution is %d\n",1,sum);
   }
}



void usertask2(void *pParam)
{
int sum;
for( ; ; )
   {
      printf("\ntask%  call add2(100,200)\n",2);
  sum=add2(100,200);
printf("\ntask%  call add2(100,200)  solution is %d\n",2,sum);
   }
}




a:
使用不可重入函數(shù)得到的錯(cuò)誤結(jié)果:

int a,b;                                    //定義全局變量,各個(gè)任務(wù)都可以訪問(wèn)的全局變量
int add2(int p1,int,p2)       //函數(shù)add2()實(shí)現(xiàn)對(duì)兩個(gè)參數(shù)相加,返回結(jié)果,因?yàn)槭褂昧巳肿兞,所以在任?wù)切換過(guò)程中,他得知可能改變
{
a=p1;
b=p2;
OSTimeDly(OS_TICKS_PER_SEC);          //延時(shí)1s任務(wù)被阻塞,以保證任務(wù)被切換
return(a+b);                                          //返回相加結(jié)果
}



運(yùn)行結(jié)果:
task1 call add2(1,2)  solution is 300

task2 call add2(100,200)  solution is 3

task1 call add2(1,2)  solution is 300

task2 call add2(100,200)  solution is 3

分析:
結(jié)果完全錯(cuò)誤。
usertask1的優(yōu)先級(jí)為5,usertask2的優(yōu)先級(jí)為6。
操作系統(tǒng)首先調(diào)度usertask1運(yùn)行,對(duì)變量a、b進(jìn)行賦值,運(yùn)行結(jié)果為a=1,b=2.
然后調(diào)用OSTimeDly(OS_TICKS_PER_SEC);延時(shí),usertask1被阻塞,操作系統(tǒng)進(jìn)行一次任務(wù)切換。
usertask2得到尋釁,對(duì)a,b進(jìn)行賦值,運(yùn)行結(jié)果為a=100,b=200.
在經(jīng)過(guò)一段延時(shí)后,usertask1被喚醒,重新得到運(yùn)行,返回a+b的結(jié)果,于是有了1+2=300的錯(cuò)誤結(jié)果。

打印出第一行后,usertask1仍然要進(jìn)行循環(huán),于是又調(diào)用add2,又給a、b進(jìn)行賦值,運(yùn)行結(jié)果為a=1,b=2,
再延時(shí),進(jìn)入usertask2延時(shí)結(jié)束得到運(yùn)行,打印出了第二行100+200=3的錯(cuò)誤結(jié)果。






b:使用可重入函數(shù)得到正確結(jié)果


                              
int add2(int p1,int,p2)       //函數(shù)add2()實(shí)現(xiàn)對(duì)兩個(gè)參數(shù)相加,返回結(jié)果,因?yàn)槭褂昧巳肿兞,所以在任?wù)切換過(guò)程中,他得知可能改變
{
int a,b;  

a=p1;
b=p2;
OSTimeDly(OS_TICKS_PER_SEC);          //延時(shí)1s任務(wù)被阻塞,以保證任務(wù)被切換
return(a+b);                                          //返回相加結(jié)果
}



運(yùn)行結(jié)果:
task1 call add2(1,2)  solution is 3

task2 call add2(100,200)  solution is 300

task1 call add2(1,2)  solution is 3

task2 call add2(100,200)  solution is 300



分析:
結(jié)果正確。
原因是add2函數(shù)采用了可重入代碼----------因此在實(shí)時(shí)多任務(wù)操作系統(tǒng)中,公用函數(shù)口用該采用可重入代碼。


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表