[TOC]
# 簡介
信號是 Linux 進程間通信的最古老的方式。信號是軟件中斷,它是在軟件層次上對中斷機制的一種模擬,是一種異步通信的方式 。信號可以導致一個正在運行的進程被另一個正在運行的異步進程中斷,轉而處理某一個突發事件。
**信號的特點**
* 簡單
* 不能攜帶大量信息
* 滿足某個特設條件才發送
信號可以直接進行用戶空間進程和內核空間進程的交互,內核進程可以利用它來通知用戶空間進程發生了哪些系統事件。
一個完整的信號周期包括三個部分:信號的產生,信號在進程中的注冊,信號在進程中的注銷,執行信號處理函數

注意:這里信號的產生,注冊,注銷時信號的內部機制,而不是信號的函數實現
**信號編號:**
Unix早期版本就提供了信號機制,但不可靠,信號可能丟失。Berkeley 和 AT&T都對信號模型做了更改,增加了可靠信號機制。但彼此不兼容。POSIX.1對可靠信號例程進行了標準化。
Linux 可使用命令:kill -l("l" 為字母),查看相應的信號
~~~
[root@master ~]# kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
~~~
不存在編號為0的信號。其中1-31號信號稱之為常規信號(也叫普通信號或標準信號),34-64稱之為實時信號,驅動編程與硬件相關。名字上區別不大。而前32個名字各不相同
Linux常規信號一覽表
| **編號** | **信號** | **對應事件** | **默認動作** |
| --- | --- | --- | --- |
| 1 | SIGHUP | 用戶退出shell時,由該shell啟動的所有進程將收到這個信號 | 終止進程 |
| 2 | **SIGINT** | 當用戶按下了****組合鍵時,用戶終端向正在運行中的由該終端啟動的程序發出此信號 | 終止進程 |
| 3 | **SIGQUIT** | 用戶按下****組合鍵時產生該信號,用戶終端向正在運行中的由該終端啟動的程序發出些信號 | 終止進程 |
| 4 | SIGILL | CPU檢測到某進程執行了非法指令 | 終止進程并產生core文件 |
| 5 | SIGTRAP | 該信號由斷點指令或其他 trap指令產生 | 終止進程并產生core文件 |
| 6 | SIGABRT | 調用abort函數時產生該信號 | 終止進程并產生core文件 |
| 7 | SIGBUS | 非法訪問內存地址,包括內存對齊出錯 | 終止進程并產生core文件 |
| 8 | SIGFPE | 在發生致命的運算錯誤時發出。不僅包括浮點運算錯誤,還包括溢出及除數為0等所有的算法錯誤 | 終止進程并產生core文件 |
| 9 | SIGKILL | 無條件終止進程。本信號不能被忽略,處理和阻塞 | 終止進程,可以殺死任何進程 |
| 10 | SIGUSE1 | 用戶定義的信號。即程序員可以在程序中定義并使用該信號 | 終止進程 |
| 11 | **SIGSEGV** | 指示進程進行了無效內存訪問(段錯誤) | 終止進程并產生core文件 |
| 12 | SIGUSR2 | 另外一個用戶自定義信號,程序員可以在程序中定義并使用該信號 | 終止進程 |
| 13 | **SIGPIPE** | Broken pipe向一個沒有讀端的管道寫數據 | 終止進程 |
| 14 | SIGALRM | 定時器超時,超時的時間 由系統調用alarm設置 | 終止進程 |
| 15 | SIGTERM | 程序結束信號,與SIGKILL不同的是,該信號可以被阻塞和終止。通常用來要示程序正常退出。執行shell命令Kill時,缺省產生這個信號 | 終止進程 |
| 16 | SIGSTKFLT | Linux早期版本出現的信號,現仍保留向后兼容 | 終止進程 |
| 17 | **SIGCHLD** | 子進程結束時,父進程會收到這個信號 | 忽略這個信號 |
| 18 | SIGCONT | 如果進程已停止,則使其繼續運行 | 繼續/忽略 |
| 19 | SIGSTOP | 停止進程的執行。信號不能被忽略,處理和阻塞 | 為終止進程 |
| 20 | SIGTSTP | 停止終端交互進程的運行。按下組合鍵時發出這個信號 | 暫停進程 |
| 21 | SIGTTIN | 后臺進程讀終端控制臺 | 暫停進程 |
| 22 | SIGTTOU | 該信號類似于SIGTTIN,在后臺進程要向終端輸出數據時發生 | 暫停進程 |
| 23 | SIGURG | 套接字上有緊急數據時,向當前正在運行的進程發出些信號,報告有緊急數據到達。如網絡帶外數據到達 | 忽略該信號 |
| 24 | SIGXCPU | 進程執行時間超過了分配給該進程的CPU時間 ,系統產生該信號并發送給該進程 | 終止進程 |
| 25 | SIGXFSZ | 超過文件的最大長度設置 | 終止進程 |
| 26 | SIGVTALRM | 虛擬時鐘超時時產生該信號。類似于SIGALRM,但是該信號只計算該進程占用CPU的使用時間 | 終止進程 |
| 27 | SGIPROF | 類似于SIGVTALRM,它不公包括該進程占用CPU時間還包括執行系統調用時間 | 終止進程 |
| 28 | SIGWINCH | 窗口變化大小時發出 | 忽略該信號 |
| 29 | SIGIO | 此信號向進程指示發出了一個異步IO事件 | 忽略該信號 |
| 30 | SIGPWR | 關機 | 終止進程 |
| 31 | SIGSYS | 無效的系統調用 | 終止進程并產生core文件 |
| 34~64 | SIGRTMIN ~ SIGRTMAX | LINUX的實時信號,它們沒有固定的含義(可以由用戶自定義) | 終止進程 |
# 信號四要素
每個信號必備4要素,分別是:
1)編號 2)名稱 3)事件 4)默認處理動作
可通過**man 7 signal**查看幫助文檔獲取

在標準信號中,有一些信號是有三個“Value”,第一個值通常對alpha和sparc架構有效,中間值針對x86、arm和其他架構,最后一個應用于mips架構。一個‘-’表示在對應架構上尚未定義該信號。
不同的操作系統定義了不同的系統信號。因此有些信號出現在Unix系統內,也出現在Linux中,而有的信號出現在FreeBSD或Mac OS中卻沒有出現在Linux下。這里我們只研究Linux系統中的信號。
Action為默認動作:
* Term:終止進程
* Ign: 忽略信號 (默認即時對該種信號忽略操作)
* Core:終止進程,生成Core文件。(查驗死亡原因,用于gdb調試)
* Stop:停止(暫停)進程
* Cont:繼續運行進程
注意通過man 7 signal命令查看幫助文檔,其中可看到 : The signals**SIGKILL**and**SIGSTOP**cannot be caught, blocked, or ignored.
這里特別強調了**9) SIGKILL****和19) SIGSTOP信號,不允許忽略和捕捉,只能執行默認動作。甚至不能將其設置為阻塞。**
另外需清楚,只有每個信號所對應的事件發生了,該信號才會被遞送(但不一定遞達),不應亂發信號!!
# 信號的狀態
**1) 產生**
a) 當用戶按某些終端鍵時,將產生信號。
終端上按“Ctrl+c”組合鍵通常產生中斷信號 SIGINT
終端上按“Ctrl+\\”鍵通常產生中斷信號 SIGQUIT
終端上按“Ctrl+z”鍵通常產生中斷信號 SIGSTOP 等。
b) 硬件異常將產生信號。
除數為 0,無效的內存訪問等。這些情況通常由硬件檢測到,并通知內核,然后內核產生適當的信號發送給相應的進程。
c) 軟件異常將產生信號。
當檢測到某種軟件條件已發生(如:定時器alarm),并將其通知有關進程時,產生信號。
d) 調用系統函數(如:kill、raise、abort)將發送信號。
注意:接收信號進程和發送信號進程的所有者必須相同,或發送信號進程的所有者必須是超級用戶。
e) 運行 kill /killall命令將發送信號。
此程序實際上是使用 kill 函數來發送信號。也常用此命令終止一個失控的后臺進程。
**2) 未決狀態:沒有被處理**
**3) 遞達狀態:信號被處理了**
# 阻塞信號集和未決信號集
信號的實現手段導致信號有很強的延時性,但對于用戶來說,時間非常短,不易察覺。
Linux內核的進程控制塊PCB是一個結構體,task\_struct, 除了包含進程id,狀態,工作目錄,用戶id,組id,文件描述符表,還包含了信號相關的信息,主要指**阻塞信號集和未決信號集**。
**6.1 阻塞信號集(信號屏蔽字)**
將某些信號加入集合,對他們設置屏蔽,當屏蔽x信號后,再收到該信號,該信號的處理將推后(處理發生在解除屏蔽后)。
**6.2 未決信號集**
信號產生,未決信號集中描述該信號的位立刻翻轉為1,表示信號處于未決狀態。當信號被處理對應位翻轉回為0。這一時刻往往非常短暫。
信號產生后由于某些原因(主要是阻塞)不能抵達。這類信號的集合稱之為未決信號集。在屏蔽解除前,信號一直處于未決狀態。
在PCB中有兩個非常重要的信號集。一個稱之為“阻塞信號集”,另一個稱之為“未決信號集”。
這兩個信號集都是內核使用**位圖機制**來實現的。但操作系統不允許我們直接對其進行位操作。而需自定義另外一個集合,借助信號集操作函數來對PCB中的這兩個信號集進行修改。

- c語言
- 基礎知識
- 變量和常量
- 宏定義和預處理
- 隨機數
- register變量
- errno全局變量
- 靜態變量
- 類型
- 數組
- 類型轉換
- vs中c4996錯誤
- 數據類型和長度
- 二進制數,八進制數和十六進制數
- 位域
- typedef定義類型
- 函數和編譯
- 函數調用慣例
- 函數進棧和出棧
- 函數
- 編譯
- sizeof
- main函數接收參數
- 宏函數
- 目標文件和可執行文件有什么
- 強符號和弱符號
- 什么是鏈接
- 符號
- 強引用和弱引用
- 字符串處理函數
- sscanf
- 查找子字符串
- 字符串指針
- qt
- MFC
- 指針
- 簡介
- 指針詳解
- 案例
- 指針數組
- 偏移量
- 間接賦值
- 易錯點
- 二級指針
- 結構體指針
- 字節對齊
- 函數指針
- 指針例子
- main接收用戶輸入
- 內存布局
- 內存分區
- 空間開辟和釋放
- 堆空間操作字符串
- 內存處理函數
- 內存分頁
- 內存模型
- 棧
- 棧溢出攻擊
- 內存泄露
- 大小端存儲法
- 寄存器
- 結構體
- 共用體
- 枚舉
- 文件操作
- 文件到底是什么
- 文件打開和關閉
- 文件的順序讀寫
- 文件的隨機讀寫
- 文件復制
- FILE和緩沖區
- 文件大小
- 插入,刪除,更改文件內容
- typeid
- 內部鏈接和外部鏈接
- 動態庫
- 調試器
- 調試的概念
- vs調試
- 多文件編程
- extern關鍵字
- 頭文件規范
- 標準庫以及標準頭文件
- 頭文件只包含一次
- static
- 多線程
- 簡介
- 創建線程threads.h
- 創建線程pthread
- gdb
- 簡介
- mac使用gdb
- setjump和longjump
- 零拷貝
- gc
- 調試器原理
- c++
- c++簡介
- c++對c的擴展
- ::作用域運算符
- 名字控制
- cpp對c的增強
- const
- 變量定義數組
- 盡量以const替換#define
- 引用
- 內聯函數
- 函數默認參數
- 函數占位參數
- 函數重載
- extern "C"
- 類和對象
- 類封裝
- 構造和析構
- 深淺拷貝
- explicit關鍵字
- 動態對象創建
- 靜態成員
- 對象模型
- this
- 友元
- 單例
- 繼承
- 多態
- 運算符重載
- 賦值重載
- 指針運算符(*,->)重載
- 前置和后置++
- 左移<<運算符重載
- 函數調用符重載
- 總結
- bool重載
- 模板
- 簡介
- 普通函數和模板函數調用
- 模板的局限性
- 類模板
- 復數的模板類
- 類模板作為參數
- 類模板繼承
- 類模板類內和類外實現
- 類模板和友元函數
- 類模板實現數組
- 類型轉換
- 異常
- 異常基本語法
- 異常的接口聲明
- 異常的棧解旋
- 異常的多態
- 標準異常庫
- 自定義異常
- io
- 流的概念和類庫結構
- 標準io流
- 標準輸入流
- 標準輸出流
- 文件讀寫
- STL
- 簡介
- string容器
- vector容器
- deque容器
- stack容器
- queue容器
- list容器
- set/multiset容器
- map/multimap容器
- pair對組
- 深淺拷貝問題
- 使用時機
- 常用算法
- 函數對象
- 謂詞
- 內建函數對象
- 函數對象適配器
- 空間適配器
- 常用遍歷算法
- 查找算法
- 排序算法
- 拷貝和替換算法
- 算術生成算法
- 集合算法
- gcc
- GDB
- makefile
- visualstudio
- VisualAssistX
- 各種插件
- utf8編碼
- 制作安裝項目
- 編譯模式
- 內存對齊
- 快捷鍵
- 自動補全
- 查看c++類內存布局
- FFmpeg
- ffmpeg架構
- 命令的基本格式
- 分解與復用
- 處理原始數據
- 錄屏和音
- 濾鏡
- 水印
- 音視頻的拼接與裁剪
- 視頻圖片轉換
- 直播
- ffplay
- 常見問題
- 多媒體文件處理
- ffmpeg代碼結構
- 日志系統
- 處理流數據
- linux
- 系統調用
- 常用IO函數
- 文件操作函數
- 文件描述符復制
- 目錄相關操作
- 時間相關函數
- 進程
- valgrind
- 進程通信
- 信號
- 信號產生函數
- 信號集
- 信號捕捉
- SIGCHLD信號
- 不可重入函數和可重入函數
- 進程組
- 會話
- 守護進程
- 線程
- 線程屬性
- 互斥鎖
- 讀寫鎖
- 條件變量
- 信號量
- 網絡
- 分層模型
- 協議格式
- TCP協議
- socket
- socket概念
- 網絡字節序
- ip地址轉換函數
- sockaddr數據結構
- 網絡套接字函數
- socket模型創建流程圖
- socket函數
- bind函數
- listen函數
- accept函數
- connect函數
- C/S模型-TCP
- 出錯處理封裝函數
- 多進程并發服務器
- 多線程并發服務器
- 多路I/O復用服務器
- select
- poll
- epoll
- epoll事件
- epoll例子
- epoll反應堆思想
- udp
- socket IPC(本地套接字domain)
- 其他常用函數
- libevent
- libevent簡介