概述
一、signal函数
signal()函数只处理一次信号;
signal函数每次设置具体的信号处理函数只能生效一次, 每次在进程响应处理信号的时候,随即将信号处理函数恢复到默认方式;如果想多次以相同的方式处理某个信号,通常的做法是,在响应函数开始,再次设置signal;
但是依旧会有问题。在信号发出时候到信号处理程序中重新调用signal函数,存在一段时间。如果这段时间内接收到一个信号(此时还没有调用signal函数), 这个信号的处理方式依旧是默认的。
int sigint_handler(int sig)
{
signal(SIGINT, sigint_handler);
...
}
看一个例子,此函数只能处理一次信号
void sigint_handler(int signo)
{
printf("ninterruptn"); //注意printf是不可重入函数;
}
int main()
{
signal(SIGINT, sigint_handler);
while(1){
sleep(1);
printf("mainn");
}
exit(0);
}
二、使用sigaction函数,实现一次函数调用处理多次信号
下面代码使用sigaction实现对多次信号的处理
int sigint_handler(int signo)
{
printf("ninterruptn");
}
int main()
{
struct sigaction action;
action.sa_handler = sigint_handler;
sigaction(SIGINT, &action, NULL);
while(1){
sleep(1);
printf("mainn");
}
exit(0);
}
三、signal函数与系统调用
当进程在系统调用中阻塞着的话,使用signal函数进入信号处理程序时候,从信号处理程序返回时候,原先的系统调用会被失效。
对于下面代码,当在键盘键入Ctrl + C,进程会终止。这是由于在死循环中, 进程阻塞在fgets函数中的read系统调用上,当从信号处理程序返回的时候,read系统调用失败返回,退出死循环,进程于是终止。
void sigint_handler(int signo)
{
printf("interruptn");
}
int main()
{
signal(SIGINT, sigint_handler);
void *ret;
char buf[MAXLINE];
while((ret = fgets(buf, MAXLINE, stdin)) != NULL){
printf("results:%sn", buf);
sleep(3);
}
exit(0);
}
注意,当进程在sleep(3) 睡眠时候,此时终端有输入,这个输入会进入缓存排队,在进程结束睡眠之后,进程的fgets函数会从缓存的输入队列中读出;
可以考虑使用sigaction函数,设置action.sa_flags = SA_RESTART; 此时系统调用变成可重启;
代码如下:
void sigint_handler(int signo)
{
printf("interruptn");
}
int main()
{
void *ret;
char buf[MAXLINE];
struct sigaction action;
action.sa_handler = sigint_handler;
action.sa_flags = SA_RESTART;
sigaction(SIGINT, &action, NULL);
while((ret = fgets(buf, MAXLINE, stdin)) != NULL){
printf("results:%sn", buf);
sleep(3);
}
printf("fgets errorn");
exit(0);
最后
以上就是奋斗乐曲为你收集整理的signal 和 sigaction 函数的全部内容,希望文章能够帮你解决signal 和 sigaction 函数所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复