一個(gè)最簡(jiǎn)單的信號(hào)信號(hào)處理例子:
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
void signal_rec(int signum, siginfo_t *info, void *myop)
{
?printf("receive signal %d\n", signum);
?sleep(5);?
}
int main(int argc,char **argv)
{
?struct sigaction act;
?int sig,i;
?
?sigemptyset(&act.sa_mask);
?act.sa_flags = SA_SIGINFO;
?act.sa_sigaction = signal_rec;
?
?for(i=1; i<argc; i++){ //argv[0]為調(diào)用程序名
??sig = atoi(argv[i]);
??if(sigaction(sig, &act, NULL) <0){
???printf("install signal error\n");
??}?
?}
?
?while(1){
??sleep(2);
??printf("wait for the signal\n");
?}
}
用法:
將文件保存為test.c,執(zhí)行make test,編譯生成test文件。
./test 36 39&
命令的意思是注冊(cè)信號(hào)36,39。命令結(jié)果會(huì)返回pid,假設(shè)為2625。
通過(guò)另外一個(gè)終端向2625進(jìn)程發(fā)送信號(hào)。例如:kill -s 36 2625
則我們可以看到signal_rec函數(shù)被執(zhí)行了。
當(dāng)我們發(fā)送40信號(hào),我們會(huì)發(fā)送程序終止了,這是因?yàn)閷?duì)于實(shí)時(shí)信號(hào),默認(rèn)的操作是終止。
關(guān)于信號(hào):
?Linux
支持的信號(hào)分為可靠信號(hào)和不可靠信號(hào)。此處的可靠與不可靠不是指系統(tǒng)是不是可靠的可靠,而是對(duì)于可靠信息來(lái)說(shuō),每一次信號(hào)發(fā)實(shí)都每被加到信號(hào)鏈中,所以是
可靠的;而對(duì)于不可靠信號(hào)來(lái)說(shuō),如果進(jìn)程之前已經(jīng)接收到該信號(hào),則不會(huì)被加到信號(hào)鏈中,因此對(duì)于此次發(fā)送的信號(hào)來(lái)說(shuō),對(duì)于該進(jìn)程來(lái)說(shuō)是不知道的,所就是說(shuō)
信號(hào)丟失了,因此是不可靠的。
?不可靠信號(hào)主要是在早期信號(hào)機(jī)制上的信號(hào)。一般來(lái)說(shuō),信號(hào)值小于SIGRTMIN的信號(hào)為不可靠信號(hào),不可靠信號(hào)又稱為非實(shí)時(shí)信號(hào)。可靠信號(hào)又稱為實(shí)時(shí)信號(hào)。實(shí)時(shí)信號(hào)是SIGRTMIN和SIGRTMAX間的所有信號(hào)。
?我們可以通過(guò)kill -l查看SIGRTMIN和SIGRTMAX的值。在Debian系統(tǒng)和Redhat上面,一般SIGRTMIN=33,SIGRTMAX=64。
?Linux既支持新的信號(hào)安裝函數(shù)sigation以及信號(hào)發(fā)送函數(shù)sigqueue,又支持早期的signal信號(hào)安裝函數(shù)和kill信號(hào)發(fā)送函數(shù)。
?信號(hào)的可靠與不可靠只與信號(hào)值有關(guān),與信號(hào)的發(fā)送和安裝函數(shù)無(wú)關(guān),也就是說(shuō)在Linux下即使使用sigaction和sigqueue也不可能將不可靠信號(hào)變?yōu)榭煽啃盘?hào)。
信號(hào)發(fā)送函數(shù)主要有以下幾個(gè):kill,raise,sigqueue,alarm,settimer,abort。
信號(hào)安裝函數(shù)主要有signal和sigaction。sigaction主要用于與sigqueue系統(tǒng)調(diào)用配合使用,主要用于實(shí)時(shí)信號(hào)處理。
信號(hào)集操作主要有以下幾個(gè)函數(shù):sigemptyset,sigfillset,sigaddset,sigdelset,sigismember。
信號(hào)的阻塞的未決主要有以下幾個(gè)函數(shù):sigprocmask,sigsuspend,sigpending。
最后以一個(gè)讀串口設(shè)備時(shí)用到的信號(hào)處理作為結(jié)尾(在上次的初始化串口設(shè)備中已經(jīng)出現(xiàn)過(guò)):
在讀取設(shè)備數(shù)據(jù)或者進(jìn)行網(wǎng)絡(luò)應(yīng)用的時(shí)候,為了防止程序進(jìn)入死鎖,我們需要設(shè)置超時(shí)操作,即比如我們讀串口設(shè)備,嘗試一定時(shí)間后仍然沒(méi)有響應(yīng),則可能設(shè)備沒(méi)有正常工作。那么在超時(shí)以后我們需要退出,否則程序就鎖住了。
我們現(xiàn)在使用SIGALRM信號(hào)來(lái)進(jìn)行這個(gè)處理(這種方式并不是最好的辦法):
我們假設(shè)有一個(gè)標(biāo)記是否超時(shí)的全局變量caught_alrm,默認(rèn)為0,為1時(shí)則表示超時(shí)。
static volatile sig_atomic_t caught_alrm;
static void sig_alrm(int signo){//信號(hào)處理函數(shù),設(shè)置超時(shí)全局變量為1。
??????? caught_alrm = 1;
??????? return;
}
int a_function{
?……
??? if(signal(SIGALRM, sig_alrm) == SIG_ERR){
??? ?syslog(LOG_ERR,"signal error in function:%s",__FUNCTION__);
??????? return -1;
??? }
??? caught_alrm = 0;
??? alarm(expalarm);
??? do{
??? ?//do something
??? ?//if the work is finished,call alarm(0) to clean the timer.
??? }while(caught_alrm == 0);
}
注:
1、本文為整理以前的工作筆記,如果您要轉(zhuǎn)載,請(qǐng)注意來(lái)源為爾雅,作者覃士國(guó)。如果您有任何問(wèn)題歡迎交流:shiguo.qin@gmail.com
2、
此文僅僅是一則筆記,如果您正在尋找關(guān)于Linux信號(hào)編程方面的資料,可以參考鄭彥興的一篇文章:http://www-
128.ibm.com/developerworks/cn/linux/l-ipc/part2/index1.html。此文詳細(xì)描述了很多關(guān)于信
號(hào)處理中的結(jié)構(gòu)等內(nèi)容,是學(xué)習(xí)信號(hào)編程的一篇不錯(cuò)的教程式文章。
?