《深入理解計算機系統》第八章 (四)信號

信號是軟件層面上的異常

(一)Linux信號

可以通過man 7 signal 查看Linux提供的標準信號。其中描述的信號的編號在不同的處理器體系結構的差異有所不同。

(二)信號傳送的步驟

傳送一個信號到目的進程通常由兩個不同的步驟組成:

(1)發送信號

發送信號的原因:

a)內核檢測到一個系統事件

b)一個進程調用了kill函數,顯式地要求內核發送一個信號給目的進程。

內核通過更新目的進程的上下文的某個狀態,發送一個信號給目的進程

發送信號的方式:

a)通過/bin/kill程序發送信號

b)通過鍵盤發送

常用的與鍵盤相關的信號:

SIGINT :來自鍵盤的終端信號(CTRL+C)

SIGQUIT:來自鍵盤的退出信號(CTRL +\)

SIGSTOP:來自鍵盤(CTRL+Z)或調試程序的停止信號

c)通過kill函數發送

函數原型如下:

#include<sys/type.h>

#include<signal.h>

int kill(pid_t pid , int sig);

如果pid大於0,則給進程pid 發送信號sig,如果pid小於0,則給abs(pid)進程組中的每個進程發送信號sig。如果pid等於0,則不發送信號

d)通過alarm函數發送

alarm - set an alarm clock for delivery of a signal

#include <unistd.h>

unsigned int alarm(unsigned int seconds);

alarm()  arranges  for  a SIGALRM signal to be delivered to the calling process in seconds seconds.

(2)接收信號

當目的進程被內核強迫以某種方式對信號的發送做出反應時,目的進程就接收了信號。

內核爲每個進程在pending位向量中維護着待處理信號的集合,在blocked位向量中維護着被阻塞的信號集合,傳送一個類型爲k的信號,內核就會設置pending中的k位,接受一個類型爲k的信號,內核就會清除pending中的k位。

每個信號類型都有一個預定義的默認行爲,是如下當中的一種:

a)進程終止

b)進程終止並轉儲存儲器

c)進程停止直到被SIGCONT信號重啓

d)進程忽略該信號

進程可以通過signal函數修改和信號相關聯的默認行爲,SIGSTOP和SIGKILL兩個信號的默認行爲是不能修改的。

 #include <signal.h>

typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);


signum的值爲:SIG_IGN,則忽略類型爲signum的信號

signum的值爲:SIG_DFL,則類型爲signum的信號行爲恢復爲默認行爲

signum的值爲:其他值,則設置類型爲signum的信號的行爲是用戶定義的函數(信號處理程序)。只要進程接收到一個類型爲signum信號,就調用這個程序


信號處理問題分析的三大要點

(1)待處理信號被阻塞

假設一個進程捕獲了一個類型爲k的信號,且當前正在運行它的信號處理程序,則如果另外一個類型爲k的信號傳遞給這個進程,則這個類型爲k的信號將變成待處理的,不會被接收,直到處理程序返回。

(2)待處理信號不會排隊

任意類型的信號,最多只能有一個待處理的信號,所以當上面描述的已經有一個類型爲k的待處理信號的時候,後續的傳遞到這個進程的待處理信號都將被直接丟棄。

(3)系統調用可以被中斷

在某些系統中當處理程序捕捉到一個信號時,被中斷的慢速系統調用在信號處理程序返回時將不再繼續,而是立即返回一個錯誤條件,並設置errno爲EINTR。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章