信號是Linux系統(tǒng)提供的另一種進程通信機制同眯。
手冊
手冊 | 功能簡介 |
---|---|
signal(7) | 信號概述 |
signal(2) | 設置信號處理函數(shù) |
kill(2) | 發(fā)送信號的函數(shù) |
kill(1) | 發(fā)送信號的命令 |
raise(3) | 向當前進程發(fā)送信號 |
信號
顧名思義绽昼,可以發(fā)信號,它不叫數(shù)據(jù)嗽测,也就是說绪励,數(shù)據(jù)量很少,類似于脈沖唠粥。不過“脈沖”的種類很多,在signal(7)中可以看到停做,信號有很多種晤愧,比如常用的ctrl+c
就是向前臺進程發(fā)送一個SIGINT
信號,SIGKILL
是殺進程的信號蛉腌。
信號處理函數(shù)
每個進程對于每個信號都有一個信號處理函數(shù)官份,當進程收到信號時只厘,信號處理函數(shù)會被調用,默認的信號處理函數(shù)會殺死當前進程舅巷,如果要在某種信號下做一些自定義處理羔味,可以用signal(2)設置自定義的信號處理函數(shù)。系統(tǒng)提供了兩個現(xiàn)成的信號處理函數(shù)钠右,SIG_IGN
是忽略信號赋元,SIG_DFL
是默認信號處理函數(shù)。
代碼演示
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
static int stage = 0;//表示演示階段飒房,共有3個演示
//自定義信號處理函數(shù)
static void sighandler(int sig){
printf("%d receive signal %d\n", getpid(), sig);
stage++;
if (stage > 2){//三個演示完成后結束進程
_exit(0);
}
}
int main(int argc, char **argv)
{
pid_t pid = fork();
if (pid > 0){
//父進程搁凸,發(fā)送信號
sleep(1);//等子進程設定好信號處理函數(shù)
printf("%d send signal %d to %d\n", getpid(), SIGINT, pid);
kill(pid, SIGINT);//向子進程發(fā)送一個ctrl+c信號
waitpid(pid,NULL,0);
}
else if (pid == 0){
//子進程
signal(SIGINT, sighandler);//為ctrl+c設定信號處理函數(shù)
while (stage < 1);//等待信號處理函數(shù)完成
printf("%d send signal %d to %d\n", getpid(), SIGINT, getpid());
raise(SIGINT);//向自己進程發(fā)送ctrl+c信號
while (stage < 2);//等待信號處理函數(shù)完成
printf("Please use \"kill -2 %d\"\n", getpid());
while (stage < 3);//等待用戶用kill命令發(fā)送信號
}
return 0;
}
運行與輸出
# gcc test.c -o test && ./test &
[1] 82086
82096 send signal 2 to 82097
82097 receive signal 2
82097 send signal 2 to 82097
82097 receive signal 2
Please use "kill -2 82097"
# kill -2 82097
82097 receive signal 2
[1]+ Done gcc test.c -o test && ./test
第一個演示是主進程發(fā)送信號給子進程,所以82096是主進程狠毯,82097是子進程护糖。信號的值為2,即SIGINT
嚼松。
第二個演示是嫡良,子進程自己發(fā)信號給自己,觸發(fā)了自己的信號處理函數(shù)献酗。
第三個演示是寝受,用戶用kill命令主動向子進程發(fā)信號,最后子進程也收到了凌摄。
信號組可以去了解一下羡蛾。