sigaction如何设置信号执行函数时屏蔽和屏蔽本身信号.

yanjinbin0 2010-04-08 04:50:46
我想做个测试例题,如何设置sa_mask让信号函数执行时,可以屏蔽和不屏蔽本身信号.
测试代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>

static void catch_signal(int);

int main(int argc, char* argv[])
{
struct sigaction act;
struct itimerval value;
act.sa_handler = catch_signal; //设置信号处理函数
act.sa_flags = 0; //设置信号处理标志位
sigemptyset(&act.sa_mask); //清空信号集,信号函数执行过程不屏蔽本身信号 ==1==
sigaction(SIGALRM,&act,NULL); //捕获定时信号


//设置一个定时器,1s发送一个定时信号
value.it_value.tv_sec=1;
value.it_value.tv_usec=0;
value.it_interval.tv_sec = 1;
value.it_interval.tv_usec = 0;
if(setitimer(ITIMER_REAL,&value,NULL)<0){
perror("setitimer");
}

while(1){
pause(); //让进程暂停直到信号的出现
}
return 0;
}

//所有信号处理函数
static void catch_signal(int signo)
{
printf("SIGALRM \n");
sleep(5); //用于测试函数执行过程是否会屏蔽本身信号,如果1s输出一次说明未屏蔽
//如果5s输出一次说明已屏蔽
return;
}


1.但在实际测试当中发现,不管我注释 sigemptyset(&act.sa_mask); 这行,还是不注释该行,都是5s输出一次,
但我想在信号函数执行时不屏蔽本身信号应该怎么做呢(也就是1s就输出一次).

2.我还试过signal(SIGALRM,catch_signal);直接signal来设置信号处理函数,发现都是5s输出一次,那是否说明signal设置在信号处理函数时,屏蔽了本身信号.

3.还是说我的测试方法误????????????

欢迎大家指点,谢谢.....
...全文
389 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
yanjinbin0 2010-04-09
  • 打赏
  • 举报
回复
sigaction(SIGALRM,&act,NULL);
这样绑定一个信号处理函数

和这种方式绑定
signal(SIGALRM,catch_signal);


谁能跟我说这两种方式有什么不一样,我想详细了解下.
或则在那能找到signal实现函数.
yanjinbin0 2010-04-09
  • 打赏
  • 举报
回复
但我有用connect来做了下测试,又发现只要设置了SA_RESTART标志位,就不会在出现ENITR错误了.
但不知道为什么sleep被打断但不重启......
yanjinbin0 2010-04-09
  • 打赏
  • 举报
回复
设置了SA_RESTART发现没有效果.
测试代码如下:
int main(int argc, char* argv[])
{
struct sigaction act;
struct itimerval value;
act.sa_handler = catch_signal; //设置信号处理函数
act.sa_flags = 0; //设置信号处理标志位
act.sa_flags |= SA_RESTART;

sigemptyset(&act.sa_mask); //清空信号集,sa_mask默认在处理信号过程中屏蔽本身信号
sigaction(SIGALRM,&act,NULL); //捕获定时信号


//设置一个定时器
value.it_value.tv_sec=1; //延迟1s发送SIGALRM信号
value.it_value.tv_usec=0; //micro sec 微秒(10^(-6) sec) 50ms检查一次
value.it_interval.tv_sec = 1; //延迟1s执行函数
value.it_interval.tv_usec = 0;
if(setitimer(ITIMER_REAL,&value,NULL)<0){
perror("setitimer");
}
printf("sleep start\n");
sleep(10); //看是否打断
printf("sleep stop\n");

while(1){
pause(); //让进程暂停直到信号的出现
}
return 0;
}

事实我发现,sleep在测试的时候还是被打断了,没等待10s...
这也是说明虽然置了标志位SA_RESTART,但函数还一样被打断,并没有重启啊........
mymtom 2010-04-09
  • 打赏
  • 举报
回复
因为sleep不会返回-1, 也不会设置errno,
但是pause()和nanosleep会,行为和read一样.
也许是历史原因sleep时收到信号确实不会重启.
#include <unistd.h>
unsigned int sleep(unsigned int seconds);

RETURN VALUE

If sleep() returns because the requested time has elapsed, the value returned will be 0. If sleep() returns because of premature arousal due to delivery of a signal, the return value will be the "unslept" amount (the requested time minus the time actually slept) in seconds.

ERRORS

No errors are defined.


mymtom 2010-04-08
  • 打赏
  • 举报
回复
第一种方式提供一种标准的可控制的可靠信号处理方式,是Posix推荐的方式。
第二方式是Unix最原始的不可靠信号处理函数,在不同的系统上行为差别很大。

至于提到的“程序里面用第一种方式绑定但是发现,好多函数如connect,fgets这些阻塞函数都会被SIGALARM信号中断掉,产生一个ENITR错误.”的问题.

可以用
act.sa_flags |= SA_RESTART

SA_RESTART
This flag affects the behaviour of interruptible functions; that is, those specified to fail with errno set to [EINTR]. If set, and a function specified as interruptible is interrupted by this signal, the function will restart and will not fail with [EINTR] unless otherwise specified. If the flag is not set, interruptible functions interrupted by this signal will fail with errno set to [EINTR].
yanjinbin0 2010-04-08
  • 打赏
  • 举报
回复
act.sa_handler = catch_signal;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
sigaction(SIGALRM,&act,NULL);
这样绑定一个信号处理函数

和这种方式绑定
signal(SIGALRM,catch_signal);

这两种方式有什么区别..

我现在程序里面用第一种方式绑定但是发现,好多函数如connect,fgets这些阻塞函数都会被SIGALARM信号中断掉,产生一个ENITR错误.

但是我试着用第二种方式来绑定的化,就不会有这么多ENITR错误发生.

我就想这到底是怎么回事,这两种绑定有什么区别.我应该如何消除这种区别.

这个有人遇到过这样的情况吗?????

mymtom 2010-04-08
  • 打赏
  • 举报
回复
加一句。

act.sa_flags = 0;
act.sa_flags |= SA_NODEFER;

不过这个例子可能会发生栈溢出,因为在信号处理函数未执行完毕又收到信号。
yanjinbin0 2010-04-08
  • 打赏
  • 举报
回复
有人指点下吗?

23,125

社区成员

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

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