#include<signal.h>
int sigaction(int sig, struct sigaction *act , struct sigaction *oact) ;
struct sigaction{
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
}
这个函数可以
:
1. 给一个signal安装一个handler,并且在使用sigaction修改该handler之前,不用reinstall
2. 使用sigaction结构,该结构包含handler,其中可以指定2个handler,一个是使用sigiinfo_t等参数的handler,即支持给handler更多的参数,使其可以知道自己是被什么进程,那个用户,发来的什么信号,发来该信号的具体的原因是什么,当然要像这样,得给sigaction的sa_flags设置SA_SIGINFO标记。
3.使用sigaction的sa_flags标记还可以指定系统调用被这个信号打断后,是直接返回,还是自动restart. 一个典型就是,一般我们不让SIGALRM信号将被打断的系统调用restart,因为SIGALARM一般本来就是用来打断一个block的调用的。
4. 为了模仿老的signal函数的作用,实现unreliable 的类似signal的操作,可以通过给sa_flags设置SA_RESETHAND使handler不会自动reinstall,以及SA_NODEFER标记来使在本信号的handler内部,本信号不被自动block,当然如果你手动在sa_mask中指定要block本信号的话就可以将其block了。
5. 通过使用sigaction结构中的sa_mask,可以在该handler执行的过程中,block一些信号,注意,这个mask是与我们使用sigprocmask设置的mask不同的mask,这个mask的作用范围仅限于本handler函数,而且他不会将我们用sigprocmask设置的mask取消,而仅仅是在其基础上再次将一些信号block掉,当handler结束时,系统会自动将mask恢复成以前的样子,所以这个sigaction中的sa_mask只作用本信号的handler的执行时间。
此外,系统为了避免一个signal handler的执行的时候再次被本signal打断,就自动在本handler执行之前,将本signal加入sigaction的sa_mask中,使本handler的执行过程中,不会受到本signal的嵌套打扰,单是如果本handler对应的信号的确发生了,那么该信号会在本handler执行完后执行,但只执行一次,因为只能记录一次,当然如果在这次新的执行中,又发生了这种情况,应该往复下去。下面就是一段代码,它验证了如下几点:
(1).Sigaction会使handler自动将本signal给临时block
(2).在一个handler执行过程中被临时block掉的信号也会被记录,等handler完成后会被delivery。
下例子中, child 一开始就 pause() 等待信号来临, father 给他发送 SIGUSR1 信号,然后 father 就进入 1 秒钟的睡眠,这是为了等 child 在他的 handler 里面进入睡眠。 Child 受到 SIGUSR1 后。立即执行 handler ,它会进入 5 秒钟的睡眠。那么可见,等 father 睡了 1 秒钟后, child 还在睡眠,并且在其 handler 里面睡眠。此时 father 可以连续发送 2 次 SIGUSR1 给 child ,我们发现 child 并不响应,而是依然睡足她的剩下的时间。 5 秒钟睡眠结束后, child 醒了,它的 handler 退出,系统自动将临时 block 的 SIGUSR1 unblock ,此时发现有 pending 的 SIGUSR1 ,因此将他 delivery 给 child 。于是 child 再次进入 handler ,此时 father 已经不再发送信号了,就等着孩子结束呢。所以 handler 结束后, child 就继续执行,退出,然后 father 也就退出了。#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
void nullhandler( int num )
{
puts( "child received signal" );
puts( "child sleep 5 secs in handler..." );
sleep(5);
puts( "child wake up in handler after 5 secs" );
}
int main()
{
setbuf( stdout, NULL );
int pid = fork();
if( pid == 0 )
{
//child
puts("child started");
printf("%d",getpid());
/*
sigset_t maskset,oldset,oldset1;
sigemptyset( &maskset );
sigaddset( &maskset, SIGUSR1 );
sigprocmask( SIG_BLOCK, &maskset, &oldset );
*/
struct sigaction act, oldact;
act.sa_handler = nullhandler;
sigemptyset( &act.sa_mask );
if( sigaction( SIGUSR1, &act,0 ) < 0 )
{
puts(" child install handler failed");
return -1;
}
/*
puts("child went to sleep ...");
sleep(5);
puts("child wake up...");
sigset_t pendset;
if( sigpending( &pendset ) < 0 )
{
puts("get pending signal failed");
return -1;
}
if( sigismember( &pendset, SIGUSR1 ) )
puts("SIGUSR1 is pending signal");
else
puts("SIGUSR1 is pending signal");
puts("child is unblocking signal");
if( sigprocmask(SIG_UNBLOCK, &maskset, &oldset1 ) < 0 )
puts("unblock signal failed");
else
puts("unblock signal success");
*/
puts("child waiting for signal...");
/*pause函数只是简单地将进程挂起,直至进程接受到一个terminal信号,或是一个信号函数将信号捕捉,并进行调用。*/
pause();
puts("child returnd from signal handler");
puts("child is quiting");
exit(0);
}
sleep(1);
puts( " father send SIGUSR1 once" );
int ret = kill( pid, SIGUSR1 );
puts("father sleep 1 sec to ensure child is now in signal handler");
sleep(1);
puts( " father send SIGUSR1 twice" );
ret = kill( pid, SIGUSR1 );
puts( " father send SIGUSR1 third times" );
ret = kill( pid, SIGUSR1 );
/*等待子进程的结束。*/
waitpid( pid, 0, 0);
puts("father is quiting");
return 0;
}
输出结果:
child started
child waiting for signal...
father send SIGUSR1 once
father sleep 1 sec to ensure child is now in signal handler
child received signal
child sleep 5 secs in handler...
father send SIGUSR1 twice
father send SIGUSR1 third times
child wake up in handler after 5 secs
child received signal
child sleep 5 secs in handler...
child wake up in handler after 5 secs
child returnd from signal handler
child is quiting
father is quiting感谢大牛文章的指导:http://blog.chinaunix.net/space.php?uid=12072359&do=blog&id=2961076