Unix 环境编程10-15 sigjmp longjmp 和 sigsetjmp siglongjmp的比较
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Unix 环境编程10-15 sigjmp longjmp 和 sigsetjmp siglongjmp的比较,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含6132字,纯文字阅读大概需要9分钟。
内容图文
![Unix 环境编程10-15 sigjmp longjmp 和 sigsetjmp siglongjmp的比较](/upload/InfoBanner/zyjiaocheng/638/6e22776aa07a401a8234b32afc1135f7.jpg)
Unix 环境编程10-15 sigjmp longjmp 和 sigsetjmp siglongjmp的比较
文章目录
实验一:信号函数handler 中再次触发同一个信号
首先看一般情况下,如果在一个信号执行函数中再此触发同样的信号会是则怎样的情况
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
void handler(int a)
{
sigset_t sigpend;
sigset_t sigmask;
sleep(5);
sigpending(&sigpend);
sigprocmask(0,NULL,&sigmask);
if(sigismember(&sigpend,SIGQUIT))
{
printf("SIGQUIT is pending\n");
}
else
{
printf("SIGQUIT is not pending\n");
}
if(sigismember(&sigmask,SIGQUIT))
{
printf("SIGQUIT is in sigmask\n");
}
else
{
printf("SIGQUIT is not in sigmask\n");
}
}
int main()
{
int sleep_left;
sigset_t sigmask;
if(signal(SIGQUIT,handler)==SIG_ERR)
{
printf("signal error\n");
exit(1);
}
sleep_left = sleep(5);
sigprocmask(0,NULL,&sigmask);
if(sigismember(&sigmask,SIGQUIT))
{
printf("main : SIGQUIT is in sigmask\n");
}
else
{
printf("main : SIGQUIT is not in sigmask\n");
}
printf("sleep_left = %d\n",sleep_left);
exit(0);
}
运行结果如下:
$ ./test
^\^\SIGQUIT is pending
SIGQUIT is in sigmask
SIGQUIT is not pending
SIGQUIT is in sigmask
main : SIGQUIT is not in sigmask
sleep_left = 3
结果分析:
首先在main中遇到sleep时,触发第一次SIGQUIT信号,当遇到handler中的sleep函数时触发第二次SIGQUIT信号。
第一次进入handler函数时,SIGQUIT就被加入了屏蔽字中,因此SIGQUIT 会在sigmask中,而此时发出来第二次的SIGQUIT信号
因此SIGQUIT信号会被阻塞则会处于pending状态。
第一次handler执行完之后,SIGQUIT信号会从屏蔽字中去除,因此则会处理第二次的SIGQUIT信号,第二次进入handler函数中,此时SIGQUIT依旧会被加入到屏蔽字中,但是由于没有第三个SIGQUIT信号,SIGQUIT不会处于pending状态。
而回到main函数中时,屏蔽字则会恢复,因此SIGQUIT不会在屏蔽字中。
实验二 使用longjmp 跳回到main函数中
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
static jmp_buf jmpbuf;
void handler(int a)
{
sigset_t sigpend;
sigset_t sigmask;
sleep(5);
sigpending(&sigpend);
sigprocmask(0,NULL,&sigmask);
if(sigismember(&sigpend,SIGQUIT))
{
printf("SIGQUIT is pending\n");
}
else
{
printf("SIGQUIT is not pending\n");
}
if(sigismember(&sigmask,SIGQUIT))
{
printf("SIGQUIT is in sigmask\n");
}
else
{
printf("SIGQUIT is not in sigmask\n");
}
longjmp(jmpbuf,1);
}
int main()
{
sigset_t sigmask;
sigset_t sigpend;
if(signal(SIGQUIT,handler)==SIG_ERR)
{
printf("signal error\n");
exit(1);
}
while(setjmp(jmpbuf)==0);
sigprocmask(0,NULL,&sigmask);
if(sigismember(&sigmask,SIGQUIT))
{
printf("main : SIGQUIT is in sigmask\n");
}
else
{
printf("main : SIGQUIT is not in sigmask\n");
}
sigpending(&sigpend);
if(sigismember(&sigpend,SIGQUIT))
{
printf("main : SIGQUIT is pending\n");
}
else
{
printf("main : SIGQUIT is not pending\n");
}
exit(0);
}
$ ./test
^\^\SIGQUIT is pending
SIGQUIT is in sigmask
main : SIGQUIT is in sigmask
main : SIGQUIT is pending
结果分析:
首先在main中遇到sleep时,触发第一次SIGQUIT信号,当遇到handler中的sleep函数时触发第二次SIGQUIT信号。
第一次进入handler函数时,SIGQUIT就被加入了屏蔽字中,因此SIGQUIT 会在sigmask中,而此时发出来第二次的SIGQUIT信号
因此SIGQUIT信号会被阻塞则会处于pending状态。
第一次handler执行完之后,则会跳转到setjmp函数的位置,此时SIGQUIT仍然屏蔽字中,因此第二次的SIGQUIT信号就不会进入handler函数中,因此在main函数中会输出SIGQUIT在屏蔽字中,SIGQUIT处在pending状态。
而回到main函数中时,屏蔽字则会恢复,因此SIGQUIT不会再屏蔽字中。
实验三 使用siglongjmp 跳回到main函数中
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
static jmp_buf jmpbuf;
void handler(int a)
{
sigset_t sigpend;
sigset_t sigmask;
sleep(5);
sigpending(&sigpend);
sigprocmask(0,NULL,&sigmask);
if(sigismember(&sigpend,SIGQUIT))
{
printf("SIGQUIT is pending\n");
}
else
{
printf("SIGQUIT is not pending\n");
}
if(sigismember(&sigmask,SIGQUIT))
{
printf("SIGQUIT is in sigmask\n");
}
else
{
printf("SIGQUIT is not in sigmask\n");
}
siglongjmp(jmpbuf,1);
}
int main()
{
sigset_t sigmask;
sigset_t sigpend;
if(signal(SIGQUIT,handler)==SIG_ERR)
{
printf("signal error\n");
exit(1);
}
while(sigsetjmp(jmpbuf,1)==0);
sigprocmask(0,NULL,&sigmask);
if(sigismember(&sigmask,SIGQUIT))
{
printf("main : SIGQUIT is in sigmask\n");
}
else
{
printf("main : SIGQUIT is not in sigmask\n");
}
sigpending(&sigpend);
if(sigismember(&sigpend,SIGQUIT))
{
printf("main : SIGQUIT is pending\n");
}
else
{
printf("main : SIGQUIT is not pending\n");
}
exit(0);
}
$ ./test
^\^\SIGQUIT is pending
SIGQUIT is in sigmask
SIGQUIT is not pending
SIGQUIT is in sigmask
main : SIGQUIT is not in sigmask
main : SIGQUIT is not pending
结果分析:
首先在main中遇到sleep时,触发第一次SIGQUIT信号,当遇到handler中的sleep函数时触发第二次SIGQUIT信号。
第一次进入handler函数时,SIGQUIT就被加入了屏蔽字中,因此SIGQUIT 会在sigmask中,而此时发出来第二次的SIGQUIT信号
因此SIGQUIT信号会被阻塞则会处于pending状态。
第一次handler执行完之后,则会跳转到sigsetjmp函数的位置,此时屏蔽字已经被恢复中,因此第二次的SIGQUIT信号就会进入handler函数中,此时由于没有第三个SIGQUIT信号,所以输出SIGQUIT在屏蔽字中,但不在pending中。随后再次使用siglongjmp跳入main函数中。
回到main函数中,屏蔽字被恢复,因此在main函数中会输出SIGQUIT不在在屏蔽字中,SIGQUIT不处在pending状态。
这里需要注意的时sigsetjmp函数可以设置跳转时是否恢复屏蔽字,上面的例子中设置sigsetjmp(jmpbuf,1)代表会恢复。
而设置sigsetjmp(jmpbuf,0)则不会恢复。
$ ./test
^\^\SIGQUIT is pending
SIGQUIT is in sigmask
main : SIGQUIT is in sigmask
main : SIGQUIT is pending
总结:
1、信号处理程序正常结束,会自动加触发信号加入屏蔽字,信号处理函数结束,会恢复原来的信号屏蔽字。
2、longjmp跳出信号处理程序,不会恢复原来的信号屏蔽字。
3、siglongjmp的第二个参数非零,恢复信号屏蔽字,为0则不恢复。
内容总结
以上是互联网集市为您收集整理的Unix 环境编程10-15 sigjmp longjmp 和 sigsetjmp siglongjmp的比较全部内容,希望文章能够帮你解决Unix 环境编程10-15 sigjmp longjmp 和 sigsetjmp siglongjmp的比较所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。