日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【原创】ucos信号量的操作及原理

發(fā)布時(shí)間:2023/12/9 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【原创】ucos信号量的操作及原理 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

信號量的操作及原理

? 1.OSSemCreate創(chuàng)建信號量semaphore ? ? 在使用信號量之前,要先用OSSemCreate創(chuàng)建一個(gè)信號量,并通過返回的合法事件結(jié)構(gòu)體指針使用信號量。
  • OS_EVENT *OSSemCreate(INT16U cnt)
  • {
  • #if OS_CRITICAL_METHOD == 3 /* 原理請查看http://blog.csdn.net/liuhui_8989/article/details/8783323 */
  • OS_CPU_SR cpu_sr;
  • #endif
  • OS_EVENT *pevent;
  • if(OSIntNesting>0){/* 不能在中斷內(nèi)創(chuàng)建信號量 */
  • return((OS_EVENT *)0);/* 直接返回0 */
  • }
  • OS_ENTER_CRITICAL();
  • pevent =OSEventFreeList;/* 獲取空閑的事件控制塊 */
  • if(OSEventFreeList!=(OS_EVENT *)0){/* 將OSEventFreeList指向下一個(gè)事件控制塊 */
  • OSEventFreeList=(OS_EVENT *)OSEventFreeList->OSEventPtr;
  • }
  • OS_EXIT_CRITICAL();
  • if(pevent !=(OS_EVENT *)0){/* Get an event control block */
  • pevent->OSEventType= OS_EVENT_TYPE_SEM;
  • pevent->OSEventCnt= cnt;/* 設(shè)置計(jì)數(shù)器的初值 */
  • pevent->OSEventPtr=(void*)0;/* Unlink from ECB free list */
  • OS_EventWaitListInit(pevent);/* 初始化事件控制塊中任務(wù)等待表為0 */
  • }
  • return(pevent);
  • }
  • ? ? 簡而言之,如果沒有了空閑的事件控制塊或者是在中斷內(nèi)創(chuàng)建信號里,則返回?zé)o效的事件控制塊0;否則返回類型為信號量,任務(wù)等待表OSEventGrp和OSEventTbl[]為0,且已設(shè)置了計(jì)數(shù)器初值的事件控制塊指針。這樣便成功地創(chuàng)建了一個(gè)信號量。這里要注意,使用OSSemCreate函數(shù)返回的指針前,要檢驗(yàn)是否為有效的指針。 ? ? cnt的值至少為0。 ? ? 創(chuàng)建了信號量之后,便可以對信號量進(jìn)行如下操作了,申請、釋放、刪除、查詢信號量。 2. 信號量的申請和釋放
  • 申請:voidOSSemPend(OS_EVENT *pevent, INT16U timeout, INT8U *err)
  • 釋放:INT8U OSSemPost(OS_EVENT *pevent)
  • ? ??OSSemPend函數(shù)有三個(gè)參數(shù), ? ??第一個(gè)是一個(gè)指向事件控制塊的指針,該值為OSSemCreate返回值。 ? ??第二個(gè)是一個(gè)等待時(shí)間值(至少為0),如果信號量目前被占用,則無法立即申請到信號量,調(diào)用該函數(shù)的任務(wù)將被掛起,如果等待時(shí)間值為0,則一直被掛起直到信號量被釋放為止(OSSemPost能夠在釋放信號量的同時(shí),恢復(fù)等待信號量的任務(wù)),如果等待時(shí)間值大于0,則在超時(shí)時(shí)間過后,由OSTineTick恢復(fù)為就緒狀態(tài)的任務(wù)。 ? ? 第三個(gè)為一個(gè)指向錯(cuò)誤代碼的指針,該值作為函數(shù)返回值使用。
    ? ??OS_NO_ERR ? ? ? ? ??? ??? ??? ??函數(shù)調(diào)用成功,獲得了信號量。 ? ??OS_TIMEOUT ? ? ? ??? ??? ??? ??在規(guī)定的時(shí)間內(nèi)沒有申請到信號量 ? ??OS_ERR_EVENT_TYPE ??? ??事件類型錯(cuò)誤,不是信號量 ? ??OS_ERR_PEND_ISR ? ?? ??? ??不能在中斷內(nèi)申請信號量 ? ??OS_ERR_PEVENT_NULL? ??pevent指針無效 ? 下面講解一下函數(shù)內(nèi)部原理: ? ? 如果信號量的計(jì)數(shù)器值大于0,則將其減1,表示又有一個(gè)任務(wù)占用,并直接返回。 ? ? 如果信號量的計(jì)數(shù)器值為0,表示信號量已被其他任務(wù)占用,此時(shí)任務(wù)控制塊中的狀態(tài)標(biāo)志是等待信號狀態(tài)以及就緒的,因?yàn)槭褂玫氖前次换虿僮?#xff0c;保留了原有的就緒狀態(tài)標(biāo)志。
    ? ? 之后調(diào)用了OS_EventTaskWait(pevent); 此時(shí)作了3件事:
    ? ? (1)OSTCBCur->OSTCBEventPtr = pevent;將事件控制塊指針保存于任務(wù)控制塊中
    ? ? (2)去除任務(wù)在任務(wù)就緒表的就緒狀態(tài),注意沒有包括任務(wù)控制塊中的狀態(tài)標(biāo)志 ? ? (3)設(shè)置事件控制塊中的任務(wù)等待表
    ? ? 至此任務(wù)被掛起!通過OS_Sched運(yùn)行其他任務(wù)去了。
    ? ? 接下來的結(jié)果取決于,信號量是否在規(guī)定的等待時(shí)間內(nèi)被釋放。
    ? ? 在當(dāng)前任務(wù)被掛起,而運(yùn)行其他任務(wù)的同時(shí),每個(gè)時(shí)鐘節(jié)拍都會運(yùn)行OSTimeTick中斷函數(shù),此函數(shù)會遍歷所有任務(wù),如果任務(wù)控制塊中的狀態(tài)標(biāo)志為就緒的,且Dly等待值不為0,則將Dly減1,如果減1后剛好為0,則在任務(wù)就緒表中恢復(fù)該任務(wù)的就緒狀態(tài)!
    ? ? 如果該就緒狀態(tài)的任務(wù)恢復(fù)運(yùn)行,此時(shí)任務(wù)控制塊的狀態(tài)標(biāo)志仍為OS_STAT_SEM,運(yùn)行OS_EventTO,做的事剛好和OS_EventTaskWait相反。
    ? ??(1)OSTCBCur->OSTCBEventPtr = 0;
    ? ? (2)設(shè)置任務(wù)控制塊中的狀態(tài)標(biāo)志為就緒狀態(tài)(去除OS_STAT_SEM狀態(tài) ? ? (3)去除事件控制塊中的任務(wù)等待表 ? ? 此時(shí)返回OS_TIMEOUT。
    ? ? 但是如果在等待時(shí)間未過去,其他任務(wù)釋放了信號量,OSSemPost能夠在釋放信號量的同時(shí),恢復(fù)等待信號量的任務(wù)。等待信號量的任務(wù)恢復(fù)運(yùn)行,此時(shí)任務(wù)控制塊的狀態(tài)標(biāo)志不包含OS_STAT_SEM了,所以函數(shù)直接跳過第二個(gè)if語句,返回OS_NO_ERR。
    釋放信號量過程: ? ? 函數(shù)OSSemPost在對信號量的計(jì)數(shù)器操作之前,首先檢查任務(wù)等待表中是否還有其他等待該信號的任務(wù),如果沒有,就把計(jì)數(shù)器加1,如果有,則調(diào)用OS_EventTaskRdy將任務(wù)等待表中最高優(yōu)先級的任務(wù)設(shè)為就緒狀態(tài),并調(diào)用OSSched調(diào)度任務(wù)。
    ? 3. 應(yīng)用 3.1申請函數(shù)和釋放函數(shù)在同一任務(wù)中成對出現(xiàn) main: pevent = OSSemCreate(1);
    task1: OSSemPend(pevent, 0, err);
    .... OSSemPost(pevent); task2: OSSemPend(pevent, 0, err);
    .... OSSemPost(pevent); 當(dāng)一個(gè)任務(wù)沒有釋放信號量,另一個(gè)任務(wù)在申請信號量時(shí)只能掛起直到信號量釋放。 3.2 應(yīng)用程序中有一個(gè)函數(shù)Fun(),如果想使任務(wù)M必須經(jīng)過Y任務(wù)允許才能調(diào)用函數(shù)一次,可以使用信號量 main: pevent = OSSemCreate(0);
    task1: OSSemPend(pevent, 0, err);
    Fun(); task2: OSSemPost(pevent); 本文鏈接:http://www.cnblogs.com/cposture/p/4299055.html

    轉(zhuǎn)載于:https://www.cnblogs.com/cposture/p/4299055.html

    總結(jié)

    以上是生活随笔為你收集整理的【原创】ucos信号量的操作及原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。