主頁 >  其他 > Linux 可重入、異步信號安全和執行緒安全

Linux 可重入、異步信號安全和執行緒安全

2020-11-10 23:12:12 其他

可重入函式

當一個被捕獲的信號被一個行程處理時,行程執行的普通的指令序列會被一個信號處理器暫時地中斷,它首先執行該信號處理程式中的指令,如果從信號處理程式回傳(例如沒有呼叫exit或longjmp),則繼續執行在捕獲到信號時行程正在執行的正常指令序列(這和當一個硬體中斷發生時所發生的事情相似),但是在信號處理器里,我們并不知道當信號被捕獲時行程正在執行哪里的代碼,

如果行程正使用malloc在它的堆上分配額外的記憶體,而此時由于捕捉到信號而插入執行該信號處理程式,其中又呼叫了malloc,這會發生什么呢?或者,如果行程正呼叫一個把結果存盤在一個靜態區域里的函式到一半,比如 getpwnam,而我們在信號處理器里呼叫相同的函式,又會發生什么呢?在malloc的例子里,行程可能會遭到嚴重破壞,因為malloc通常維護它 所有分配過的區域的鏈表,而插入執行信號處理程式時,行程可能正在更改此鏈接表,

在getpwnam的例子里,回傳給普通呼叫者的資訊可能被回傳給信號處理器的資訊覆寫,

SUS規定了必須保證是可以再入的函式,下表列出了這些再入函式:
在這里插入圖片描述

一個可重入的函式簡單來說就是可以被中斷的函式,也就是說,可以在這個函式執行的任何時刻中斷它,轉入OS 調度下去執行另外一段代碼,而回傳控制時不會出現什么錯誤,可重入(reentrant)函式可以由多于一個任務并發使用,而不必擔心資料錯誤,相反, 不可重入(non-reentrant)函式不能由超過一個任務所共享,除非能確保函式的互斥 (或者使用信號量,或者在代碼的關鍵部分禁用中斷),

可重入函式可以在任意時刻被中斷, 稍后再繼續運行,不會丟失資料,可重入函式要么使用本地變數,要么在使用全域變數時 保護自己的資料,

信號安全,其實也就是異步信號安全,是說執行緒在信號處理函式當中,不管以任何方式呼叫你的這個函式如果不死鎖不修改資料,那就是信號安全的,因此,我認為可重入與異步信號安全是一個概念 ,

執行緒安全

執行緒安全:一個函式被稱為執行緒安全的,當且僅當被多個并發執行緒反復的呼叫時,它會一直產生正確的結果,

有一類重要的執行緒安全函式,叫做可重入函式,其特點在于它們具有一種屬性:當它們被多個執行緒呼叫時,不會參考任何共享的資料,

盡管執行緒安全和可重入有時會( 不正確的 )被用做同義詞,但是它們之間還是有清晰的技術差別的,可重入函式是執行緒安全函式的一個真子集,

需要C/C++ Linux服務器架構師學習資料加群812855908(資料包括C/C++,Linux,golang技術,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒體,CDN,P2P,K8S,Docker,TCP/IP,協程,DPDK,ffmpeg等),免費分享

l在這里插入圖片描述

可重入與執行緒安全的區別及聯系

可重入函式:重入即表示重復進入,首先它意味著這個函式可以被中斷,其次意味著它除了使用自己堆疊上的變數以外不依賴于任何環境(包括static ),這樣的函式就是purecode (純代碼)可重入,可以允許有該函式的多個副本在運行,由于它們使用的是分離的堆疊,所以不會互相干擾,

可重入函式是執行緒安全函式,但是反過來,執行緒安全函式未必是可重入函式,

實際上,可重入函式很少,APUE 10.6 節中描述了Single UNIX Specification 說明的可重入的函式,只有115 個;APUE 12.5 節中描述了POSIX.1 中不能保證執行緒安全的函式,只有89 個,

信號就像硬體中斷一樣,會打斷正在執行的指令序列,信號處理函式無法判斷捕獲到信號的時候,行程在何處運行,如果信號處理函式中的操作與打斷的函式的操作相同,而且這個操作中有靜態資料結構等,當信號處理函式回傳的時候(當然這里討論的是信號處理函式可以回傳),恢復原先的執行序列,可能會導致信號處理函式中的操作覆寫了之前正常操作中的資料,

不可重入的幾種情況

使用靜態資料結構,比如getpwnam,getpwuid:如果信號發生時正在執行getpwnam,信號處理程式中執行getpwnam可能覆寫原來getpwnam獲取的舊值

  • 呼叫malloc或free:如果信號發生時正在malloc(修改堆上存盤空間的鏈接表),信號處理程式又呼叫malloc,會破壞內核的資料結構

  • 使用標準IO函式,因為好多標準IO的實作都使用全域資料結構,比如printf(檔案偏移是全域的)

  • 函式中呼叫longjmp或siglongjmp:信號發生時程式正在修改一個資料結構,處理程式回傳到另外一處,導致資料被部分更新,

即使對于可重入函式,在信號處理函式中使用也需要注意一個問題就是errno ,一個執行緒中只有一個errno 變數,信號處理函式中使用的可重入函式也有可能 會修改errno ,例如,read 函式是可重入的,但是它也有可能會修改errno ,因此,正確的做法是在信號處理函式開始,先保存errno ;在信號處 理函式退出的時候,再恢復errno ,

例如,程式正在呼叫printf 輸出,但是在呼叫printf 時,出現了信號,對應的信號處理函式也有printf 陳述句,就會導致兩個printf 的輸出混雜在一起,

如果是給printf 加鎖的話,同樣是上面的情況就會導致死鎖,對于這種情況,采用的方法一般是在特定的區域屏蔽一定的信號,

屏蔽信號的方法:

  signal(SIGPIPE, SIG_IGN); // 忽略一些信號
  sigprocmask()// sigprocmask 只為單執行緒定義的
  pthread_sigmask(); // pthread_sigmasks 可以在多執行緒中使用

現在看來信號異步安全和可重入的限制似乎是一樣的,所以這里把它們等同看待;

執行緒安全:如果一個函式在同一時刻可以被多個執行緒安全的呼叫,就稱該函式是執行緒安全的,Malloc 函式是執行緒安全的,

不需要共享時,請為每個執行緒提供一個專用的資料副本,如果共享非常重要,則提供顯式同步,以確保程式以確定的方式操作,通過將程序包含在陳述句中來鎖定和解除鎖定互斥,可以使不安全程序變成執行緒安全程序,而且可以進行串行化,

很多函式并不是執行緒安全的,因為他們回傳的資料是存放在靜態的記憶體緩沖區中的,通過修改介面,由呼叫者自行提供緩沖區就可以使這些函式變為執行緒安全的,

作業系統實作支持執行緒安全函式的時候,會對POSIX.1 中的一些非執行緒安全的函式提供一些可替換的執行緒安全版本,

例如,gethostbyname() 是執行緒不安全的,在Linux 中提供了gethostbyname_r() 的執行緒安全實作,

函式名字后面加上 _r ,以表明這個版本是可重入的(對于執行緒可重入,也就是說是執行緒安全的,但并不是說對于信號處理函式也是可重入的,或者是異步信號安全的),

多執行緒程式中常見的疏忽性問題:

  • 將指標作為新執行緒的引數傳遞給呼叫方堆疊,
  • 在沒有同步機制保護的情況下訪問全域記憶體的共享可更改狀態,
  • 兩個執行緒嘗試輪流獲取對同一對全域資源的權限時導致死鎖,其中一個執行緒控制第一種資源,另一個執行緒控制第二種資源,其中一個執行緒放棄之前,任何一個執行緒都無法繼續操作,
  • 嘗試重新獲取已持有的鎖(遞回死鎖),
  • 在同步保護中創建隱藏的間隔,如果受保護的代碼段包含的函式釋放了同步機制,而又在回傳呼叫方之前重新獲取了該同步機制,則將在保護中出現此間隔,結果具有誤導性,對于呼叫方,表面上看全域資料已受到保護,而實際上未受到保護,
  • 將UNIX 信號與執行緒混合時,使用sigwait(2) 模型來處理異步信號,
  • 呼叫setjmp(3C) 和longjmp(3C) ,然后長時間跳躍,而不釋放互斥鎖,
  • 從對*_cond_wait() 或 *_cond_timedwait() 的呼叫中回傳后無法重新評估條件,

總結

  • 判斷一個函式是不是可重入函式,在于判斷其能否可以被打斷,打斷后恢復運行能夠得到正確的結果,(打斷執行的指令序列并不改變函式的資料)
  • 判斷一個函式是不是執行緒安全的,在于判斷其能否在多個執行緒同時執行其指令序列的時候,保證每個執行緒都能夠得到正確的結果,
  • 如果一個函式對多個執行緒來說是可重入的,則說這個函式是執行緒安全的,但這并不能說明對信號處理程式來說該函式也是可重入的,
  • 如果函式對異步信號處理程式的重入是安全的,那 么就可以說函式是” 異步-信號安全 ” 的,

可重入與執行緒安全是兩個獨立的概念, 都與函式處理資源的方式有關,

首先,可重入和執行緒安全是兩個并不等同的概念,一個函式可以是可重入的,也可以是執行緒安全的,可以兩者均滿足,可以兩者皆不滿足( 該描述嚴格的說存在漏洞,參見第二條) ,

其次,從集合和邏輯的角度看,可重入是執行緒安全的子集,可重入是執行緒安全的充分非必要條件,可重入的函式一定是執行緒安全的,然過來則不成立,

第三,POSIX 中對可重入和執行緒安全這兩個概念的定義:

  • Reentrant Function :A function whose effect, when called by two or
    more threads,is guaranteed to be as if the threads each executed
    thefunction one after another in an undefined order, even ifthe
    actual execution is interleaved.
  • Thread-Safe Function :A function that may be safely invoked
    concurrently by multiple threads.
  • Async-Signal-Safe Function :A function that may be invoked, without
    restriction fromsignal-catching functions. No function is
    async-signal -safe unless explicitly described as such

以上三者的關系為:可重入函式 必然 是 執行緒安全函式 和 異步信號安全函式;執行緒安全函式不一定是可重入函式,

可重入與執行緒安全的區別體現在能否在signal 處理函式中被呼叫的問題上, 可重入函式在signal 處理函式中可以被安全呼叫,因此同時也是 Async-Signal-Safe Function ;而執行緒安全函式不保證可以在signal 處理函式中被安全呼叫,如果通過設定信號阻塞集合等方法保證一個非可重入函式不被信號中斷,那么它也是Async-Signal-Safe Function,

值得一提的是POSIX 1003.1 的 System Interface 預設是 Thread-Safe 的,但不是Async-Signal-Safe 的,Async-Signal-Safe 的需要明確表示,比如fork () 和signal() ,

一個非可重入函式通常( 盡管不是所有情況下) 由它的外部介面和使用方法即可進行判斷,例如:strtok() 是非可重入的,因為它在內部存盤了被標記分割的字串;ctime() 函式也是非可重入的,它回傳一個指向靜態資料的指標,而該靜態資料在每次呼叫中都被覆寫重寫,

一個執行緒安全的函式通過加鎖的方式來實作多執行緒對共享資料的安全訪問,執行緒安全這個概念,只與函式的內部實作有關,而不影響函式的外部介面,在 C 語言中,區域變數是在堆疊上分配的,因此,任何未使用靜態資料或其他共享資源的函式都是執行緒安全的,
目前的 AIX 版本中,以下函式庫是執行緒安全的:

  • C 標準函式庫
  • 與BSD 兼容的函式庫

使用全域變數( 的函式) 是非執行緒安全的,這樣的資訊應該以執行緒為單位進行存盤,這樣對資料的訪問就可以串行化,一個執行緒可能會讀取由另外一個執行緒生成的錯誤代碼,在AIX 中,每個執行緒有獨立的errno 變數,

最后讓我們來構想一個執行緒安全但不可重入的函式:

假設函式func() 在執行程序中需要訪問某個共享資源,因此為了實作執行緒安全,在使用該資源前加鎖,在不需要資源解鎖,

假設該函式在某次執行程序中,在已經獲得資源鎖之后,有異步信號發生,程式的執行流轉交給對應的信號處理函式;再假設在該信號處理函式中也需要呼叫函式 func() ,那么func() 在這次執行中仍會在訪問共享資源前試圖獲得資源鎖,然而我們知道前一個func() 實體已然獲得該鎖,因此信號處理函式阻塞——另一方面,信號處理函式結束前被信號中斷的執行緒是無法恢復執行的,當然也沒有釋放資源的機會,這樣就出現了執行緒和信號處理函式之間的死鎖局面,

因此,func() 盡管通過加鎖的方式能保證執行緒安全,但是由于函式體對共享資源的訪問,因此是非可重入,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/209816.html

標籤:其他

上一篇:java 集合LinkedList、ArrayList、Set

下一篇:【Microstation】三維建模基礎及軟體入門到精通實驗教程目錄

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more