1)信號是一種軟件中斷,是在軟件層次上對中斷的模擬;linux
2)、在平常生活中也有不少信號,好比常見的紅綠燈信號,咱們看見紅燈就停下,linux中的信號也是相似的,它提供一種機制告訴某個進程在某個時刻該怎樣作函數
1)硬件來源:好比咱們按下了鍵盤或者其它硬件故障;spa
2)軟件來源:一些系統函數,最多見的發送信號的函數有kill, raise, alarm和pause;unix
當致使產生信號的事件發生時,內核就產生一個信號。信號產生後,內核一般會在進程表中對進程設置某種形式的標誌,當內核設置了這個標誌,咱們就說內核向一個進程遞送了一個信號code
信號產生和遞送之間的時間間隔稱爲信號未決blog
1)忽略此信號:用signal函數指定SIG_IGN;SIGKILL和SIGSTOP不能被忽略繼承
2)捕捉此信號:用signal函數指定一個捕捉函數,指定信號被捕捉到就會調用這個捕捉函數;SIGKILL和SIGSTOP不能被捕捉進程
3)執行系統默認動做:用signal函數指定SIG_DFL事件
做用:設置進程對信號的處理方式(動做)資源
void handler(int signo) { //捕捉函數 } signal(SIGINT,SIG_IGN); signal(SIGINT,SIG_DFL); signal(SIGINT,process);
做用:查看和設置進程對信號的處理方式(動做),比signal()函數多了查看,sigaction函數能傳遞信息給捕捉函數,signal函數則不能。目前linux中的signal()是經過sigaction()函數實現的。
每一個進程有一個信號屏蔽字,規定了當前要阻塞遞送到該進程的信號集(unix提供sigprocmask函數能夠得到和更改屏蔽字),對於被阻塞的信號,若是進程對該信號的動做是捕捉或系統默認(即不是忽略),則內核將爲該信號保持爲未決狀態,直到該信號解除阻塞或將對該信號的動做更改成忽略。在這以前,若是這種信號發生了屢次,則發生未決信號排隊。
早期unix系統的信號爲不可靠信號,它們有下面兩點特性(問題):
1)進程對某種信號的處理方式進行設置後(早期的signal函數),第一次接收到這種信號,進程按所設置的方式處理,在這以後,這種信號的處理方式就會被自動重置爲系統默認值;
因此當信號的處理方式設成捕捉時,通常會在捕捉函數的開頭進行信號處理方式的重建:
1 int sig_int();//捕捉函數 2 . 3 . 4 . 5 signal(SIGINT, sig_int);//設置信號處理方式 6 . 7 . 8 . 9 sig_int() 10 { 11 signal(SIGINT, sig_int);//信號處理方式的重建 12 . 13 . 14 }
可是這種方法也有問題:捕捉到SIGINT,第5行執行,轉到第9行調用sig_int(),再進入函數執行第11行,在執行完第5行後到執行第11行前的這段時間裏,對SIGINT的處理方式是系統默認值,若是這時發生了SIGINT中斷,則程序就終止了。
2)信號可能丟失:對於阻塞信號,不發生未決信號排隊,信號阻塞解除後,僅傳送該種信號一次,後來的該種信號都將丟失
1)Linux對不可靠信號機制作了改進:信號的處理方式不會被自動重置爲系統默認值。所以,Linux下的不可靠信號問題主要指的是信號可能丟失。
2)Linux中信號編號小於SIGRTMIN的信號繼承於UNIX系統,是不可靠信號
可靠信號支持未決信號排隊,克服了信號可能丟失的問題,linux後來添加的新信號(編號位於SIGRTMIN和SIGRTMAX之間)都是可靠信號
實時信號爲可靠信號,非實時信號爲不可靠信號
1)UNIX中,SIGCLD在被進程設置成捕捉後,內核會馬上檢查在這以前是否已經有子進程終止了(等待着wait函數),若是有,則馬上調用捕捉函數,而SIGCHLD則不會作這個檢查,只管以後的
2)Linux中,SIGCLD等同於SIGCHLD
int kill(pid_t pid, int signo); int raise(int signo);
kill函數將指定信號發送給指定進程(也能夠是自身)或進程組,raise函數只能將指定信號發給自身進程。
1)pid>0 將信號傳給進程標識碼爲pid 的進程
2)pid=0 將信號傳給和目前進程相同進程組的全部進程
3)pid<0 將信號傳給進程組識別碼爲pid 絕對值的全部進程
4)pid=-1 將信號廣播傳送給系統內全部的進程
1)Linux指令「kill pid」實際上是向進程標識碼爲pid 的進程發送默認信號SIGTERM,由於SIGTERM信號編號爲15,因此「kill pid」和「kill -s 15 pid」和「kill -15 pid」等價,「-s」能夠省略,讓「-」加在15上;
2)進程收到SIGTERM信號,將會發生如下事情:進程釋放相應資源後終止(相似於讓進程正常退出);進程可能仍然繼續運行;
3)Linux指令「kill -s 9 pid」表示向進程發送SIGKILL信號來強制殺死進程;
4)SIGTERM信號能夠被捕捉和忽略,SIGKILL信號則不能夠;
5)Linux信號編號爲0的信號爲空信號,「kill -s 0 pid」常被用來肯定一個指定pid的進程是否存在;
unsigned int alarm(unsigned int seconds); int pause(void);
1)alarm函數設置一個定時器,通過seconds秒定時器超時,會產生SIGALRM信號,此信號的默認動做是終止進程,通常將信號設置成捕捉,就能夠實現相應的定時操做了;
2)pause函數是進程掛起直到捕捉到某個信號,與alarm函數配合時只有當捕捉函數執行完,pause函數才釋放進程;
3)每一個進程只能有一個鬧鐘時間,若是在調用alarm時,以前已經爲該進程註冊的定時器尚未超時,則這個定時器的剩餘時間將會做爲本次調用alarm的返回值,而後鬧鐘時間被更新:
ret = alarm(5); sleep(3); ret = alarm(5); //ret值爲2,鬧鐘時間從新定成5s sleep(1); ret = alarm(5); //ret值爲4,鬧鐘時間從新定成5s
15.常見信號
1) SIGCHLD:一個進程終止時,SIGCHLD信號被送給其父進程
2)SIGINT:中斷信號,ctrl+c,用來中斷進程
3)SIGKILL(9):強制殺死任一進程,不可被捕捉和忽略
4)SIGSTOP:一個做業控制信號,中止一個進程,不可被捕捉和忽略
5)SIGTERM(15):kill命令默認的終止信號
6)SIGPIPE:在讀進程已終止時進行寫操做,將產生此信號