测试代码1:
# include <stdio.h>
# include <error.h>
# include <sys/types.h>
# include <string.h>
# include <signal.h>
typedef void Sigfunc(int);
void sig_usr(int signo){
if(signo == SIGUSR1) printf("SIGUSR1 received.\n");
else if(signo == SIGUSR2) printf("SIGUSR2 received.\n");
//else if(signo == SIGTERM) printf("SIGTERM received.\n");
else return;
}
int main(int argc, char *argv[]){
if(signal(SIGUSR1, sig_usr) == SIG_ERR) perror("cant catch sigusr1");
if(signal(SIGUSR2, sig_usr) == SIG_ERR) perror("cant catch sigusr2");
//if(signal(SIGTERM, sig_usr) == SIG_ERR) perror("cant catch sigterm");
for(;;) pause();
return 0;
}
$ gcc unix.c -o unix
./unix &
[1] 4339$ kill -SIGUSR1 4339
SIGUSR1 received.$ kill -SIGUSR2 4339
SIGUSR2 received.$ kill 4339
$
[1]+ 已终止 ./unix
sig_usr处理用户定义的信号SIGUSR1和SIGUSR2,kill指令向进程发送信号,由于进程没有处理终止信号,所以收到终止信号SIGTERM时程序默认被终止(代码注释部分就是处理终止信号的)。
测试代码2:进行信号处理函数时能否捕捉其他信号?
# include <stdio.h>
# include <error.h>
# include <errno.h>
# include <sys/types.h>
# include <string.h>
# include <signal.h>
typedef void Sigfunc(int);
void handler(){
printf("begin SIGINT\n");
for(int i=0; i<2000000000; ++i);
printf("end SIGINT\n");
}
void handler2(){
printf("begin SIGUSR1\n");
printf("end SIGUSR1\n");
}
int main(int argc, char *argv[]){
signal(SIGINT, handler);
signal(SIGUSR1, handler2);
pause();
perror("done ");
return 0;
}
$ ./unix &
[1] 3548
$ kill -SIGINT 3548
begin SIGINT
$ kill -SIGUSR1 3548
begin SIGUSR1
end SIGUSR1
$ end SIGINT
done : Interrupted system call
结果显示为可以(另外经过测试在执行信号A的处理函数时是会阻塞信号A的到来的)。
测试代码3:sigaction函数代替signal函数
# include <stdio.h>
# include <error.h>
# include <errno.h>
# include <sys/types.h>
# include <string.h>
# include <signal.h>
typedef void Sigfunc(int);
void handler(){
printf("handling singo.\n");
}
Sigfunc *signal(int signo, Sigfunc *func){
struct sigaction act, oact;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
act.sa_handler = func;
if(signo == SIGALRM) act.sa_flags |= SA_INTERRUPT;
else act.sa_flags |= SA_RESTART;
if(sigaction(signo, &act, &oact) < 0) return SIG_ERR;
return oact.sa_handler;
}
int main(int argc, char *argv[]){
signal(SIGINT, handler);
signal(SIGALRM, handler);
alarm(8);
char s[10]={0};
read(0, s, sizeof(s));
printf("%s\n",s);
perror("done");
return 0;
}
$ ./unix
^Chandling singo.
^Chandling singo.
^Chandling singo.
^Chandling singo.
handling singo.
done: Interrupted system call
sigaction比signal提供了更多功能,包括阻塞信号sa_mask和状态位sa_flags,后者可以设置被信号中断的函数是否自动重启(比如低速系统调用read、write)。上面代码如果是alarm引起的中断不重启,其他重启,也就是8秒内read要返回,否则就跳过了。另外老版的signal函数只能生效一次,而sigaction函数能永久生效。