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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

ucos中的三种临界区管理机制

發(fā)布時(shí)間:2024/4/18 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ucos中的三种临界区管理机制 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
熟悉ucos,或者讀過Jean.J.Labrosse寫過的ucos書籍的人,一定會(huì)知道ucos中著名的臨界去管理宏:OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()。

同樣是通過關(guān)中斷來(lái)保護(hù)臨界區(qū),OS_ENTER_CRITICAL/OS_EXIT_CRITICAL一共實(shí)現(xiàn)了三種實(shí)現(xiàn)方式,如下所示:

[cpp]?view plaincopyprint?
  • #if?OS_CRITICAL_METHOD?==?1??
  • #define?OS_ENTER_CRITICAL()?__asm__("cli")??
  • #define?OS_EXIT_CRITICAL()?__asm__("sti")??
  • #endif??
  • ??
  • #if?OS_CRITICAL_METHOD?==?2??
  • #define?OS_ENTER_CRITICAL()?__asm__("pushf?\n\t?cli")??
  • #define?OS_EXIT_CRITICAL()?__asm__("popf")??
  • #endif??
  • ??
  • #if?OS_CRITICAL_METHOD?==?3??
  • #define?OS_ENTER_CRITICAL()?(cpu_sr?=?OSCPUSaveSR())??
  • #define?OS_EXIT_CRITICAL()?(OSCPURestoreSR(cpu_sr))??
  • #endif??
  • ?? 第一種方式,OS_ENTER_CRITICAL()簡(jiǎn)單地關(guān)中斷,OS_EXIT_CRITICAL()簡(jiǎn)單地開中斷。這種方式雖然簡(jiǎn)單高效,但無(wú)法滿足嵌套的情況。如果有兩層臨界區(qū)保護(hù),在退出內(nèi)層臨界區(qū)時(shí)就會(huì)開中斷,使外層的臨界區(qū)也失去保護(hù)。雖然ucos的內(nèi)核寫的足夠好,沒有明顯嵌套臨界區(qū)的情況,但誰(shuí)也無(wú)法保證一定沒有,無(wú)法保證今后沒有,無(wú)法保證在附加的驅(qū)動(dòng)或什么位置沒有,所以基本上第一種方法是沒有人用的。

    ?? 第二種方式,OS_ENTER_CRITICAL()會(huì)在關(guān)中斷前保存之前的標(biāo)志寄存器內(nèi)容到堆棧中,OS_EXIT_CRITICAL()從堆棧中恢復(fù)之前保存的狀態(tài)。這樣就允許了臨界區(qū)嵌套的情況。但現(xiàn)在看來(lái),這種方法還存在很大的問題,甚至?xí)霈F(xiàn)致命的漏洞。

    ????? 在OS_CRITICAL_METHOD=2的情況下,假設(shè)有如下代碼:

    [cpp]?view plaincopyprint?
  • function_a()??
  • {??
  • ?????int?a=(1<<31);??
  • ?????OS_ENTER_CRITICAL();??
  • ?????function_b(a);??
  • ?????OS_EXIT_CRITICAL();??
  • ???????
  • }??
  • ?? 會(huì)出現(xiàn)什么情況?在我的實(shí)驗(yàn)中,OS_EXIT_CRITICAL()之后,會(huì)出現(xiàn)處理器異常。為什么會(huì)出現(xiàn)處理起異常,讓我來(lái)模擬一下它的匯編代碼。之所以是模擬,并非是我虛構(gòu)數(shù)據(jù),而是因?yàn)槲覍?shí)際碰到問題的函數(shù)復(fù)雜一些,理解起來(lái)就需要更多的代碼。而這個(gè)問題是有普遍意義的,所以請(qǐng)?jiān)试S我來(lái)淺顯地揭示這個(gè)隱藏的bug。

    [cpp]?view plaincopyprint?
  • function_a:??
  • ?????push?ebp??
  • ?????mov?ebp,?esp??
  • ?????sub?esp,?8??
  • ?????mov?4(esp),?0x80000000??
  • ?????pushfd??
  • ?????cli??
  • ?????mov?edi,?4(esp)??
  • ?????mov?(esp),?edi??
  • ?????call?function_b??
  • ????popfd??
  • ????mov?esp,?ebp??
  • ????ret??
  • ??? 這是參照了gcc編譯結(jié)果的匯編模擬,無(wú)論是否加優(yōu)化選項(xiàng)這一問題都存在。這個(gè)問題的起因很簡(jiǎn)單,gcc想聰明一點(diǎn),一次把堆棧降個(gè)夠,然后它就可以在棧上隨意放參數(shù)去調(diào)用其他函數(shù)。尤其是在調(diào)用函數(shù)較多的時(shí)候,這種做法就更有意義。而且,gcc這種聰明與優(yōu)化選項(xiàng)O好像沒有太大關(guān)系,好像沒有什么能禁止它這么做。但問題是,gcc不知道我們的OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()是操作了堆棧的,我嘗試過使用__asm__ __volatile__("pushfd \n\tcli":::"memory")來(lái)通知gcc內(nèi)存數(shù)據(jù)改變了,但顯然gcc不認(rèn)為堆棧也改變了。于是,OS_ENTER_CRITICAL()保存在棧上的狀態(tài)就被沖掉了,比如被這里調(diào)用參數(shù)a的值。在恢復(fù)時(shí),是否會(huì)引發(fā)異常,會(huì)引發(fā)什么異常,這個(gè)就要靠運(yùn)氣了。但我相信一個(gè)人的運(yùn)氣不會(huì)總是那么好的,所以最后別使用OS_CRITICAL_METHOD=2。


    ??? 第三種,在關(guān)中斷前,使用局部變量保存中斷狀態(tài)。這也是幾乎所有實(shí)時(shí)操作系統(tǒng)共有的選擇。但ucos是一朵奇葩,為了兼容前兩種方式,OS_ENTER_CRITICAL()/ OS_EXIT_CRITICAL()宏定義并沒有提供傳遞狀態(tài)參數(shù)的功能。所以它的臨界去必須這么用:

    [cpp]?view plaincopyprint?
  • function_a()??
  • {??
  • #if?OS_CRITICAL_METHOD?==?3??
  • ????int?cpu_sr;??
  • #endif??
  • ??????int?a?=?1<<31;??
  • ??????OS_ENTER_CRITICAL();??
  • ??????function_b(a);??
  • ??????OS_EXIT_CRITICAL();??
  • }??
  • 這種代碼怎么看怎么別扭,可能是因?yàn)樵诤瘮?shù)體內(nèi)加了宏定義吧。然后,第三種方法對(duì)同一個(gè)函數(shù)體內(nèi)的嵌套臨界區(qū)無(wú)法支持,這在一些很長(zhǎng)大的函數(shù)中使用時(shí)或許會(huì)造成一定困擾。



    ??? 好吧,如果有了問題,就要有解決方案,畢竟我不是為了讓大家對(duì)ucos失去信心的。我們可以參考下一般的實(shí)時(shí)操作系統(tǒng)是如何實(shí)現(xiàn)關(guān)中斷臨界區(qū)的,就是以顯式的方式用局部變量保存中斷狀態(tài)。

    [cpp]?view plaincopyprint?
  • int?int_lock()??
  • {??
  • ???int?cpu_sr;??
  • ????__asm__?__volatile__("pushfd?\n\t?pop?%0\n\t?cli":"=r"(cpu_sr));??
  • ????return?cpu_sr;??
  • }??
  • ??
  • void?int_unlock(int?cpu_sr)??
  • {??
  • ?????__asm__?__volatile__("push?%0\n\t?popfd"::"r"(cpu_sr));??
  • }??
  • ??
  • function_a()??
  • {??
  • ???int?a,?cpu_sr;??
  • ???a=1<<31;??
  • ???cpu_sr?=?int_lock();??
  • ???function_b(a);??
  • ???int_unlock(cpu_sr);??
  • }??

  • ?? int_lock()和int_unlock()的可以用匯編更高效地實(shí)現(xiàn),也可以選擇只恢復(fù)中斷標(biāo)志的狀態(tài)。這種方法讓我們顯示地管理狀態(tài)保存的情況,我覺得至少要比宏定義清楚多了。

    總結(jié)

    以上是生活随笔為你收集整理的ucos中的三种临界区管理机制的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

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