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

標題: uC/OS-II學習筆記—信號量管理 [打印本頁]

作者: xueren    時間: 2013-8-4 13:12
標題: uC/OS-II學習筆記—信號量管理
信號量在資源共享管理、任務同步與通信等方面都有廣泛的應用。uC/OS-II單獨為信號量管理編寫了C語言文件os_sem.c。信號管理的核心函數如下所示:

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

首先,如果是在中斷服務程序中,那么中斷服務程序按照規范,應該先調用OSIntEnter,該函數將中斷嵌套數OSIntNesting加1,因此只要是在中斷服務中調用OSSemCreate,OSIntNesting>0u就應該成立,OSSemCreate就返回。OSEventFreeList指向ECB空閑鏈表的表頭,如果OSEventFreeList的值是0,即空指針,那么ECB鏈表就為空。這說明已經沒有空閑的ECB可供使用了。在這種情況下,當然就不能創建信號量或任何其他的事件。當將宏OS_MAX_EVENTS定義的太小滿足不了需要的時候就會出現這種情況。另外,還需要注意的是事件沒有用時要盡快釋放還給系統。在OSEventFreeList的值不為0的情況下,既然將空閑ECB鏈表的表頭分配給要創建的信號量事件,就需要將空閑ECB鏈表的第一個ECB取下來,這時OSEventList應該指向第二個ECB。接下來的5條語句

都是對取得的ECB進行賦值。假設信號量值為5,則賦值后的ECB應該如下圖所示:

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

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



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



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

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

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


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


該函數比較簡單,進行參數檢查之后,查看該信號的值是否大于0,如果大于0則說明米有任務在等待該信號量,因此可以修改信號量值。否則,查看是否有任務等待,如果沒有任務等待仍可修改信號量值,否則不允許修改信號量的值。
信號量狀態查詢將ECB中關于信號量的信息復制到另一個數據結構信號量數據OS_SEM_DATA,信號量數據OS_SEM_DATA的聲明如下所示:

信號量狀態查詢函數OSSemQuery的代碼如下所示:

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

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

55.png

作者: 有bear來~    時間: 2013-10-25 10:51
請問樓主的程序使用什么軟件打開的?有顏色看的方便多了~




歡迎光臨 (http://www.raoushi.com/bbs/) Powered by Discuz! X3.1