Linux 信號機制:操作系統的“緊急電話”系統

想象一下,你正在電腦前專心工作,突然手機響了——這是一個通知,要求你立即處理一件新事情(比如接電話)。

Linux 系統中的信號(Signal)?? 機制,本質上就是操作系統內核或進程之間用來發送這類“緊急通知”的一種方式。

它不是普通的聊天(像文件或網絡傳輸數據那樣),而更像是一個簡潔的指令或警報,告訴目標進程:“嘿,有重要事情發生了,快看看怎么處理!”

一、信號是什么?—— 軟件中斷

從技術角度看,信號是一種軟件中斷機制。中斷是什么?想想你正在看書,突然門鈴響了,你不得不放下書去開門——這就是一個“中斷”。

硬件中斷是 CPU 響應外部設備(如鍵盤、網卡)的事件,而信號則是操作系統在軟件層面模擬的中斷。

  • ?異步性:?? 信號可以在進程執行的任何時候到來,進程無法預知信號何時到達。就像你不知道電話什么時候會響。
  • ?簡潔性:?? 信號本身攜帶的信息量通常很小。它主要是一個編號?(整數),代表發生了“哪一類”事件。例如,SIGINT?(編號 2) 代表“中斷”,SIGTERM?(編號 15) 代表“終止請求”。少數信號(實時信號)可以攜帶少量附加數據
  • ?強制性:?? 信號一旦發送給目標進程,進程必須暫停當前正在執行的任務,轉而去響應這個信號(除非信號被明確屏蔽或忽略)。這就像那個必須接聽的電話。

二、為什么需要信號?—— 核心用途

信號機制解決了 Linux 系統中幾個關鍵問題:

  1. ?進程控制:?? 這是最常見的用途。用戶或管理員可以通過信號控制進程的行為。

    • Ctrl+C?(終端中) -> 發送?SIGINT?-> 通常請求進程終止?
    • kill -15 PID?-> 發送?SIGTERM?-> 優雅地請求進程終止?(允許進程清理資源)
    • kill -9 PID?-> 發送?SIGKILL?-> ?強制終止進程(終極手段,無法被捕獲或忽略)
    • Ctrl+Z?-> 發送?SIGTSTP?-> ?暫停進程 -> 之后可以用?fg/bg?配合?SIGCONT?信號恢復進程
  2. ?異常與錯誤處理:?? 當進程運行時發生嚴重錯誤,內核會自動發送信號給它。

    • 訪問非法內存 (段錯誤) ->?SIGSEGV?(11)
    • 執行了非法指令 ->?SIGILL?(4)
    • 浮點運算錯誤 (如除零) ->?SIGFPE?(8)。這些信號的默認行為通常是終止進程并可能產生?core dump?文件用于調試。
  3. ?事件通知:??

    • 子進程結束或狀態改變 -> 內核發送?SIGCHLD?(17) 給父進程。父進程可以捕獲此信號來回收子進程資源,避免僵尸進程。
    • 定時器到期 (alarm(),?setitimer()) ->?SIGALRM?(14)。常用于超時控制或周期性任務觸發。
    • 終端斷開連接 ->?SIGHUP?(1)。常用于通知守護進程重新讀取配置文件
  4. ?簡單的進程間通信 (IPC):?? 雖然不適合傳輸大量數據,但一個進程 (kill(),?raise()) 可以給另一個進程發送信號來通知特定事件的發生。自定義信號?SIGUSR1?(10) 和?SIGUSR2?(12) 常被應用程序用于此目的。

三、信號如何工作?—— 生命周期三部曲

一個信號從產生到被處理完,經歷三個階段:

?1.生成:?? 信號被某個源頭創建出來。

  • ?來源:?? 用戶按鍵、硬件異常、內核事件、其他進程調用?kill()/raise()?等系統調用

?2.遞送:?? 信號被放入目標進程的“待辦事項”清單(稱為掛起信號隊列)。

  • ?關鍵點:?? 此時信號處于 ?Pending (掛起)?? 狀態,等待被處理
  • ?阻塞:?? 進程可以設置信號掩碼來暫時阻塞某些信號。被阻塞的信號會停留在掛起隊列,直到解除阻塞。
  • ?隊列 vs 標志位:?? 這是區分信號類型的關鍵!標準信號(1-31)通常用位標志實現。如果同一個標準信號在掛起期間被多次發送,進程可能只收到一次?(丟失信號!),所以也叫不可靠信號?。實時信號(32-64)使用隊列實現,同一信號的多次發送都會被排隊并按序處理,稱為可靠信號

?3.處理:?? 進程實際響應信號。

  • ?時機:?? 當進程即將從內核態返回用戶態時(例如系統調用結束、硬件中斷處理完),內核會檢查掛起隊列。如果有未被阻塞的信號,就處理它們。
  • ?處理方式:?? 進程對每個信號可以指定三種處理方式之一:
    • ?默認動作:?? 執行系統預定義的操作(如終止、忽略、暫停、生成 core dump 等)。大部分信號有默認行為。
    • ?忽略:?? 直接丟棄該信號(SIG_IGN)。注意:SIGKILL?和?SIGSTOP??不能被忽略或捕獲?!這是內核確保能控制進程的最后手段
    • ?捕獲:?? 進程提供一個自定義的信號處理函數? (handler)。當信號到來時,進程會中斷當前執行流,跳轉到這個函數執行。執行完后再(通常)恢復原流程。這是最靈活但也最需要謹慎使用的方式。

四、深入一點:關鍵特性與挑戰

  1. ?實時信號 vs 標準信號:??

    • ?范圍:?? 標準信號:1-31 (如?SIGINT=2,?SIGKILL=9,?SIGTERM=15);實時信號:32-64 (SIGRTMIN?~?SIGRTMAX)
    • ?可靠性:?? 標準信號可能丟失(不可靠);實時信號保證不丟失(可靠,隊列實現)
    • ?數據攜帶:?? 實時信號可以攜帶一個整數或指針值 (siginfo_t),通過?sigqueue()?發送。標準信號不行
    • ?優先級:?? 多個掛起信號待處理時,?編號越小優先級越高?(會先被處理)。實時信號也遵循此規則
  2. ?信號處理函數的危險性:??

    • ?異步安全:?? 信號處理函數在異步上下文中執行,它可能打斷程序任何地方的執行(包括正在執行庫函數或系統調用的中途)。因此,在?handler?內部只能調用保證是異步信號安全 (async-signal-safe) 的函數?(如?write(),?kill(),?_exit())。調用不安全的函數(如?printf(),?malloc())可能導致死鎖或數據損壞。
    • ?可重入性:?? 相關概念。處理函數如果訪問全局數據,需要非常小心并發訪問問題。
  3. ?多線程與信號:??

    • ?發送目標:?? 信號可以發給整個進程或特定線程。異常(如?SIGSEGV)通常發給觸發異常的線程;kill()?默認發給進程;pthread_kill()?發給特定線程
    • ?處理歸屬:?? 發給進程的信號,由進程內任意一個不阻塞該信號的線程處理(具體哪個線程不確定)。發給線程的信號,由該線程自己處理。
    • ?信號掩碼:?? 每個線程可以獨立設置自己的信號阻塞掩碼 (pthread_sigmask)
    • ?處理函數:?? 信號處理方式的設置 (signal(),?sigaction()) 是進程級別的。一個線程設置的處理函數會覆蓋之前其他線程的設置,對所有線程生效

五、常見信號一覽表

下表列出了部分常用信號及其默認行為:

信號名編號默認行為觸發場景
SIGHUP1終止終端連接斷開
SIGINT2終止鍵盤 Ctrl+C
SIGQUIT3Core 終止鍵盤 Ctrl+\
SIGILL4Core 終止非法指令
SIGABRT6Core 終止abort()?調用
SIGFPE8Core 終止算術錯誤(如除零)
SIGKILL9終止?強制終止進程?
SIGSEGV11Core 終止無效內存訪問
SIGPIPE13終止向無讀端的管道寫
SIGALRM14終止定時器超時(alarm())
SIGTERM15終止?請求進程終止? (kill?默認)
SIGCHLD17忽略子進程狀態改變(停止/終止)
SIGCONT18繼續讓停止的進程繼續
SIGSTOP19停止?強制暫停進程?
SIGTSTP20停止鍵盤 Ctrl+Z
SIGUSR110終止用戶自定義信號1
SIGUSR212終止用戶自定義信號2
SIGRTMIN32終止實時信號起始
SIGRTMAX64終止實時信號結束

六、總結:簡潔而強大的基石

Linux 信號機制,作為操作系統最基礎的異步事件通知進程間通信手段之一,其設計體現了簡潔與高效的哲學。它像一套遍布系統的“緊急電話”網絡:

  • ?對用戶/管理員:?? 提供?Ctrl+C,?kill?等直觀工具控制進程。
  • ?對應用程序:?? 提供處理異常(SIGSEGV)、響應通知(SIGCHLD)、實現超時(SIGALRM)和簡單IPC(SIGUSR1/2)的能力。
  • ?對內核:?? 提供通知進程錯誤和事件的標準通道。

理解信號的異步本質處理方式?(默認/忽略/捕獲)、可靠性差異?(標準 vs 實時)以及多線程環境下的復雜性,是深入掌握 Linux 系統編程和進程管理的關鍵一環。

雖然它不適合傳輸大數據,但在處理關鍵事件、控制流程和確保系統穩定性方面,這套簡潔的“中斷”機制發揮著不可替代的作用。

下次當你按下?Ctrl+C?時,不妨想想背后這套精妙的“緊急電話”系統是如何運作的。

?資源推薦:

C/C++學習交流君羊?<< 點擊加入

C/C++指針教程

C/C++學習路線,就業咨詢,技術提升

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

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

相關文章

論文略讀:Prefix-Tuning: Optimizing Continuous Prompts for Generation

2021 ACL固定預訓練LM&#xff0c;為LM添加可訓練&#xff0c;任務特定的前綴這樣就可以為不同任務保存不同的前綴這種前綴可以看成連續可微的soft prompt&#xff0c;相比于離散的token&#xff0c;更好優化&#xff0c;效果更好訓練的時候只需要更新prefix部分的參數&#xf…

CSS基礎選擇器、文本屬性、引入方式及Chorme調試工具

CSS基礎 1.1 CSS簡介 CSS 是層疊樣式表 ( Cascading Style Sheets ) 的簡稱. 有時我們也會稱之為 CSS 樣式表或級聯樣式表。 CSS 是也是一種標記語言 CSS 主要用于設置 HTML 頁面中的文本內容&#xff08;字體、大小、對齊方式等&#xff09;、圖片的外形&#xff08;寬高、邊…

RabbitMQ 高級特性之事務

1. 簡介與 MySQL、Redis 一樣&#xff0c;RabbitMQ 也支持事務。事務中的消息&#xff0c;要么全都發送成功&#xff0c;要么全部發送失敗&#xff0c;不會出現一部分成功一部分失敗的情況。2. 使用事務發送消息spring 中使用 RabbitMQ 開啟事務需要兩步&#xff1a;第一步&…

iframe 的同源限制與反爬機制的沖突

一、事件背景A域名接入了動態防護&#xff08;Bot 防護、反爬蟲機制&#xff09;&#xff0c;同時第三方業務B域名通過內嵌iframe的方式調用了A域名下的一個鏈接。二、動態防護介紹&#xff1a;動態防護&#xff08;也稱為 Bot 防護、反爬蟲機制&#xff09;是網站為了防止自動…

Rust 的 Copy 語義:深入淺出指南

在 Rust 中&#xff0c;Copy 是一個關鍵的特性&#xff0c;它定義了類型的復制行為。理解 Copy 語義對于掌握 Rust 的所有權系統和編寫高效代碼至關重要。一、核心概念&#xff1a;Copy vs Move特性Copy 類型非 Copy 類型 (Move)賦值行為按位復制 (bitwise copy)所有權轉移 (ow…

Qt的信號與槽(二)

Qt的信號與槽&#xff08;二&#xff09;1.自定義槽2.通過圖形化界面來生成自定義槽3.自定義信號3.信號和槽帶參數4.參數數量5.connect函數的設計&#x1f31f;hello&#xff0c;各位讀者大大們你們好呀&#x1f31f;&#x1f31f; &#x1f680;&#x1f680;系列專欄&#xf…

Java研學-MongoDB(三)

三 文檔相關 7 文檔統計查詢① 語法&#xff1a; // 精確統計文檔數 慢 準 dahuang> db.xiaohuang.countDocuments({條件}) 4 // 粗略統計文檔數 快 大致準 dahuang> db.xiaohuang.estimatedDocumentCount({條件}) 4② 例子&#xff1a; // 精確統計文檔數 name為奔波兒灞…

TCP協議格式與連接釋放

TCP報文段格式 TCP雖然是面向字節流的&#xff0c;但TCP傳送帶數據單元確是報文段。TCP報文段分為首部和數據段部分&#xff0c;而TCP的全部功能體現在它在首部中各字段的作用。因此&#xff0c;只有弄清TCP首部各字段的作用才能掌握TCP的工作原理。 TCP報文段首部的前20字節是…

CSS05:結構偽類選擇器和屬性選擇器

結構偽類選擇器 /*ul的第一個子元素*/ ul li:first-child{background: #0af6f6; }/*ul的最后一個子元素*/ ul li:last-child{background: #d27bf3; } /*選中p1&#xff1a;定位到父元素&#xff0c;選擇當前的第一個元素 選擇當前p元素的父級元素&#xff0c;選中父級元素的第…

使用策略模式 + 自動注冊機制來構建旅游點評系統的搜索模塊

? 目標&#xff1a; 搜索模塊支持不同內容類型&#xff08;攻略、達人、游記等&#xff09;每種搜索邏輯用一個策略類表示自動注冊&#xff08;基于注解 Spring 容器&#xff09;新增搜索類型時&#xff0c;只需添加一個類 一個注解&#xff0c;無需改工廠、注冊表等&#x…

第八十九篇 大數據開發中的數據算法:貪心策略 - 生活中的“精打細算”藝術

在資源有限的世界里&#xff0c;貪心算法教會我們&#xff1a;局部最優的累積&#xff0c;往往是通往全局最高效的捷徑。本文通過3個生活化場景原創圖表&#xff0c;揭示大數據開發中最實用的優化策略。目錄一、貪心算法核心思想&#xff1a;當下即最優二、三大核心應用場景詳解…

【論文閱讀】Dynamic Few-Shot Visual Learning without Forgetting

系統概述如下: (a) 一個基于卷積神經網絡(ConvNet)的識別模型,該模型包含特征提取器和分類器; (b) 一個少樣本分類權重生成器。這兩個組件都是在一組基礎類別上訓練的,我們為這些類別準備了大量訓練數據。在測試階段,權重生成器會接收少量新類別的訓練數據以及基礎類別的…

HTML應用指南:利用GET請求獲取全國山姆門店位置信息

山姆會員店作為全球知名的零售品牌&#xff0c;自進入中國市場以來&#xff0c;始終致力于為消費者提供高品質商品與便捷的購物體驗。隨著新零售業態的快速發展&#xff0c;門店位置信息的獲取變得愈發重要。品牌通過不斷拓展門店網絡&#xff0c;目前已覆蓋多個一、二線城市&a…

java ThreadLocal源碼分析

寫個demo測試下&#xff1a;private static void testThreadLocal() {ThreadLocal<Integer> threadLocal new ThreadLocal<>();new Thread(){Overridepublic void run() {threadLocal.set(9527);System.out.println("curr thread: " Thread.currentThr…

后端Web實戰(項目管理)

Restful風格 我們的案例是基于當前最為主流的前后端分離模式進行開發 在前后端分離的開發模式中&#xff0c;前后端開發人員都需要根據提前定義好的接口文檔&#xff0c;來進行前后端功能的開發。 后端開發人員&#xff1a;必須嚴格遵守提供的接口文檔進行后端功能開發&#…

Leetcode 3604. Minimum Time to Reach Destination in Directed Graph

Leetcode 3604. Minimum Time to Reach Destination in Directed Graph 1. 解題思路2. 代碼實現 題目鏈接&#xff1a;3604. Minimum Time to Reach Destination in Directed Graph 1. 解題思路 這一題思路上就是一個廣度優先遍歷&#xff0c;我們不斷考察當前時間點以及位置…

OpenXR Runtime切換工具-OpenXR-Runtime-Switcher

在開發VR時&#xff0c;有時有多個設備&#xff0c;大家可能也會選擇不同的串流工具&#xff0c;OpenXR類似于默認瀏覽器&#xff0c;如果設置錯誤可能導致游戲無法串流。 推薦一個工具&#xff0c;可以設置默認的OpenXR工具。 OpenXR-Runtime-Switcher 對于沒有的設備&#…

Opencv探索之旅:從像素變化到世界輪廓的奧秘

在你已經能熟練地為圖像施展“降噪”、“縮放”等魔法之后&#xff0c;你的探索之旅來到了一個全新的領域。你可能會好奇&#xff1a;我們人類能輕易地識別出照片中杯子的邊緣、建筑的輪廓&#xff0c;那計算機是如何“看見”這些邊界的呢&#xff1f;僅僅依靠濾波和顏色變換&a…

Ubuntu 22.04 + MySQL 8 無密碼登錄問題與 root 密碼重置指南

背景場景 在 Ubuntu 系統中使用 apt 或 deb 包方式安裝 MySQL 8 時&#xff1a; 初次安裝后會自動初始化數據庫&#xff1b;但 沒有提示 root 初始密碼&#xff1b;導致 mysql -u root -p 無法登錄。 為了解決該問題&#xff0c;通常我們使用 --skip-grant-tables 方式跳過權限…

題解:P13017 [GESP202506 七級] 線圖

首先明白定義&#xff1a; 線圖 L(G)L(G)L(G) 的頂點對應原圖 GGG 的邊&#xff0c;當且僅當原圖中的兩條邊有公共頂點時&#xff0c;對應的線圖頂點之間有一條邊。 不難想到&#xff0c;對于原圖中的每個頂點 vvv&#xff0c;其度數 d(v)d(v)d(v) 對應的邊集可以形成 (d(v)2)\…