在一个程序收到某些信号后,程序都会自动去执行默认的操作,但大多的操作都会导致程序异常退出,除了前文我们介绍的阻塞信号以外,我们还可以对信号进行捕获(拦截)处理,让被捕获的信号去执行我们已经编写好的函数中,这样可以帮我们处理太多的问题。
C语言库函数中,提供了一个信号捕获函数,如下:
代码语言:javascript复制typedef void (*sighandler_t)(int)
sighandler_t signal(int signum, sighandler_t handler
该函数的第一个参数是我们要发送的信号,第二个参数是让我们提供一个函数指针,这个函数指针的原型就是上面 typedef 的原型,我们根据原型定义一个函数,然后将函数名传递到第二个参数,就可以成功调用这个函数了。当函数执行成功,会将第一个参数中的信号捕获并让其指向我们自己编写的处理函数。具体代码如下:
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
// 自定义的信号处理函数
void mySigAction(int num)
{
printf(“recv sig number %d, mySigAction function…n”, num);
}
int main(int argc, char* argv[])
{
// 将 SIGINT 信号捕获,让程序接受到该信号后转到 mySigAction 函数
signal(SIGINT, mySigAction);
while (1)
{
printf(“mian printf…n”);
sleep(1);
}
return 0;
}
以上代码执行的效果如下:
这是 C 语言库函数提供给我们的方法,除了这个方法外,我们还可以使用 linux/unix 系统提供给我们的系统函数来实现如上功能:
代码语言:javascript复制#include <stdio.h>
#include <unistd.h>
#include <signal.h>
void dosig(int num)
{
printf(“num = %dn”, num);
printf(“Hello itcastn”);
}
int main(int argc, char* argv[])
{
struct sigaction act, oldact;
// 设定处理函数
act.sa_handler = dosig;
// 如果不需要对新的阻塞列表进行修改,那么将这个掩码列表全部置零
sigemptyset(&act.sa_mask);
// 设定捕获信号的处理方式为 sa_handler 方式
act.sa_flags = 0;
// 捕获信号,并传递捕获后执行的操作结构体
sigaction(SIGINT, &act, &oldact);
while (1)
{
printf(“************n”);
sleep(1);
}
return 0;
}
与 C 语言库函数一样,我们实现了同样的功能,但是系统函数的功能更加强大,他允许我们保存原有的信号处理过程的状态(sigaction第三个参数),如果需要恢复的时候,可以使用这个保存下来的结构体恢复到原来的信号处理过程。