信號(signal)

1.信號本質

1)信號是一種軟件中斷,是在軟件層次上對中斷的模擬;linux

2)、在平常生活中也有不少信號,好比常見的紅綠燈信號,咱們看見紅燈就停下,linux中的信號也是相似的,它提供一種機制告訴某個進程在某個時刻該怎樣作函數

2.信號產生(來源)

1)硬件來源:好比咱們按下了鍵盤或者其它硬件故障;spa

2)軟件來源:一些系統函數,最多見的發送信號的函數有kill, raise, alarm和pause;unix

3.信號遞送

  當致使產生信號的事件發生時,內核就產生一個信號。信號產生後,內核一般會在進程表中對進程設置某種形式的標誌,當內核設置了這個標誌,咱們就說內核向一個進程遞送了一個信號code

4.信號未決

  信號產生和遞送之間的時間間隔稱爲信號未決blog

5.進程對信號的處理方式(也稱對信號的動做)

1)忽略此信號:用signal函數指定SIG_IGN;SIGKILL和SIGSTOP不能被忽略繼承

2)捕捉此信號:用signal函數指定一個捕捉函數,指定信號被捕捉到就會調用這個捕捉函數;SIGKILL和SIGSTOP不能被捕捉進程

3)執行系統默認動做:用signal函數指定SIG_DFL事件

6.signal函數

做用:設置進程對信號的處理方式(動做)資源

void handler(int signo)
{
    //捕捉函數
}

signal(SIGINT,SIG_IGN);
signal(SIGINT,SIG_DFL);
signal(SIGINT,process);

7.sigaction函數

做用:查看設置進程對信號的處理方式(動做),比signal()函數多了查看,sigaction函數能傳遞信息給捕捉函數,signal函數則不能。目前linux中的signal()是經過sigaction()函數實現的。

8.信號排隊

  每一個進程有一個信號屏蔽字,規定了當前要阻塞遞送到該進程的信號集(unix提供sigprocmask函數能夠得到和更改屏蔽字),對於被阻塞的信號,若是進程對該信號的動做是捕捉或系統默認(即不是忽略),則內核將爲該信號保持爲未決狀態,直到該信號解除阻塞或將對該信號的動做更改成忽略。在這以前,若是這種信號發生了屢次,則發生未決信號排隊

9.不可靠信號

早期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)信號可能丟失:對於阻塞信號,不發生未決信號排隊,信號阻塞解除後,僅傳送該種信號一次,後來的該種信號都將丟失

9.1Linux下的不可靠信號

1)Linux對不可靠信號機制作了改進:信號的處理方式不會被自動重置爲系統默認值。所以,Linux下的不可靠信號問題主要指的是信號可能丟失。

2)Linux中信號編號小於SIGRTMIN的信號繼承於UNIX系統,是不可靠信號

10.可靠信號

可靠信號支持未決信號排隊克服了信號可能丟失的問題,linux後來添加的新信號(編號位於SIGRTMIN和SIGRTMAX之間)都是可靠信號

11.實時信號和非實時信號

  實時信號爲可靠信號,非實時信號爲不可靠信號

12.SIGCLD和SIGCHLD區別

1)UNIX中,SIGCLD在被進程設置成捕捉後,內核會馬上檢查在這以前是否已經有子進程終止了(等待着wait函數),若是有,則馬上調用捕捉函數,而SIGCHLD則不會作這個檢查,只管以後的

2)Linux中,SIGCLD等同於SIGCHLD

13.kill函數和raise函數

int kill(pid_t pid, int signo);
int raise(int signo);

kill函數將指定信號發送給指定進程(也能夠是自身)進程組,raise函數只能將指定信號發給自身進程。

13.1kill函數的pid

1)pid>0 將信號傳給進程標識碼爲pid 的進程

2)pid=0 將信號傳給和目前進程相同進程組的全部進程

3)pid<0 將信號傳給進程組識別碼爲pid 絕對值的全部進程

4)pid=-1 將信號廣播傳送給系統內全部的進程

13.2Linux中的kill指令

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的進程是否存在;

14.alarm函數和pause函數

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:在讀進程已終止時進行寫操做,將產生此信號

相關文章
相關標籤/搜索