欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一篇文章帶你了解C語(yǔ)言函數(shù)的可重入性

 更新時(shí)間:2021年08月25日 11:47:14   作者:zhuimeng_ruili  
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言函數(shù)的可重入性,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

一、不可重入函數(shù)。

在函數(shù)中如果我們使用靜態(tài)變量了,導(dǎo)致產(chǎn)生中斷調(diào)用別的函數(shù)的 過(guò)程中可能還會(huì)調(diào)用這個(gè)函數(shù),于是原來(lái)的 靜態(tài)變量被在這里改變了,然后返回主體函數(shù),用著的那個(gè)靜態(tài)變量就被改變了,導(dǎo)致錯(cuò)誤。這類函數(shù)我們稱為不可重入函數(shù)。

在 嵌入式系統(tǒng)的設(shè)計(jì)中,經(jīng)常會(huì)出現(xiàn)多個(gè)任務(wù)調(diào)用同一個(gè)函數(shù)的情況。如果這個(gè)函數(shù)不幸被設(shè)計(jì)成為不可重入的函數(shù)的話,那么不同任務(wù)調(diào)用這個(gè)函數(shù)時(shí)可能修改其他任 務(wù)調(diào)用這個(gè)函數(shù)的數(shù)據(jù),從而導(dǎo)致不可預(yù)料的后果。

不可重入函數(shù)在實(shí)時(shí)系統(tǒng)設(shè)計(jì)中被視為不安全函數(shù)。

 滿足下列條件的函數(shù)多數(shù)是不可重入的:

(1)函數(shù)體內(nèi)使用了靜態(tài)的數(shù)據(jù)結(jié)構(gòu);

(2)函數(shù)體內(nèi)調(diào)用了malloc()或者free()函數(shù);

(3)函數(shù)體內(nèi)調(diào)用了標(biāo)準(zhǔn)I/O函數(shù)。

(4)函數(shù)體內(nèi)調(diào)用了不可中斷的硬件寄存器,如串口收發(fā)寄存器

二、可重入函數(shù)。

可重入函數(shù)可以被一個(gè)以上的任務(wù)調(diào)用,而不必?fù)?dān)心數(shù)據(jù)被破壞??芍厝牒瘮?shù)任何時(shí)候都可以被中斷,一段時(shí)間以后又可以運(yùn)行,而相應(yīng)的數(shù)據(jù)不會(huì)丟失。

可重入函數(shù)或者只使用局部變量,即保存在CPU寄存器中或堆棧中;或者使用全局變量,則要對(duì)全局變量予以保護(hù)。

若一個(gè)函數(shù)是可重入的,則該函數(shù)必須滿足一下必要條件:

1、不能含有靜態(tài)(全局)非常量數(shù)據(jù)。

2、不能返回靜態(tài)(全局)非常量數(shù)據(jù)的地址。

3、只能處理由調(diào)用者提供的數(shù)據(jù)。作為可重入函數(shù)的輸入?yún)?shù),只能由調(diào)用者提供,而且所提供的輸入數(shù)據(jù)必須滿足上面兩點(diǎn)要求

4、不能依賴于單實(shí)例模式資源的鎖。

5、不能調(diào)用不可重入的函數(shù)。 函數(shù)內(nèi)部,盡量不能用 malloc 和 free 之類的方法進(jìn)行內(nèi)存分配和釋放,如果使用,一般情況下會(huì)造成該函數(shù)的不可重入

三、如何寫出可重入的函數(shù)

1、在寫函數(shù)時(shí)候盡量使用局部變量(例如寄存器、堆棧中的變量)。不訪問(wèn)那些全局變量,不使用靜態(tài)局部變量

2、如果確實(shí)需要訪問(wèn)全局變量(包括static),一定要注意實(shí)施互斥手段。可重入函數(shù)在并行運(yùn)行環(huán)境中非常重要,但是一般要為訪問(wèn)全局變量付出一些性能代價(jià)。編寫可重入函數(shù)時(shí),若使用全局變量,則應(yīng)通過(guò)關(guān)中斷、信號(hào)量(即P、V操作)等手段對(duì)其加以保護(hù)。

四、函數(shù)的可重入性和線程安全的關(guān)系

可重入與線程安全兩個(gè)概念都關(guān)系到函數(shù)處理資源的方式。但是,他們有一定的區(qū)別??芍厝敫拍顣?huì)影響函數(shù)的外部接口,而線程安全只關(guān)心函數(shù)的實(shí)現(xiàn)。

大多數(shù)情況下,要將不可重入函數(shù)改為可重入的,需要修改函數(shù)接口,使得所有的數(shù)據(jù)都通過(guò)函數(shù)的調(diào)用者提供。要將非線程安全的函數(shù)改為線程安全的,則只需要修改函數(shù)的實(shí)現(xiàn)部分。一般通過(guò)加入同步機(jī)制以保護(hù)共享的資源,使之不會(huì)被幾個(gè)線程同時(shí)訪問(wèn)。

線程安全與可重入性是兩個(gè)不同性質(zhì)的概念。

可重入是在單線程操作系統(tǒng)背景下,重入的函數(shù)或者子程序,按照后進(jìn)先出的線性序依次執(zhí)行完畢。多線程執(zhí)行的函數(shù)或子程序,各個(gè)線程的執(zhí)行時(shí)機(jī)是由操作系統(tǒng)調(diào)度,不可預(yù)期的,但是該函數(shù)的每個(gè)執(zhí)行線程都會(huì)不時(shí)的獲得CPU的時(shí)間片,不斷向前推進(jìn)執(zhí)行進(jìn)度。

可重入函數(shù)未必是線程安全的;線程安全函數(shù)未必是可重入的。例如,一個(gè)函數(shù)打開某個(gè)文件并讀入數(shù)據(jù)。這個(gè)函數(shù)是可重入的,因?yàn)樗亩鄠€(gè)實(shí)例同時(shí)執(zhí)行不會(huì)造成沖突;但它不是線程安全的,因?yàn)樵谒x入文件時(shí)可能有別的線程正在修改該文件,為了線程安全必須對(duì)文件加“同步鎖”。

函數(shù)在它的函數(shù)體內(nèi)部訪問(wèn)共享資源使用了加鎖、解鎖操作,所以它是線程安全的,但是卻不可重入。因?yàn)槿粼摵瘮?shù)一個(gè)實(shí)例運(yùn)行到已經(jīng)執(zhí)行加鎖但未執(zhí)行解鎖時(shí)被停下來(lái),系統(tǒng)又啟動(dòng)該函數(shù)的另外一個(gè)實(shí)例,則新的實(shí)例在加鎖處將轉(zhuǎn)入等待。如果該函數(shù)是一個(gè)中斷處理服務(wù),在中斷處理時(shí)又發(fā)生新的中斷將導(dǎo)致資源死鎖。

五、malloc和printf為什么不可重入

malloc和printf通常使用全局結(jié)構(gòu),并在內(nèi)部使用基于鎖的同步。這就是為什么它們不可重入。

malloc函數(shù)可以是線程安全的,也可以是線程不安全的。兩者都不可重入:

malloc在全局堆上操作,同時(shí)發(fā)生的兩個(gè)不同的malloc調(diào)用可能返回相同的內(nèi)存塊。(第二個(gè)malloc調(diào)用應(yīng)該在獲取塊的地址之前發(fā)生,但塊沒有標(biāo)記為不可用)。這違反了malloc的后置條件,因此此實(shí)現(xiàn)不會(huì)重新進(jìn)入。

printf函數(shù)也對(duì)全局?jǐn)?shù)據(jù)進(jìn)行操作。任何輸出流通常都使用一個(gè)附加到資源數(shù)據(jù)的全局緩沖區(qū)(用于終端或文件的緩沖區(qū))。打印過(guò)程通常是將數(shù)據(jù)復(fù)制到緩沖區(qū),然后刷新緩沖區(qū)的序列。

總結(jié)

本篇文章就到這里了,希望能給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • c語(yǔ)言10個(gè)經(jīng)典小程序

    c語(yǔ)言10個(gè)經(jīng)典小程序

    c語(yǔ)言的經(jīng)典程序,學(xué)習(xí)c語(yǔ)言的初學(xué)者可以參考下
    2013-01-01
  • C語(yǔ)言實(shí)現(xiàn)通用數(shù)據(jù)結(jié)構(gòu)之通用映射(HashMap)

    C語(yǔ)言實(shí)現(xiàn)通用數(shù)據(jù)結(jié)構(gòu)之通用映射(HashMap)

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)通用數(shù)據(jù)結(jié)構(gòu)之通用映射,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • 二叉樹遍歷 非遞歸 C++實(shí)現(xiàn)代碼

    二叉樹遍歷 非遞歸 C++實(shí)現(xiàn)代碼

    對(duì)于二叉樹,有前序、中序以及后序三種遍歷方法。因?yàn)闃涞亩x本身就是遞歸定義,因此采用遞歸的方法去實(shí)現(xiàn)樹的三種遍歷不僅容易理解而且代碼很簡(jiǎn)潔。而對(duì)于樹的遍歷若采用非遞歸的方法,就要采用棧去模擬實(shí)現(xiàn)
    2013-09-09
  • C語(yǔ)言string庫(kù)strcpy、strcmp、strcat函數(shù)的使用

    C語(yǔ)言string庫(kù)strcpy、strcmp、strcat函數(shù)的使用

    這篇文章主要介紹了C語(yǔ)言string庫(kù)strcpy、strcmp、strcat函數(shù)的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • C++ 名稱空間詳情

    C++ 名稱空間詳情

    當(dāng)一個(gè)項(xiàng)目變得大型之后,我們會(huì)引入很多的庫(kù),這么一來(lái)兩個(gè)庫(kù)很可能會(huì)定義List、Tree、Node同名的類,編譯器要是不考慮這情況的話,程序員調(diào)用時(shí)就會(huì)出現(xiàn)沖突問(wèn)題。C++提供了名稱空間工具,以更好的控制名稱的作用域,本文就來(lái)談?wù)凜++ 名稱空間,需要的朋友可以參考一下
    2021-09-09
  • 解析四則表達(dá)式的編譯過(guò)程及生成匯編代碼

    解析四則表達(dá)式的編譯過(guò)程及生成匯編代碼

    本篇文章是對(duì)四則表達(dá)式的編譯過(guò)程及生成匯編代碼進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-06-06
  • C語(yǔ)言數(shù)字圖像處理之直方圖均衡化

    C語(yǔ)言數(shù)字圖像處理之直方圖均衡化

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言數(shù)字圖像處理之直方圖均衡化,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • C語(yǔ)言實(shí)現(xiàn)學(xué)生檔案管理系統(tǒng)

    C語(yǔ)言實(shí)現(xiàn)學(xué)生檔案管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)學(xué)生檔案管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • C語(yǔ)言鏈表案例學(xué)習(xí)之通訊錄的實(shí)現(xiàn)

    C語(yǔ)言鏈表案例學(xué)習(xí)之通訊錄的實(shí)現(xiàn)

    為了將所學(xué)到的鏈表的知識(shí)進(jìn)行鞏固學(xué)習(xí),做到學(xué)以致用,本文將利用鏈表制作一個(gè)簡(jiǎn)單的通訊錄。文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2022-10-10
  • C語(yǔ)言實(shí)現(xiàn)紅黑樹的實(shí)例代碼

    C語(yǔ)言實(shí)現(xiàn)紅黑樹的實(shí)例代碼

    這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)紅黑樹的實(shí)例代碼,有需要的朋友可以參考一下
    2013-12-12

最新評(píng)論