信 號 :
同步通信:按照某種順序依次做事情。
異步通信:接收到某個信號,去執行某個操作,然后再接著做之前的事情阻塞:沒有等到結果,不做其他事情,一直等待
非阻塞:沒有等到結果,直接返回。信號是唯一一種異步通信的方式
信號是信息的載體,Linux/UNIX 環境下,古老、經典的通信方式, 現下依然是主要的通信手段。Unix早期版本就提供了信號機制,但不可靠,信號可能丟失。Berkeley 和
AT&T都對信號模型做了更改,增加了可靠信號機制。但彼此不兼容。POSIX.1對可靠信號例程進行了標準化。
一個完整的信號生命周期可以分為3個重要階段,這3個階段由4個重要事件來刻畫
$信號產生
$信號在進程中注冊
$信號在進程中注銷
$執行信號處理函數
相鄰兩個事件的時間間隔構成信號生命周期的一個階段
信號處理有多種方式,一般是由內核完成的,當然也可以有用戶進程完成不可靠信號的處理過程(信號值在32號之前)
$發現該信號已經在進程中注冊,則忽略該信號
$故若前一個信號還未注銷又產生了相同的信號就會產生信號丟失可靠信號的處理過程(信號值在32號之后)
$發現信號不管該信號是否已經在進程中注冊,都會被再注冊所有可靠信號都支持排隊,而不可靠信號則都不支持排隊
信號的機制:
A給B發送信號,B收到信號之前執行自己的代碼,收到信號后,不管執行到程序的什
么位置,都要暫停運行,去處理信號,處理完畢再繼續執行。與硬件中斷類似——異步模 式。但信號是軟件層面上實現的中斷,早期常被稱為“軟中斷”。
信號的特質:由于信號是通過軟件方法實現,其實現手段導致信號有很強的延時性。 但對于用戶來說,這個延遲時間非常短,不易察覺。
每個進程收到的所有信號,都是由內核負責發送的,內核處理。
與信號相關的事件和狀態
產生信號:
1. 按鍵產生,如:Ctrl+c、Ctrl+z、Ctrl+\
2. 系統調用產生,如:kill、raise、abort
3. 軟件條件產生,如:定時器alarm
4. 硬件異常產生,如:非法訪問內存(段錯誤)、除0(浮點數例外)、內存對齊出錯
(總線錯誤)
5. 命令產生,如:kill命令遞達:遞送并且到達進程。
未決:產生和遞達之間的狀態。主要由于阻塞(屏蔽)導致該狀態。 信號的處理方式:
1. 執行默認動作,由Linux規定的默認操作。
2. 忽略(丟棄);SIGKILL及SIGSTOP不可被忽略。
3. 捕捉(調用戶處理函數)
Linux內核的進程控制塊PCB是一個結構體,task_struct, 除了包含進程id,狀態,工作目錄,用戶id,組id,文件描述符表,還包含了信號相關的信息,主要指阻塞信號集和未決信號集。
阻塞信號集(信號屏蔽字): 將某些信號加入集合,對他們設置屏蔽,當屏蔽x信號后,再收到該信號,該信號的處理將推后(解除屏蔽后)
未決信號集:
1. 信號產生,未決信號集中描述該信號的位立刻翻轉為1,表信號處于未決狀態。當信號被處理對應位翻轉回為0。這一時刻往往非常短暫。
2. 信號產生后由于某些原因(主要是阻塞)不能抵達。這類信號的集合稱之為未決信 號集。在屏蔽解除前,信號一直處于未決狀態。
查看所有的信號: kill -l
信號四要素:
與變量三要素類似的,每個信號也有其必備4要素,分別是:
1. 編號 2. 名稱 3. 事件 4. 默認處理動作
不同的操作系統定義了不同的系統信號。因此有些信號出現在Unix系統內,也出現在
Linux中,而有的信號出現在FreeBSD或Mac OS中卻沒有出現在Linux下。這里我們只研究
Linux系統中的信號。默認動作:
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) 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) SIGRTMIN ~ (64) SIGRTMAX:LINUX的實時信號,它們沒有固定的含義(可以由用戶自定義)。所有的實時信號的默認動作都為終止進程。
終端按鍵產生信號
Ctrl + c → 2) SIGINT(終止/中斷) "INT" Interrupt
Ctrl + z → 20) SIGTSTP(暫停/停止) "T" ----Terminal 終端。 Ctrl + \ → 3) SIGQUIT(退出)
硬件異常產生信號
除0操作 → 8) SIGFPE (浮點數例外) "F" -----float 浮點數。非法訪問內存 → 11) SIGSEGV (段錯誤)
總線錯誤 → 7) SIGBUS