欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

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

QQ登錄

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

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

uC/OS-II學(xué)習(xí)筆記—信號(hào)量管理

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
信號(hào)量在資源共享管理、任務(wù)同步與通信等方面都有廣泛的應(yīng)用。uC/OS-II單獨(dú)為信號(hào)量管理編寫了C語(yǔ)言文件os_sem.c。信號(hào)管理的核心函數(shù)如下所示:

信號(hào)量通過(guò)OSSemCreate創(chuàng)建,并分配一個(gè)ECB給該信號(hào)量。OSSemSet可以單獨(dú)設(shè)置信號(hào)量的計(jì)數(shù)值,這個(gè)值在ECB中。被創(chuàng)建的信號(hào)量可以通過(guò)OSSemDel來(lái)刪除。OSSemQuery查詢信號(hào)量的信息。這4種操作針對(duì)的對(duì)象是信號(hào)量,使用的數(shù)據(jù)結(jié)構(gòu)式ECB。
OSSemPend是任務(wù)請(qǐng)求信號(hào)量時(shí)執(zhí)行的操作。例如,請(qǐng)求操作串口、打印機(jī)或某共享數(shù)據(jù)結(jié)構(gòu),如果這時(shí)信號(hào)量無(wú)效,任務(wù)就被阻塞,并在ECB中標(biāo)記自己在等待。
OSSemPost是使用資源的任務(wù)由于資源使用結(jié)束而提交信號(hào)量,這時(shí)ECB中被阻塞的任務(wù)中優(yōu)先級(jí)最高的因?yàn)楂@得了信號(hào)量,被喚醒回到就緒態(tài)。
OSSemAccept是任務(wù)無(wú)等待的請(qǐng)求信號(hào)量,也就是說(shuō),如果訪問(wèn)的資源有效,那么就訪問(wèn);如果訪問(wèn)的資源無(wú)效也不阻塞自己,而是去做其他工作。因此,OSSemAccept非常適用于中斷服務(wù)程序(ISR)。
OSSemPendAbort放棄某任務(wù)對(duì)信號(hào)量的等待,任務(wù)仍將被喚醒回到就緒態(tài)。
所以,以上4中函數(shù)的操作對(duì)象不僅包括事件控制塊(ECB),還將包括任務(wù)管理中如任務(wù)控制塊(TCB)、就緒表等諸多數(shù)據(jù)結(jié)構(gòu)。
信號(hào)量在操作系統(tǒng)初始化的時(shí)候并不存在。這時(shí),操作系統(tǒng)中的事件管理數(shù)據(jù)結(jié)構(gòu)事件控制塊(ECB)為全空,所有的事件控制塊都在ECB空閑鏈表中排隊(duì)。信號(hào)量的建立函數(shù)OSSemCreate將使用一個(gè)并配置一個(gè)ECB,使其具備信號(hào)量的屬性。創(chuàng)建信號(hào)量的函數(shù)OSSemCreate的代碼如下所示:

首先,如果是在中斷服務(wù)程序中,那么中斷服務(wù)程序按照規(guī)范,應(yīng)該先調(diào)用OSIntEnter,該函數(shù)將中斷嵌套數(shù)OSIntNesting加1,因此只要是在中斷服務(wù)中調(diào)用OSSemCreate,OSIntNesting>0u就應(yīng)該成立,OSSemCreate就返回。OSEventFreeList指向ECB空閑鏈表的表頭,如果OSEventFreeList的值是0,即空指針,那么ECB鏈表就為空。這說(shuō)明已經(jīng)沒(méi)有空閑的ECB可供使用了。在這種情況下,當(dāng)然就不能創(chuàng)建信號(hào)量或任何其他的事件。當(dāng)將宏OS_MAX_EVENTS定義的太小滿足不了需要的時(shí)候就會(huì)出現(xiàn)這種情況。另外,還需要注意的是事件沒(méi)有用時(shí)要盡快釋放還給系統(tǒng)。在OSEventFreeList的值不為0的情況下,既然將空閑ECB鏈表的表頭分配給要?jiǎng)?chuàng)建的信號(hào)量事件,就需要將空閑ECB鏈表的第一個(gè)ECB取下來(lái),這時(shí)OSEventList應(yīng)該指向第二個(gè)ECB。接下來(lái)的5條語(yǔ)句

都是對(duì)取得的ECB進(jìn)行賦值。假設(shè)信號(hào)量值為5,則賦值后的ECB應(yīng)該如下圖所示:

宏OS_EVENT_TYPE_SEM的值是3,所以ECB中OSEventType的值為3。假設(shè)該信號(hào)量為創(chuàng)建的第一個(gè)事件,那么事件空閑任務(wù)鏈表將去掉第一個(gè)事件控制塊如下所示:

另外,應(yīng)用程序在調(diào)用OSSemCreate創(chuàng)建了一個(gè)信號(hào)量后如何找到該ECB以進(jìn)行操作呢?這個(gè)也沒(méi)有問(wèn)題,因?yàn)镺SSemCreate返回了該ECB的指針。代碼中也可以看到,如果創(chuàng)建失敗,那么返回的是空指針,應(yīng)用程序可根據(jù)返回值是否為空指針判斷是否創(chuàng)建失敗。如果成功,根據(jù)該指針執(zhí)行其他的如等待信號(hào)量、提交信號(hào)量等操作。
前面提到系統(tǒng)中的信號(hào)量如果不再使用了就應(yīng)該盡快刪除,否則分配多少個(gè)ECB也是不夠用的。信號(hào)量的刪除函數(shù)時(shí)OSSemDel。刪除一個(gè)信號(hào)量要涉及很多方面,因此OSSemDel并不簡(jiǎn)單。OSSemDel的參數(shù)是ECB指針pevent、整形的刪除選項(xiàng)opt和用來(lái)返回結(jié)果的指向整形的指針perr。其中,opt的值為OS_DEL_NO_PEND表示只有當(dāng)沒(méi)有任務(wù)等待該事件的時(shí)候才允許刪除,opt的值為OS_DEL_ALWAYS表示無(wú)論如何都允許刪除。OSSemDel程序如下所示:



可以單刀,刪除信號(hào)量比創(chuàng)建一個(gè)信號(hào)量更復(fù)雜,首先要進(jìn)行很多參數(shù)檢查,檢查傳遞來(lái)的參數(shù)的正確性。例如,是否是在中斷中刪除信號(hào)量、ECB的屬性是否是信號(hào)量等。
使用局部變量tasks_waiting來(lái)保存是否有任務(wù)等待信號(hào)量。判斷的方法是通過(guò)事件等待組是否為0.如果tasks_waiting=OS_TRUE,則表示有任務(wù)等待信號(hào)量,如果tasks_waiting=OS_FALSE,則表示沒(méi)有任務(wù)等待信號(hào)量。
然后根據(jù)選項(xiàng)opt決定程序的分支。如果為OS_DEL_NO_PEND,則表示只有在沒(méi)有事件等待的時(shí)候才允許刪除信號(hào)量,因此,在tasks_waiting = OS_TRUE時(shí)不能做任何事情,返回該ECB的指針,表示刪除失敗了,并在err中填寫了出錯(cuò)的原因。
如果opt為OS_DEL_ALWAYS,那么,先把ECB初始化后歸還給空閑ECB鏈表,然后將所有等待該信號(hào)量的任務(wù)都用OS_EventTaskRdy來(lái)就緒,采用的方法是使用while循環(huán),只要OSEventGrp不為0就循環(huán)下去,從高優(yōu)先級(jí)到低優(yōu)先級(jí)的任務(wù)一個(gè)一個(gè)就緒,事件等待表中的任務(wù)也一個(gè)一個(gè)減少。等到OSEventGrp為0時(shí)循環(huán)就結(jié)束了,所有等待該事件的任務(wù)除了被掛起的之外(OS_EventTaskRdy不就緒掛起的任務(wù)),全部都就緒了。這時(shí)如果判定tasks_waiting為OS_TRUE,知道有任務(wù)被就緒了,就執(zhí)行一次任務(wù)調(diào)度來(lái)讓高優(yōu)先級(jí)的就緒任務(wù)獲得運(yùn)行,否則不需要進(jìn)行任務(wù)調(diào)度了。
操作系統(tǒng)程序的編寫是非常細(xì)致的,如果opt不是這兩個(gè)值中的一個(gè),那就是選項(xiàng)不對(duì),什么也不做,標(biāo)記錯(cuò)誤信息后直接返回原來(lái)的ECB指針。
請(qǐng)求信號(hào)量又稱等待信號(hào)量。等待信號(hào)量的參數(shù)為3個(gè),分別是ECB的指針pevent,32位無(wú)符號(hào)整數(shù)超時(shí)時(shí)間timeout和用來(lái)返回結(jié)果的指向整形的指針perr。等待信號(hào)量函數(shù)OSSemPend的定義如下所示:



信號(hào)量的等待函數(shù)代碼稍多一些,讀懂了該代碼,其他的事件如互斥信號(hào)量、消息等的處理都很相似。
首先還是參數(shù)檢查,這里增加了一個(gè)如果調(diào)度器上鎖不能等待信號(hào)量的限制。perr是以指針的形式傳遞過(guò)來(lái)的,其實(shí)是用它來(lái)返回處理的結(jié)果。例如,OS_ERR_PEND_LOCKED,表示是因?yàn)檎{(diào)度器上鎖了而無(wú)功而返。
然后判斷OSEventCnt信號(hào)量的值,入股該值大于0,則可以訪問(wèn)資源。因?yàn)楸救蝿?wù)將占有一個(gè)資源,因此將OSEventCnt減1,信號(hào)量指示的資源數(shù)減少一個(gè)。然后給*perr賦值為OS_ERR_NONE,表示操作正常。然后本函數(shù)返回。應(yīng)用程序看到OS_ERR_NONE就可以大膽地去使用資源了。
如果不是,那就比較麻煩了!先在TCB中的OSTCBStat打個(gè)標(biāo)記,表示本任務(wù)的狀體是請(qǐng)求信號(hào)量。OSTCBStatPend賦值為OS_STAT_PEND_OK,等待狀態(tài)正常。把延時(shí)時(shí)間這個(gè)參數(shù)給OSTCBDly。
調(diào)用OS_EventTaskWait在事件等待表、等待組中占一個(gè)地方,在就緒表和就緒組中取消就緒標(biāo)志。然后執(zhí)行一次任務(wù)調(diào)度,徹底被阻塞掉。輪到其他任務(wù)運(yùn)行了。當(dāng)再運(yùn)行到此處的時(shí)候已經(jīng)發(fā)生了很多事情,本任務(wù)是不知道的。總之,任務(wù)被從阻塞態(tài)喚醒回到就緒態(tài),又獲得了運(yùn)行。查看OSTCBStatPend,如果是OS_STAT_PEND_OK,是由于等待的信號(hào)量有效(有其他任務(wù)釋放了信號(hào)量),因?yàn)楸救蝿?wù)在ECB的事件等待表中有記錄,所以被喚醒并得到了運(yùn)行,雖然經(jīng)歷磨難,但是還是可以去訪問(wèn)資源了。如果是OS_STAT_PEND_ABORT,在獲得信號(hào)量之前取消了等待,因此不能訪問(wèn)資源,在perr中填寫信號(hào)為OS_ERR_PEND_ABORT。如果是OS_STAT_PEND_TO或其他,表示超時(shí)了,時(shí)間到了還沒(méi)有得到信號(hào)量,表示失敗了,也不能訪問(wèn)資源!在perr中填寫信號(hào)為OS_ERR_TIMEOUT。另外需要注意的是,執(zhí)行了OS_EventTaskRemove,在事件等待表和事件等待組中清除了本任務(wù)的等待信息。
無(wú)論如何,請(qǐng)求信號(hào)量結(jié)束了,最后清理一下比較混亂的TCB中的狀態(tài)標(biāo)志和ECB指針,結(jié)束本函數(shù)的運(yùn)行。
當(dāng)任務(wù)A獲得信號(hào)量之后將信號(hào)量數(shù)字減1,然后就可以訪問(wèn)資源R。這時(shí),如果信號(hào)量的值為0,任務(wù)B如果也要訪問(wèn)資源R,必須等待信號(hào)量,因此將任務(wù)B阻塞。任務(wù)A在對(duì)資源的訪問(wèn)完成之后,應(yīng)將信號(hào)量的值加1。因?yàn)橘Y源已經(jīng)可以被其他的任務(wù)訪問(wèn)了,因此應(yīng)該將任務(wù)B喚醒,使任務(wù)B就緒。再?gòu)?fù)雜一些,訪問(wèn)資源的任務(wù)有2個(gè)以上,資源R可以同時(shí)被N個(gè)任務(wù)訪問(wèn),因此信號(hào)量的值在最開(kāi)始創(chuàng)建的時(shí)候應(yīng)該等于N。當(dāng)任務(wù)A訪問(wèn)信號(hào)量時(shí),信號(hào)量值變?yōu)镹-1,任務(wù)B又訪問(wèn),信號(hào)量等于N-2,當(dāng)?shù)贛個(gè)任務(wù)訪問(wèn)時(shí),信號(hào)量等于N-M。當(dāng)N-M=0時(shí),也就是當(dāng)N=M時(shí),如果第N+1個(gè)任務(wù)來(lái)訪問(wèn)資源R,那么它必須等待。當(dāng)任何一個(gè)任務(wù)(如第2個(gè))訪問(wèn)資源完成后,應(yīng)該喚醒第N+1個(gè)任務(wù),讓其他資源訪問(wèn)。當(dāng)?shù)贜+1個(gè)任務(wù)訪問(wèn)完成之后,因?yàn)闆](méi)有其他的任務(wù)等待信號(hào)量,只需要簡(jiǎn)單地將信號(hào)量值加1即可。
提交信號(hào)量的函數(shù)時(shí)OSSemPost,參數(shù)是信號(hào)量所在的ECB的指針。代碼如下所示:

代碼中首先進(jìn)行參數(shù)檢查,然后判斷是否有任務(wù)在等待該信號(hào)量。如果有,那么就喚醒阻塞中的最高優(yōu)先級(jí)的任務(wù),方法就是調(diào)用OS_EventTaskRdy,然后進(jìn)行任務(wù)調(diào)度之后返回即可。如果沒(méi)有,就簡(jiǎn)單地將信號(hào)量加1。
在中斷服務(wù)程序和有些用戶任務(wù)中,需要無(wú)等待的請(qǐng)求信號(hào)量。也就是說(shuō),使用信號(hào)量請(qǐng)求資源,當(dāng)沒(méi)有可用的資源,信號(hào)量為0時(shí),并不阻塞自己,而是繼續(xù)執(zhí)行其他代碼。OSSemAccept就是無(wú)等待的請(qǐng)求信號(hào)量函數(shù),參數(shù)是請(qǐng)求信號(hào)量的ECB指針,返回值是當(dāng)前信號(hào)量的數(shù)值。當(dāng)有有效的資源時(shí),返回值大于0,否則返回0.代碼如下所示:

代碼中首先進(jìn)行參數(shù)檢查,然后將信號(hào)量的值賦值給局部變量cnt,如果cnt>0說(shuō)明資源有效或信號(hào)量有效,因此將信號(hào)量的值減1,然后返回cnt,就可以訪問(wèn)資源的代碼了。如果函數(shù)返回值為0,說(shuō)明要么參數(shù)檢查失敗要么資源被其他任務(wù)占用而不能訪問(wèn),都不能執(zhí)行訪問(wèn)資源的代碼。
放棄等待信號(hào)量并非放棄本任務(wù)對(duì)信號(hào)量的等待。可以采用反證法:如果是放棄本任務(wù)對(duì)信號(hào)量的等待,那么本任務(wù)應(yīng)該處于阻塞狀態(tài),一個(gè)處于阻塞狀態(tài)的任務(wù)得不到運(yùn)行,怎么能執(zhí)行放棄等待信號(hào)量的代碼呢?因此,一定是放棄其他任務(wù)對(duì)一個(gè)信號(hào)量的等待。放棄等待信號(hào)量的第一個(gè)參數(shù)是ECB的指針。這個(gè)ECB必須是信號(hào)量的,如果不是則返回。如果這個(gè)ECB的事件等待表中沒(méi)有任務(wù)等待,那么也無(wú)須做什么操作。否則,根據(jù)第二個(gè)參數(shù)opt的值分兩種情況處理。一種是opt的值是宏OS_PEND_OPT_BROADCAST,那么就要將等待該信號(hào)量的所有任務(wù)就緒。另一種是opt的值是OS_PEND_OPT_NONE或其他值,只將等待該信號(hào)量的最高優(yōu)先級(jí)的任務(wù)就緒。另一個(gè)參數(shù)是返回結(jié)果的指向整形的指針perr,使用方法與前面類似。
放棄等待信號(hào)量函數(shù)OSSemPendAbort代碼如下所示:


分析該函數(shù)流程如下:
(1)參數(shù)檢查,如果ECB指針無(wú)效或ECB的類型不是信號(hào)量類型,返回參數(shù)檢查錯(cuò)誤信息。
(2)如果pevent->OSEventGrp為0說(shuō)明沒(méi)有任務(wù)等待信號(hào)量,返回0.
(3)否則根據(jù)參數(shù)opt(選項(xiàng))進(jìn)行分支轉(zhuǎn)移,如果為OS_PEND_OPT_BROADCAST,使用while語(yǔ)句循環(huán)地將等待該信號(hào)量的每個(gè)任務(wù)用OS_EventTaskRdy來(lái)取消等待并使其就緒(除非任務(wù)還被掛起);如果為其他值則只將最高優(yōu)先級(jí)取消等待并使之就緒。兩種情況下都返回取消等待信號(hào)量的任務(wù)數(shù)。
總之,OSSemPendAbort取消任務(wù)對(duì)某信號(hào)量的等待,操作的對(duì)象是ECB等待中的任務(wù)。一般在極為特殊的情況下(如要?jiǎng)h除一個(gè)任務(wù),而這個(gè)任務(wù)當(dāng)前在等待信號(hào)量時(shí)),才使用該函數(shù)。
操作系統(tǒng)提供了直接設(shè)置信號(hào)量值的函數(shù)OSSemSet。一般情況下無(wú)須使用該函數(shù)設(shè)置信號(hào)量的值,應(yīng)該在信號(hào)量創(chuàng)建的時(shí)候初始化信號(hào)量的值。當(dāng)一個(gè)信號(hào)量的值在創(chuàng)建之后為N,每次有任務(wù)請(qǐng)求信號(hào)量就將該值減1,反之,將該值加1,一般情況下是不允許隨便改動(dòng)的。但是在極其特殊的情況下,因?yàn)槟撤N特殊的需要(如突然增加了其他的資源),需要修改資源數(shù)N,可采用OSSemSet直接對(duì)信號(hào)量賦值,但條件是這時(shí)沒(méi)有任務(wù)在等待該信號(hào)量。OSSemset函數(shù)代碼如下所示:


該函數(shù)比較簡(jiǎn)單,進(jìn)行參數(shù)檢查之后,查看該信號(hào)的值是否大于0,如果大于0則說(shuō)明米有任務(wù)在等待該信號(hào)量,因此可以修改信號(hào)量值。否則,查看是否有任務(wù)等待,如果沒(méi)有任務(wù)等待仍可修改信號(hào)量值,否則不允許修改信號(hào)量的值。
信號(hào)量狀態(tài)查詢將ECB中關(guān)于信號(hào)量的信息復(fù)制到另一個(gè)數(shù)據(jù)結(jié)構(gòu)信號(hào)量數(shù)據(jù)OS_SEM_DATA,信號(hào)量數(shù)據(jù)OS_SEM_DATA的聲明如下所示:

信號(hào)量狀態(tài)查詢函數(shù)OSSemQuery的代碼如下所示:

該函數(shù)比較簡(jiǎn)單,進(jìn)行參數(shù)檢查之后,將ECB中的事件等待組、事件等待表和信號(hào)量值的內(nèi)容,完全復(fù)制到信號(hào)量數(shù)據(jù)OS_SEM_DATA中

55.png (14.45 KB, 下載次數(shù): 118)

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

使用道具 舉報(bào)

沙發(fā)
ID:56293 發(fā)表于 2013-10-25 10:51 | 只看該作者
請(qǐng)問(wèn)樓主的程序使用什么軟件打開(kāi)的?有顏色看的方便多了~
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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