#include <signal.h>
sighandler_t signal(int signum, sighandler_t handler);
第一参数是信号
第二个参数是信号处理器:
1.可以是SIG_DFL,信号的默认动作
2. 可以是SIG_IGN,忽略该信号
3. 一个带有一个整型参数的处理函数。
#include <signal.h>
int sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact);
signum 要处理的信号
act 指针,指向描述操作的结构 如何响应信号的结构体
oldact 指针,指向描述被替换操作的结构 被替换的处理设置的结构体
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
};
进程该如何处理信号(早期的信号处理机制):
进程可以通过signal系统调用来告诉内核该怎么去处理信号
1.接受默认处理
按照信号本来的意图区处理 signal(SIGINT,SIG_DFL)
2.忽略信号
signal(SIGINT,SIG_IGN) 忽略SIGINT信号
3.调用一个函数
signal(SIGINT,functionname)
2.早期的信号处理机制存在的问题
一:信号处理函数每次调用后都要被禁用(根据系统的不同而不不同)
二:不知道信号被发送的原因
三:处理函数中不能安全地阻塞其他信号
四:不支持信号中断,信号会被阻塞。(不同的系统可能不同)
3.POSIX信号处理函数
POSIX提供了sigaction这个信号处理函数。相应的提供了一个sigaction结构体。
这个结构体中的sa_flags定义了一些如何处理早期信号机制存在的问题的标志位,可以通过与操作进行组合。
下面仅列出部分标志位:
SA_RESETHAND 当处理函数被调用时重置而不是禁用
SA_NODEFER 关闭信号阻塞,允许递归调用信号
SA_RESTAAT 当系统调用针对一些慢速设备或类似的系统调用重新开始而不是返回
SA_SIGINFO 指明使用sa_sigaction函数的值,,如果这个位没有设置,那么就使用sa_handle指向的函数的值,如果sa_sigaction被使用了,那么传递给函数的将不只是信号的编号,而是信号产生的原因和条件的结构体。
下面的一个例子将演示如何使用sigaction来实现安全的阻塞其它信号
#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
#define INPUTLEN 100
int main ( int argc, char *argv[] )
{
struct sigaction newhandler;
#定义一个信号集
sigset_t blocked;
char x[INPUTLEN];
#设置信号处理函数
newhandler.sa_handler = inthandler;
#设置信号处理函数重置
newhandler.sa_flags = SA_RESETHAND|SA_RESTART
#清空信号集
sigemptyset(&blocked);
#添加SIGQUIT信号集
sigaddset(&block,SIGQUIT);
#设置屏蔽的信号集
newhandler.sa_mask = blocked;
#装载信号
if(sigaction(SIGINT,&newhandler,NULL) == -1)
perror("sigaction");
else
while(1){
fgets(x,INPUTLEN,stdin);
printf("INput: %s",x);
}
return EXIT_SUCCESS;
}
/* ---------- end of function main ---------- */
void inthandler (int s)
{
printf("Called with signal %d\n",s);
sleep(s);
printf("done handling signal %d\n",s);
} /* ----- end of function inthandler ----- */