99精品伊人亚洲|最近国产中文炮友|九草在线视频支援|AV网站大全最新|美女黄片免费观看|国产精品资源视频|精彩无码视频一区|91大神在线后入|伊人终合在线播放|久草综合久久中文

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

函數(shù)的可重入與線程安全有什么關(guān)系

汽車電子技術(shù) ? 來源:宅學部落 ? 作者: 王利濤 ? 2023-02-17 09:39 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

嵌入式裸機時代,也就是無OS時代,我們在裸機環(huán)境下編寫C語言程序非常簡單,實現(xiàn)一個函數(shù),然后將函數(shù)接口API提供給其它模塊調(diào)用就可以了。比如下面的函數(shù),我們實現(xiàn)一個sum函數(shù),用來求兩個數(shù)的和:

圖片

但是在一個運行OS的多任務環(huán)境中,我們在編寫sum函數(shù)時就要注意一些細節(jié)了:我們編寫的sum函數(shù)可能會被多個任務調(diào)用,而且可能在sum函數(shù)執(zhí)行的過程被打斷,接著在另一個任務中再次調(diào)用sum函數(shù)。而在上面的sum函數(shù)實現(xiàn)中,我們定義了一個靜態(tài)變量sum用來保存兩個數(shù)相加的臨時結(jié)果,靜態(tài)變量是保存到數(shù)據(jù)段中的,大家可以想一想,在一個任務A中正在執(zhí)行sum(1,2)函數(shù)中的第4行,此時任務被打斷掛起,接著運行任務B,在任務B中接著執(zhí)行sum(10,20)函數(shù),執(zhí)行結(jié)束后接著運行任務A,A獲得CPU控制權(quán)后繼續(xù)運行sum(1,2)的第5行,此時sum(1,2)的返回結(jié)果就變成了30,而不是正確結(jié)果3。

在一個多任務環(huán)境中,如果一個函數(shù)可以重復并發(fā)調(diào)用,而且多次調(diào)用并不會影響函數(shù)的運行結(jié)果,那么這個函數(shù)是可重入的,我們稱這個函數(shù)為:可重入函數(shù)。在上面的sum函數(shù)實現(xiàn)中,當其被多次并發(fā)調(diào)用時,函數(shù)的運行結(jié)果并不確定,我們稱其為不可重入函數(shù)。

我們?nèi)绾稳ヅ卸ㄒ粋€函數(shù)是可重入的,還是不可重入的呢?很簡單,當一個函數(shù)滿足下面任一條件,那么這個函數(shù)就是不可重入函數(shù)。

  • 函數(shù)內(nèi)部使用了全局變量
  • 函數(shù)內(nèi)部使用了靜態(tài)局部變量
  • 函數(shù)返回值為全局變量或靜態(tài)變量
  • 函數(shù)內(nèi)部使用了malloc/free函數(shù)
  • 函數(shù)北部使用了標準I/O函數(shù)
  • 函數(shù)內(nèi)部調(diào)用其它不可重入函數(shù)

不可重入函數(shù)在一個多任務環(huán)境中不能被多次并發(fā)調(diào)用,如果一個函數(shù)可能被多次調(diào)用,那么我們設計這個函數(shù)時盡量要將其設計為可重入函數(shù)。

  • 不使用/返回靜態(tài)變量、全局變量
  • 不使用標準I/O函數(shù)
  • 不使用malloc/free函數(shù)
  • 不調(diào)用不可重入函數(shù)

在函數(shù)設計時,只要注意上面的原則,那么我們就可以將一個函數(shù)設計為可重入函數(shù),可重入函數(shù)在多任務環(huán)境下可以被多次并發(fā)調(diào)用,是線程安全的,程序員可以放心大膽地調(diào)用。

理想很豐滿,現(xiàn)實很骨干。我們在編程中如果說不用malloc/free、全局變量,那是不現(xiàn)實的。只要我們使用了這些全局變量,靜態(tài)變量,那么函數(shù)就變成不可重入了,在多任務環(huán)境下使用這個函數(shù)就變得線程不安全了,那怎么辦呢?

方法還是有的,一個函數(shù)之所以變得不可重入,就是因為函數(shù)內(nèi)有一些資源是全局共享的,在多任務環(huán)境下多次并發(fā)調(diào)用該函數(shù)時可能會破壞掉這些共享的全局資源。我們?nèi)绻堰@些資源在訪問的時候保護起來,不讓其它任務訪問(即互斥訪問),即同一時刻只允許一個進程訪問就安全了。這些被保護的資源我們稱為臨界資源,訪問這些臨界資源的代碼段,我們稱之為臨界區(qū)。臨界區(qū)的訪問方式為互斥訪問,即同一時刻只允許一個進程訪問。

臨界區(qū)的實現(xiàn)方式有很多種,不同的操作系統(tǒng)可能會提供不同的實現(xiàn)方式。我們可以通過下面的操作原語來實現(xiàn)一個臨界區(qū):

  • EnterCriticalSection()
  • LeaveCriticalSection()

不同的操作系統(tǒng),具體的實現(xiàn)手段可能不一樣,常見的方法有:關(guān)中斷;實現(xiàn)互斥訪問,比如通過信號量、互斥量、自旋鎖等實現(xiàn),甚至原子操作等。比如在uc/os操作系統(tǒng)中,我們使用關(guān)中斷的方式來實現(xiàn)臨界區(qū),確保函數(shù)的線程安全。

圖片

而在linux/windows操作系統(tǒng)中,我們通常使用鎖機制來實現(xiàn)臨界區(qū):

圖片

在一個不可重入函數(shù)中,通過臨界區(qū)來實現(xiàn)共享全局資源的互斥訪問,那么在多任務環(huán)境下調(diào)用這個函數(shù)也就變得安全了,也就是說這個不可重入函數(shù)是線程安全的。

通過上面的分析,我們可以得出下面的結(jié)論:一個函數(shù)如果是可重入函數(shù),那么這個函數(shù)是線程安全的,其它進程線程都可以對這個函數(shù)并發(fā)訪問,并不會影響函數(shù)的運行結(jié)果。如果一個函數(shù)是不可重入函數(shù),我們通過臨界區(qū)設計對共享全局資源進行互斥訪問,也可以讓這個函數(shù)變得線程安全,其它進程線程也可以放心調(diào)用。由此,我們得出線程安全與可重入之間的關(guān)系如下:

圖片

也就是說,一個可重入函數(shù)肯定是線程安全的,而線程安全函數(shù)并不一定是可重入函數(shù),不可重入函數(shù)也有可能是線程安全的,比如我們常見的malloc函數(shù),就是不可重入函數(shù),但是是線程安全的,為什么呢?

通過《C語言嵌入式Linux高級編程》課程學習,我們已經(jīng)知道,對于我們使用malloc/free申請釋放的內(nèi)存,glibc在用戶空間實現(xiàn)了一個內(nèi)存管理器,將各個大小的內(nèi)存塊鏈成多個全局鏈表進行管理。

圖片

當我們使用malloc/free申請釋放內(nèi)存時,如果申請/釋放的內(nèi)存塊大小符合規(guī)定,一般都是直接對這些全局鏈表進行操作、避免多次系統(tǒng)調(diào)用進入內(nèi)核態(tài),減少系統(tǒng)開銷。因為malloc/free函數(shù)對全局鏈表進行了操作,所以malloc/free是不可重入函數(shù)。在訪問這些全局鏈表時,我們需要通過鎖機制加以保護,每次malloc/free操作全局鏈表時,其它地方就被互斥訪問了,只有當malloc/free操作全局鏈表完成退出,其它地方的malloc/free才能對這個全局鏈表進行訪問。

通過上面的分析,我們可以看到:malloc/free雖然是不可重入函數(shù),但是通過加鎖對共享全局資源的互斥訪問,也就變得線程安全了,在多任務環(huán)境下,每個進程都可以放心大膽地調(diào)用它:因為malloc雖然是不可重入函數(shù),但它是線程安全的。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 嵌入式
    +關(guān)注

    關(guān)注

    5149

    文章

    19651

    瀏覽量

    317219
  • C語言
    +關(guān)注

    關(guān)注

    180

    文章

    7632

    瀏覽量

    141537
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4379

    瀏覽量

    64780
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    Keil C51處理科重入函數(shù)問題的探討

    在程序設計中,變量具體可以分為四種類型: 全局變量 ,靜態(tài)全局變量,局部變量,靜態(tài)局部變量。這幾種變量類型對函數(shù)重入產(chǎn)生的重大的影響,因為不同的編譯器采用不同的策略。 針對51的存儲區(qū)有
    發(fā)表于 04-22 21:40

    調(diào)用非安全線程的dll的問題

    在調(diào)用非線程安全的dll時,是不是要選擇在UI線程中運行?是不是還必須用不可重入的子VI封裝一下?上述的兩步是不是都要做?這些問題不是很清楚,還請各位大神指點一下
    發(fā)表于 03-14 21:13

    我想問如果我異步調(diào)用重入 參數(shù)是X80會怎么樣

    這個問題 因為我感覺里面有的地方很怪異,我在這些線程里用了全局變量 存了這個重入的VI的停止事件引用在別的地方去調(diào)用 停止它 就有時候 感覺并不能停止掉 關(guān)閉工程文件時候說是有線程
    發(fā)表于 06-06 19:38

    用ERTM關(guān)閉全局中斷來實現(xiàn)函數(shù)重入性有什么附加影響?

    在編程中,用ERTM關(guān)閉全局中斷來實現(xiàn)函數(shù)重入性有什么附加影響?
    發(fā)表于 08-09 11:12

    重入函數(shù)相關(guān)資料推薦

    數(shù)碼管點亮時間約為1~2ms。在數(shù)碼管數(shù)字變化時,先熄滅再更新數(shù)據(jù),稱為消隱。using 0 是第0組寄存器;reentrant聲明的函數(shù)重入函數(shù)。
    發(fā)表于 01-11 07:37

    函數(shù)對FFT有什么影響?他們是什么關(guān)系

    函數(shù)對FFT有什么影響?他們是什么關(guān)系?在visualStudio軟建中,要對音頻信號進行FFT變換時,需要加窗函數(shù)進行控制,這是為什么?窗函數(shù)對FFT有什么影響?窗
    發(fā)表于 11-30 06:24

    Linux 多線程重入函數(shù)

    的相互影響,如果一個函數(shù)在多線程并發(fā)的環(huán)境中每次被調(diào)用產(chǎn)生的結(jié)果是不確定的,我們就說這個函數(shù)是"不可重入的"/"線程
    發(fā)表于 05-16 17:41 ?1062次閱讀

    重入函數(shù)與不可重入函數(shù)分析

    導致不可預料的后果。那么什么是重入函數(shù)呢?所謂重入函數(shù)是指一個可以被多個任務調(diào)用的過程,任務
    發(fā)表于 04-02 14:43 ?977次閱讀

    51單片機的重入函數(shù)有什么陷阱

    函數(shù)一旦定義為重入, 參數(shù)就會通過堆棧傳遞。 不要忘記的是, 局部變量也會在堆棧上分配。 更不能忽略的是, 51的堆??臻g大小是在2^8以內(nèi)的, 所以堅決不能在
    發(fā)表于 08-20 17:31 ?0次下載
    51單片機的<b class='flag-5'>可</b><b class='flag-5'>重入</b><b class='flag-5'>函數(shù)</b>有什么陷阱

    重入和不可重入函數(shù)的詳細資料和應用簡介

    重入一般可以理解為一個函數(shù)在同時多次調(diào)用,例如操作系統(tǒng)在進程調(diào)度過程中,或者單片機、處理器等的中斷的時候會發(fā)生重入的現(xiàn)象。一般浮點運算都是由專門的硬件來完成,舉個例子假設有個硬件寄存器名字叫做FLOAT,用來計算和存放浮點數(shù)的中
    發(fā)表于 08-02 17:34 ?0次下載
    <b class='flag-5'>可</b><b class='flag-5'>重入</b>和不可<b class='flag-5'>重入</b><b class='flag-5'>函數(shù)</b>的詳細資料和應用簡介

    KEIL C51的重入函數(shù)的詳細資料講解

    重入函數(shù),又叫再入函數(shù),是一種可以在函數(shù)體內(nèi)不直接或間接調(diào)用其自身的一種函數(shù)。再入函數(shù)可被遞歸調(diào)
    發(fā)表于 08-01 17:35 ?0次下載
    KEIL C51的<b class='flag-5'>重入</b><b class='flag-5'>函數(shù)</b>的詳細資料講解

    Linux中的重入、異步信號安全線程安全

    下文是在看csapp的時候引發(fā)的一些思考,其實之前看anup的時候也有所了解,不過時間有點長了,所以有點忘記了,當再次在csapp看到這部分內(nèi)容的時候有了更多的理解。 重入函數(shù) 當一個被捕獲的信號
    的頭像 發(fā)表于 11-10 14:45 ?1533次閱讀
    Linux中的<b class='flag-5'>可</b><b class='flag-5'>重入</b>、異步信號<b class='flag-5'>安全</b>和<b class='flag-5'>線程</b><b class='flag-5'>安全</b>

    為什么中斷處理函數(shù)不能直接調(diào)用不可重入函數(shù)

    中斷丟失和系統(tǒng)位置錯誤,這里直接導致嵌入式 linux 系統(tǒng)應用進程中的所有線程停掉,進而導致看門狗進程得不到喂狗,設備重啟。 那什么是不可重入函數(shù)呢? 為什么中斷處理函數(shù)不能直接調(diào)用
    的頭像 發(fā)表于 02-17 09:33 ?6422次閱讀

    &quot;重入&quot;和&quot;線程安全&quot;是兩個概念 千萬不要搞混了

    ? ? 今天的這篇文章應該可以幫助你解決一大部分問題。 ? 01 兩個概念 1、重入函數(shù)?? 多任務系統(tǒng)中每個進程或線程都是由多種執(zhí)行流并發(fā)運行的,當執(zhí)行流同時進入同一個
    的頭像 發(fā)表于 02-10 17:38 ?3470次閱讀
    &quot;<b class='flag-5'>可</b><b class='flag-5'>重入</b>&quot;和&quot;<b class='flag-5'>線程</b><b class='flag-5'>安全</b>&quot;是兩個概念 千萬不要搞混了

    CPU的核心數(shù)和線程數(shù)有什么關(guān)系

    1 概念 1.1 背景 當看到以下一些名詞,你是否感到過疑惑:他們之間到底有什么關(guān)系? CPU核心數(shù)、線程數(shù)、處理器數(shù)量、每個處理器的內(nèi)核數(shù)量、處理器內(nèi)核總數(shù)、邏輯核數(shù)… 在安裝linux虛擬機
    的頭像 發(fā)表于 11-24 16:22 ?9035次閱讀
    CPU的核心數(shù)和<b class='flag-5'>線程</b>數(shù)有<b class='flag-5'>什么關(guān)系</b>