久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

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

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:51773 發(fā)表于 2013-8-4 13:12 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
信號量在資源共享管理、任務(wù)同步與通信等方面都有廣泛的應(yīng)用。uC/OS-II單獨為信號量管理編寫了C語言文件os_sem.c。信號管理的核心函數(shù)如下所示:

信號量通過OSSemCreate創(chuàng)建,并分配一個ECB給該信號量。OSSemSet可以單獨設(shè)置信號量的計數(shù)值,這個值在ECB中。被創(chuàng)建的信號量可以通過OSSemDel來刪除。OSSemQuery查詢信號量的信息。這4種操作針對的對象是信號量,使用的數(shù)據(jù)結(jié)構(gòu)式ECB。
OSSemPend是任務(wù)請求信號量時執(zhí)行的操作。例如,請求操作串口、打印機或某共享數(shù)據(jù)結(jié)構(gòu),如果這時信號量無效,任務(wù)就被阻塞,并在ECB中標(biāo)記自己在等待。
OSSemPost是使用資源的任務(wù)由于資源使用結(jié)束而提交信號量,這時ECB中被阻塞的任務(wù)中優(yōu)先級最高的因為獲得了信號量,被喚醒回到就緒態(tài)。
OSSemAccept是任務(wù)無等待的請求信號量,也就是說,如果訪問的資源有效,那么就訪問;如果訪問的資源無效也不阻塞自己,而是去做其他工作。因此,OSSemAccept非常適用于中斷服務(wù)程序(ISR)。
OSSemPendAbort放棄某任務(wù)對信號量的等待,任務(wù)仍將被喚醒回到就緒態(tài)。
所以,以上4中函數(shù)的操作對象不僅包括事件控制塊(ECB),還將包括任務(wù)管理中如任務(wù)控制塊(TCB)、就緒表等諸多數(shù)據(jù)結(jié)構(gòu)。
信號量在操作系統(tǒng)初始化的時候并不存在。這時,操作系統(tǒng)中的事件管理數(shù)據(jù)結(jié)構(gòu)事件控制塊(ECB)為全空,所有的事件控制塊都在ECB空閑鏈表中排隊。信號量的建立函數(shù)OSSemCreate將使用一個并配置一個ECB,使其具備信號量的屬性。創(chuàng)建信號量的函數(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鏈表就為空。這說明已經(jīng)沒有空閑的ECB可供使用了。在這種情況下,當(dāng)然就不能創(chuàng)建信號量或任何其他的事件。當(dāng)將宏OS_MAX_EVENTS定義的太小滿足不了需要的時候就會出現(xiàn)這種情況。另外,還需要注意的是事件沒有用時要盡快釋放還給系統(tǒng)。在OSEventFreeList的值不為0的情況下,既然將空閑ECB鏈表的表頭分配給要創(chuàng)建的信號量事件,就需要將空閑ECB鏈表的第一個ECB取下來,這時OSEventList應(yīng)該指向第二個ECB。接下來的5條語句

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

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

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



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



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

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

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


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


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

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

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

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

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

使用道具 舉報

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

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: www.色.com| 成人精品一区二区三区中文字幕 | 精品成人在线视频 | 18性欧美| 国产精品 亚洲一区 | 久久视频精品在线 | 国产精品久久久久久久久久免费 | 91久久国产综合久久91精品网站 | 9久9久 | 999久久久| 国产传媒视频在线观看 | 视频一区在线观看 | 夜夜操天天操 | 久久最新 | 亚洲一区视频在线 | 色一阁 | 日本一区二区影视 | 中文字幕久久精品 | 黄色毛片在线观看 | 午夜理伦三级理论三级在线观看 | 久久中文字幕一区 | 午夜无码国产理论在线 | 91久久精品一区二区二区 | 免费中文字幕日韩欧美 | 欧美在线日韩 | 精品国产乱码久久久久久牛牛 | 中文字幕乱码一区二区三区 | 午夜精品久久久久99蜜 | 午夜av在线| 天天操综合网站 | 2019天天操| 国产精品永久免费视频 | japanhd美女动| 国产成人99久久亚洲综合精品 | 亚洲a一区二区 | 色久影院 | 亚洲视频一区二区三区 | 亚洲国产精品成人 | 狼色网| 97色在线观看免费视频 | 亚洲在线一区二区 |