信号屏蔽问题?

m565471801 2011-11-17 09:55:47
有两个信号SIGQUIT SIGINT,并且为他们注册信号处理函数,
在主函数中把SIGINT设置为屏蔽
发一个SIGQUIT,在SIGQUIT信号处理函数中将SIGINT解除屏蔽,返回主函数时,打印未决信号集状态,是解除屏蔽的状态,但是为什么这时响应SIGINT时,却还是打印屏蔽状态(如果已经解除屏蔽,应该打印recv a signal……)?
具体代码如下:

#include <unistd.h>

#include <signal.h>

#include <stdio.h>


void printsigset(sigset_t* set)

{

int i;

for (i=1;i<64;i++)

{

if (sigismember(set,i))

putchar('1');

else

putchar('0');

}

puts("");

}


void handler(int sig)

{

if (sig==SIGQUIT)

{

sigset_t s;

sigemptyset(&s);

sigaddset(&s,SIGINT);

sigprocmask(SIG_UNBLOCK,&s,NULL);

}


if (sig==SIGINT)

{

printf("recv a signal %d\n",sig);

}

}


int main(void)

{

sigset_t s;

sigset_t p;

signal(SIGINT,handler);

signal(SIGQUIT,handler);

sigemptyset(&s);

sigaddset(&s,SIGINT);

sigprocmask(SIG_BLOCK,&s,NULL);

for (;;)

{

sigpending(&p);

printsigset(&p);

sleep(1);

}

}
...全文
284 17 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
dd_zhouqian 2011-11-22
  • 打赏
  • 举报
回复
这两天看书看的云里雾里的,个人想法希望不要误导楼主,呵呵

在信号处理函数完成后,主程序再恢复到初始信号掩码,是不是考虑到其他进程会在某个时刻会触发信号从而产生冲突问题?出于对信号资源一致性考虑?

qq120848369 2011-11-21
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 jcback 的回复:]

void handler(int sig)
{
if (sig==SIGQUIT)
{
flag=1;
}
...
}
main
{...
if(flag==1)
{
sigset_t s;
sigemptyset(&a……
[/Quote]

恩,这样OK的。
qq120848369 2011-11-21
  • 打赏
  • 举报
回复
       SIG_SETMASK
The set of blocked signals is set to the argument set.

If oldset is non-NULL, the previous value of the signal mask is stored in oldset.

If set is NULL, then the signal mask is unchanged (i.e., how is ignored), but the current value of the signal mask is nevertheless returned in
oldset (if it is not NULL).

The use of sigprocmask() is unspecified in a multithreaded process; see pthread_sigmask(3).


justkk 2011-11-21
  • 打赏
  • 举报
回复
可以调用apue中的一个函数来显示当前信号掩码,验证一下
Figure 10.14. Print the signal mask for the process
#include "apue.h"
#include <errno.h>

void
pr_mask(const char *str)
{
sigset_t sigset;
int errno_save;

errno_save = errno; /* we can be called by signal handlers */
if (sigprocmask(0, NULL, &sigset) < 0)
err_sys("sigprocmask error");

printf("%s", str);
if (sigismember(&sigset, SIGINT)) printf("SIGINT ");
if (sigismember(&sigset, SIGQUIT)) printf("SIGQUIT ");
if (sigismember(&sigset, SIGUSR1)) printf("SIGUSR1 ");
if (sigismember(&sigset, SIGALRM)) printf("SIGALRM ");

/* remaining signals can go here */

printf("\n");
errno = errno_save;
}
qq120848369 2011-11-21
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 justkk 的回复:]

也就是说在信号处理函数中操作信号掩码是没有效果的
[/Quote]

恩,只能这么理解啦。
justkk 2011-11-21
  • 打赏
  • 举报
回复
也就是说在信号处理函数中操作信号掩码是没有效果的
justkk 2011-11-21
  • 打赏
  • 举报
回复
应该是这样的

在调用信号处理函数之前,首先保存了进程的当前信号掩码,也就是“屏蔽SIGINT”
在信号处理函数中解除了信号SIGINT的屏蔽
但是从信号处理函数返回之后,又自动恢复了之前保存的信号掩码
jcback 2011-11-20
  • 打赏
  • 举报
回复
void handler(int sig)
{
if (sig==SIGQUIT)
{
flag=1;
}
...
}
main
{...
if(flag==1)
{
sigset_t s;
sigemptyset(&s);
sigaddset(&s,SIGINT);
sigprocmask(SIG_UNBLOCK,&s,NULL);
}
...
}
m565471801 2011-11-19
  • 打赏
  • 举报
回复
可能我没说清楚
过程大概是这样
1、输入Ctrl+C(发送一个SIGINT信号)
2、这时因为主程序中设置为屏蔽SIGINT,故打印 0100……
3、接着输入Ctrl+\(发送一个SIGQUIT信号)
4、在SIGQUIT信号处理函数中,将SIGINT解除屏蔽,故打印 "recv recv a signal 2",返回主函数打印 0000……
5、问题出现了,这时候既然已经解除SIGINT屏蔽,那么回到主函数中,输入Ctrl+C就应该响应信号,并输出"recv recv a signal 2",但是实际上输出是"0100……",也就是说信号又被屏蔽了。

是不是因为当退出一个信号处理函数时,信号屏蔽字会恢复(转换)为原先的信号屏蔽字?如果这么说,那不是有两个信号屏蔽字,一个是当前进程信号屏蔽字(唯一的),一个是缓存的信号屏蔽字(以便返回时恢复)?
qq120848369 2011-11-19
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 m565471801 的回复:]

感谢qq120848369的回复。从结果上看,可以用"信号处理函数相当于一个线程"来解释,但是查了很多资料,也没这一方面的说明。
测试将singal函数改用sigaction结果也是一样,接着又改成可靠信号也是一样的结果。
[/Quote]

额,只能围观了,希望有解答.
m565471801 2011-11-19
  • 打赏
  • 举报
回复
感谢qq120848369的回复。从结果上看,可以用"信号处理函数相当于一个线程"来解释,但是查了很多资料,也没这一方面的说明。
测试将singal函数改用sigaction结果也是一样,接着又改成可靠信号也是一样的结果。

沭水河畔 2011-11-19
  • 打赏
  • 举报
回复
把singal函数改用sigaction做试试,据说signal可移植性不好。
xuexingyang 2011-11-19
  • 打赏
  • 举报
回复
路过,研究清楚了再告诉你。
qq120848369 2011-11-19
  • 打赏
  • 举报
回复
这个就挺神奇了.

只知道siglongjump这个函数的原理,还有信号处理函数是全局的,信号掩码是线程的,并且子线程是继承父线程的掩码.

第一个SIGINT被主线程阻塞,并且没有其他线程可以接受这个信号,所以信号被悬挂在进程层面。
然后SIGQUIT调用了主线程的信号处理函数,解除了SIGINT的阻塞,于是SIGINT被处理,这说明掩码的确解除了,但我极大的认为此刻信号处理函数相当于一个线程,只是解除了信号处理函数所在线程的掩码,这一刻SIGINT被马上传给该还未销毁的信号处理函数线程,于是被处理。 之后信号处理函数线程退出,再来SIGINT还是被主线程阻塞。

甚至说不定sigaction的行为和signal的行为都不同。 路过
qq120848369 2011-11-18
  • 打赏
  • 举报
回复
kill -SIGQUIT ,我这里打印recv了。
justkk 2011-11-18
  • 打赏
  • 举报
回复
貌似信号屏蔽没有被解除

23,216

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧