参数signo是要检测或修改器具体动作的信号编号。如果act指针为非空,则要修改其动作。
如果oact不为空,则系统经由oact指针返回该信号的上一个动作。
struct sigaction {
void (*sa_handler)(int); /*信号处理函数*/
sigset_t sa_mask; /*additional signals to block, sa_mask字段是一个信号集,在调用该信号处理函数之前,这一信号集要加到进程的信号屏蔽字中。
仅当从信号处理函数返回时再讲进程的信号屏蔽字复位为原先值。这样,在调用信号处理程序时就能阻塞某些信号。*/
int sa_flags; /*指定对信号处理的各个选项,如SA_RESTART,此信号中断的系统调用会自动重启动*/
void (*sa_sigaction)(int, siginfo_t *,void *);
};
一旦对给定的信号设置了一个动作,那么在调用sigaction显示地改变它之前,该设置就一直有效。
用sigaction实现的signal函数
-
void (*signal(int signo,void(*func)(int)))(int)
-
{
-
struct sigaction act, oact;
-
-
setsigempty(&act.sa_mask);
-
act.sa_handler = func;
-
act.sa_flags = 0;
-
/*对除SIGALRM以外的所有信号,我们都有意尝试设置SA_RESTART标志,于是这些信号中断的系统调用都能重启动。*/
-
if (signo == SIGALARM) {
-
#ifdef SA_INTERRUPT
-
act.sa_flags |= SA_INTERRUPT;
-
#endif
-
} else {
-
#ifdef SA_RESTART
-
act.sa_flags |= SA_RESTART;
-
#endif
-
}
-
if(sigaction(signo,&act,&oact) < 0) {
-
return SIGERR;
-
}
-
return oact.sa_handler;
-
}
用sigaction实现的signal函数(目前linux系统里面默认的signal函数已经是sigaction实现的版本了)
在信号处理处理函数被调用时,操作系统建立的新信号屏蔽字包含正在被递送的信号。
因此保证了在处理一个给定的信号时,如果这种信号再次发生,那么它会被阻塞到对前一个信号的处理结束为止.
同一种信号多次发生,通常并不讲它们排队,所以如果在某种信号被阻塞时它发生了五次,
那么对这种信号解除阻塞后,其信号处理函数通常只会被调用一次。
举例:
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <signal.h>
-
#include <unistd.h>
-
static void sig_int(int);
-
-
int main(void)
-
{
-
if(signal(SIGINT,sig_int) == SIG_ERR)
-
perror("can't catch SIGINT\n");
-
-
for(;;)
-
pause;
-
}
-
-
void sig_int(int signo)
-
{
-
printf("received SIGINT\n");
-
sleep(10);
-
printf("after sleep 10s\n");
-
}
-
[root@localhost signal]#
编译运行:
-
[root@localhost signal]# gcc -g signal.c -o signal
-
[root@localhost signal]# ./signal
-
^Creceived SIGINT -----输入一个CTRL+C,打印出received SIGINT
-
^C^C^C^C^C -----持续输入5次CTRL+C,由于在上面一次CTRL+C的信号处理函数中,这5次CTRL+C被阻塞
-
-
-
/*空白处为输入回车*/
-
-
-
-
after sleep 10s ----过了10s,第一次的CTRL+C信号处理函数退出
-
received SIGINT ----直接就输出了received SIGINT, 只是一次而不是5次。
-
after sleep 10s ----过了10s,信号处理函数再次退出