Linux : 內核中的信號捕捉

目錄

一 前言

?二 信號捕捉的方法

1.sigaction()?編輯

2. sigaction() 使用?

?三??可重入函數

四 volatile 關鍵字?


一 前言

如果信號的處理動作是用戶自定義函數,在信號遞達時就調用這個函數,這稱為捕捉信號。在Linux: 進程信號初識-CSDN博客?這一篇中已經學習到了一種信號捕捉的調用接口:signal(),為了深入理解操作系統內核中的信號捕獲機制,我們今天再來看一個接口:sigaction()。


?二 信號捕捉的方法

1.sigaction()

🍪:?sigaction?作為一個系統調用,用于修改和/或查詢信號的處理方式。相較于?signal?函數來說,它提供了對信號處理函數更精細的控制。

  • int signum:該參數需要傳入指定的進程信號,表示要捕捉的信號。
  • const struct sigaction *act:該參數與函數同名,是一個結構體指針。

  1. void (*sa_handler)(int)? :此成員的含義其實就是自定義處理信號的函數指針;
  2. void (*sa_sigcation)(int, siginfo_t *, void *): 此成員也是一個函數指針. 但是這個函數的意義是用來 處理實時信號的, 本節不考慮分析。
  3. sigset_t sa_mask: 此成員是一個信號集。
  4. int sa_flags:此成員包含著系統提供的一些選項, 本篇文章使用中都設置為0
  5. void (*sa_restorer)(void):很明顯 此成員也是一個函數指針. 但我們暫時不考慮他的意義.

也就是說我們暫時將該接口的第二個參數簡單理解為一個結構體指針,并且結構體里有一個成員是用來自定義處理信號的。

  • struct sigaction *oldact :第三個參數是輸出型參數,且其作用是獲取?此次修改信號?struct sigaction之前的原本的?struct sigaction?,?如果傳入的是空指針,則不獲取。??

2. sigaction() 使用?

#include <iostream>
#include <signal.h>
#include <unistd.h>using namespace std;//自定義處理動作
void handler( int signo)
{cout<<"get a signno: " <<signo<<endl;
}
int main()
{struct sigaction act,oact;act.sa_handler=handler;//函數指針,自定義處理動作act.sa_flags=0;sigisemptyset(&act.sa_mask);//初始化信號集sa.masksigaction(SIGINT,&act,&oact);while(true) sleep(1);return 0;}

運行結果:

?接下來我們對測試做一點修改

/其實就是相當于在handler中休眠了20s
//計時函數
void Count(int cnt)
{while(cnt){printf("cnt: %d\r",cnt);//\r回車fflush(stdout);//刷新緩沖區cnt--;sleep(1);}printf("\n");
}
//自定義處理動作
void handler( int signo)
{cout<<"get a signno: " <<"正在處理中"<<signo<<endl;Count(20);//休眠20s
}int main()
{struct sigaction act,oact;act.sa_handler=handler;//函數指針,自定義處理動作act.sa_flags=0;sigisemptyset(&act.sa_mask);//初始化信號集sa.masksigaction(SIGINT,&act,&oact);while(true) sleep(1);return 0;}

?運行結果:

?🍉:從運行結果我們可以看到,我們向進程發了大量2信號,但實際上進程只處理了幾次(即20s處理一個信號)。當我們進行正在遞達的某一個信號期間,同類信號無法遞達,這是因為當前信號正在被捕捉時,系統會自動將當前信號加入到進程的信號屏蔽字。(block)

? ? ? ? ? ? ? ? ? ?當信號完成捕捉動作,系統又會自動解除對該信號的信號屏蔽

當我們正在處理某一種信號的時候,我們也想屏蔽其他信號,我們可以利用? sigaction()函數中的一個參數 sa_mask,將額外想屏蔽的信號類型加入到sa_mask.?

int main()
{struct sigaction act,oact;act.sa_handler=handler;//函數指針,自定義處理動作act.sa_flags=0;sigisemptyset(&act.sa_mask);//初始化信號集sa.mask
這是修改部分/sigaddset(&act.sa_mask,3);//除了屏蔽2號我們也想屏蔽3號sigaction(SIGINT,&act,&oact);while(true) sleep(1);return 0;}

?小結:當某個信號的處理函數被調用時,內核自動將當前信號加入進程的信號屏蔽字,當信號處理函數返回時自動恢復原來 的信號屏蔽字,這樣就保證了在處理某個信號時,如果這種信號再次產生,那么 它會被阻塞到當前處理結束為止。 如果 在調用信號處理函數時,除了當前信號被自動屏蔽之外,還希望自動屏蔽另外一些信號,則用sa_mask字段說明這些需 要額外屏蔽的信號,當信號處理函數返回時自動恢復原來的信號屏蔽字。

🍎::signal() 和sigaction() 比較: 正如上文所說?相較于?signal?函數來說,它提供了對信號處理函數更精細的控制。一個直觀的表現,在調用信號處理函數時,除了當前信號被自動屏蔽之外,還可以自動屏蔽另外一些信號。


?三??可重入函數

可重入函數(Reentrant Function)是指可以在多線程環境中安全使用的函數,即這個函數可以被多個線程同時調用而不會導致數據錯誤或不一致

下面用個例子解釋一下:

一個進程中, 存在一個單鏈表結構. 并且此時需要執行一個節點的頭插操作:

頭插的操作就是:

node1->next = head;
head = node1;

如果在剛執行完第一步之后, 進程因為硬件中斷或者其他原因?陷入內核.

陷入內核之后需要回到用戶態繼續執行, 切換回用戶態時 進程會檢測未決信號, 如果此時剛好存在一個信號未決, 且此信號自定義處理.并且, 自定義處理函數動作也是一個新節點頭插操作:

?那么此時, 就會執行?node2?的頭插操作, 執行完畢的結果就是:

即,?node2 成為了鏈表的第一個節點 head,信號處理完畢之后, 需要返回用戶繼續執行代碼, 用戶剛執行完?node1->next = head;? ?所以下面應該執行?head = node1;, 結果就成了這樣:

結果就是,?node2?無法被找到了.造成了內存泄漏問題。

那么造成這個結果的原因是什么?

是因為單鏈表的頭插函數, 被不同的控制流調用了, 并且是在第一次調用還沒返回時就再次進入該函數, 這個行為稱為 重入

像例子中這個單鏈表頭插函數, 訪問的是一個全局鏈表, 所以可能因為重入而造成數據錯亂, 這樣的函數被稱為 不可重入函數, 即此函數不能重入, 重入可能會發生錯誤

反之, 如果一個函數即使重入, 也不會發生任何錯誤,這樣的函數被稱為可重入函數.?

如果一個函數符合以下條件之一,則稱為不可重入函數

調用了malloc和free。
調用了標準I/O庫函數, 標準I/O庫的很多實現都以不可重入的方式使用全局數據結構


四 volatile 關鍵字?

在之前學習C/C++的時候,我們就已經接觸過這個關鍵字了,它的作用是防止編譯器對該關鍵字修飾的變量的優化,確保每次訪問這個變量時都直接從內存中讀取,而不是使用可能存在的寄存器中的緩存值

接下來我們用一個例子分析一下該關鍵字

   #include<stdio.h>#include<signal.h>int quit=0;void handler(int signo){printf(" %d 號信號:正在被捕捉\n",signo);printf("quit :%d",quit);quit=1;printf("->%d\n",quit);                                                  }int main(){signal(2,handler);//對2號信號進行捕捉while(!quit);//邏輯反,quit為0 !quit 為真   printf("我是正常退出的!\n");return 0;}  

接下來我們做個改動

?測試結果

?我們看到雖然quit 變為1了,但是? 我是正常退出的這句話并沒有打印出來也就是說? ? ? ? ? ? ? ? ? while(!quit);

? printf("我是正常退出的!\n");?這個while循環依然在運行,這是為什么呢?

:? 我們使用了?-03?選項讓編譯器做出了優化?

🍪未優化前:

CPU訪問數據時 會將數據從內存中拿到寄存器中. 然后再根據寄存器中的數據進行處理.所以在優化前,cpu一直在內存中讀取quit值,main()和signal()是兩個執行流,當2號信息傳來的時候,signal()把quit的值改為1,main()執行流中cpu再次從內存讀取quit的值時候已經變為1,跳出循環,所以打印了?我是正常退出的這句話。

🍪優化后:?

所以??volatile 關鍵字的作用就是保持內存可見性

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/75255.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/75255.shtml
英文地址,請注明出處:http://en.pswp.cn/web/75255.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

分布式id生成算法(雪花算法 VS 步長id生成)

分布式ID生成方案詳解:雪花算法 vs 步長ID 一、核心需求 全局唯一性:集群中絕不重復有序性:有利于數據庫索引性能高可用:每秒至少生成數萬ID低延遲:生成耗時<1ms二、雪花算法(Snowflake) 1. 數據結構(64位) 0 | 0000000000 0000000000 0000000000 0000000000 0 |…

函數式編程在 Java:Function、BiFunction、UnaryOperator 你真的會用?

大家好&#xff0c;我是你們的Java技術博主&#xff01;今天我們要深入探討Java函數式編程中的幾個核心接口&#xff1a;Function、BiFunction和UnaryOperator。很多同學雖然知道它們的存在&#xff0c;但真正用起來卻總是不得要領。這篇文章將帶你徹底掌握它們&#xff01;&am…

x265 編碼器中運動搜索 ME 方法對比實驗

介紹 x265 的運動搜索方法一共有 6 種方法,分別是 DIA、HEX、UMH、STAR、SEA、FULL。typedef enum {X265_DIA_SEARCH,X265_HEX_SEARCH,X265_UMH_SEARCH,X265_STAR_SEARCH,X265_SEA,X265_FULL_SEARCH } X265_ME_METHODS;GitHub

2025.4.8 dmy NOI模擬賽總結(轉化貢獻方式 dp, 交互(分段函數找斷點),SAM上計數)

文章目錄 時間安排題解T1.搬箱子(dp&#xff0c;轉化貢獻方式)T2.很多線。(分段函數找斷點)T3.很多串。(SAM&#xff0c; 計數) 時間安排 先寫了 T 3 T3 T3 60 p t s 60pts 60pts&#xff0c;然后剩下 2.5 h 2.5h 2.5h 沒有戰勝 T 1 T1 T1 40 p t s 40pts 40pts。 總得分…

ZYNQ筆記(四):AXI GPIO

版本&#xff1a;Vivado2020.2&#xff08;Vitis&#xff09; 任務&#xff1a;使用 AXI GPIO IP 核實現按鍵 KEY 控制 LED 亮滅&#xff08;兩個都在PL端&#xff09; 一、介紹 AXI GPIO (Advanced eXtensible Interface General Purpose Input/Output) 是 Xilinx 提供的一個可…

CSP認證準備第二天-第36/37次CCF認證

第37次CCF認證-第三題 主要是間接賦值比較難。 自己編寫的代碼如下&#xff0c;但是有問題&#xff0c;沒有解決間接賦值的問題&#xff0c;可以參考一下deepseek的回答。 #include <iostream> #include <bits/stdc.h> using namespace std; long long n,x; char …

Kotlin與HttpClient編寫視頻爬蟲

想用Apache HttpClient庫和Kotlin語言寫一個視頻爬蟲。首先&#xff0c;我需要確定用戶的具體需求。視頻爬蟲通常涉及發送HTTP請求&#xff0c;解析網頁內容&#xff0c;提取視頻鏈接&#xff0c;然后下載視頻。可能需要處理不同的網站結構&#xff0c;甚至可能需要處理動態加載…

FFMEPG常見命令查詢

基本參數 表格1&#xff1a;主要參數 參數說明-i設定輸入流-f設定輸出格式(format) 高于后綴名-ss開始時間-t時間長度codec編解碼 表格2&#xff1a;音頻參數 參數說明-aframes設置要輸出的音頻幀數-f音頻幀深度-b:a音頻碼率-ar設定采樣率-ac設定聲音的Channel數-acodec設定…

Java-對比兩組對象找出發生變化的字段工具-支持枚舉映射-支持時間-支持顯示對應字段中文描述-嵌套list等場景

實體字段比較器&#xff08;對比兩組對象找出發生變化的字段工具類開發&#xff09; 支持枚舉映射 支持時間 支持顯示對應字段中文描述 支持嵌套list等場景 下載地址&#xff1a; Java-對比兩組對象找出發生變化的字段工具-支持枚舉映射-支持時間-支持顯示對應字段中文描述-嵌…

15. git push

基本概述 git push 的作用是&#xff1a;把本地分支的提交推送到遠程倉庫。推送分支需要滿足快進規則&#xff08;Fast-Forward&#xff09;&#xff0c;即遠程分支的最新提交必須是本地分支的直接祖先&#xff0c;這個是通過哈希值值進行判斷的。 基本用法 1.完整格式 git…

訓練數據清洗(文本/音頻/視頻)

多數據格式的清洗方法 以下是針對多數據格式清洗方法的系統性總結&#xff0c;結合Python代碼示例&#xff1a; 一、數據清洗方法總覽&#xff08;表格對比&#xff09; 數據類型核心挑戰關鍵步驟常用Python工具文本非結構化噪聲去噪→分詞→標準化→向量化NLTK, SpaCy, Jie…

Python標準庫json完全指南:高效處理JSON數據

一、json庫概述 JSON(JavaScript Object Notation)是一種輕量級的數據交換格式&#xff0c;Python的json模塊提供了JSON數據的編碼和解碼功能。該模塊可以將Python對象轉換為JSON字符串&#xff08;序列化&#xff09;&#xff0c;也可以將JSON字符串轉換為Python對象&#xf…

微軟推出首款量子計算芯片Majorana 1

全球首款拓撲架構量子芯片問世&#xff0c;2025年2月20日&#xff0c;經過近20年研究&#xff0c;微軟推出了首款量子計算芯片Majorana 1&#xff0c;其宣傳視頻如本文末尾所示。 微軟表示&#xff0c;開發Majorana 1需要創造一種全新的物質狀態&#xff0c;即所謂的“拓撲體”…

【QT】QT中的文件IO

QT中的文件IO 一、有關文件IO的類二、步驟1、定義QFile的對象,與要讀寫的文件綁定在一起2、打開文件3、讀寫文件1&#xff09;讀取文件2&#xff09;寫入文件 4、關閉文件5、示例代碼&#xff1a; 三、QString和QByteArray之間的轉換1、方法2、示例代碼&#xff1a; 四、QFileI…

Nginx 499 錯誤的原因及解決方法

Nginx 499 錯誤的原因及解決方法 原因 客戶端超時&#xff1a; 客戶端在等待服務器響應時超時&#xff0c;導致連接被關閉。 解決方法&#xff1a;優化服務端響應時間&#xff0c;或調大客戶端的連接超時時間。 服務端響應過慢&#xff1a; 后端服務處理請求時間過長。 解決方法…

Smith-Waterman 算法(C++實現)

本文實現Smith-Waterman 算法案例&#xff0c;用于局部序列比對。該算法是生物信息學中用于尋找兩個 DNA、RNA 或蛋白質序列之間最優局部比對的經典算法&#xff0c;廣泛應用于序列相似性分析和功能預測。 問題描述 給定兩個生物序列 seq1 和 seq2&#xff0c;如何找到它們的最…

安卓玩機工具-----安卓機型通用 無損備份與恢復數據的工具BackupToolkit 操作過程

常規安卓機型數據備份與恢復的方法及工具 安卓設備的數據備份與恢復是保護個人數據的重要手段之一。以下是幾種常用的方法和工具&#xff1a; 方法一&#xff1a;利用內置的云服務進行備份 許多安卓設備提供了內置的云服務&#xff0c;例如華為手機可以通過“華為云空間”來…

oracle 動態性能視圖

Oracle 數據庫中的 V$SQLAREA 是一個動態性能視圖&#xff08;Dynamic Performance View&#xff09;&#xff0c;用于記錄共享池&#xff08;Shared Pool&#xff09;中所有 SQL 語句的統計信息。每個 SQL 語句在共享池中存儲為一個游標&#xff08;Cursor&#xff09;&#x…

OceanBase V4.3.5 上線全文索引功能,讓數據檢索更高效

近日&#xff0c;OceanBase 4.3.5 BP1 版本正式推出了企業級全文索引功能。該版本在中文分詞、查詢效率及混合檢索能力上進行了全面提升。經過自然語言模式和布爾模式在不同場景下的對比測試&#xff0c;OceanBase 的全文索引性能明顯優于 MySQL。 點擊下載 OceanBase 社區版…

海康攝像頭AI報警、移動偵測報警等通過Ehome/ISUP協議上報到LiveNVR流媒體平臺時如何進行報警配置

海康攝像頭AI報警、移動偵測報警等通過Ehome/ISUP協議上報到LiveNVR流媒體平臺時如何進行報警配置 1、LiveNVR介紹2、如何配置海康攝像頭、錄像機通過Ehome/ISUP注冊到LiveNVR設備 EHOME 接入配置示例設備 ISUP 接入配置示例直播流接入類型 海康ISUP海康 ISUP 設備ID啟用保存 3…