Linux信号处理:深入理解sigaction函数

需积分: 11 0 下载量 127 浏览量 更新于2024-07-13 收藏 804KB PPT 举报
本文主要介绍了Linux系统中的信号处理机制,特别是使用`sigaction`函数进行信号处理的方法。信号是操作系统用于通知进程发生特定事件的一种机制,它可以是系统自动产生的,也可以由进程之间互相发送。在Linux中,信号处理主要包括信号的生成、捕获以及相应的处理函数。 一、信号的基本概念 信号是Unix和Linux系统中的一种异步通信方式,当进程遇到异常、错误或者需要执行特定操作时,系统会发送信号给进程。例如,用户按下Ctrl+C会产生SIGINT信号,导致进程终止。进程接收到信号后可以采取默认行为,如终止、忽略或者自定义的行为。 二、信号的种类 信号的名称通常以SIG开头,常见的信号包括SIGINT(中断)、SIGTERM(终止请求)、SIGKILL(强制终止)、SIGSEGV(非法内存访问)等。不同的信号对应着不同的系统事件和进程响应。更多信号类型可以在`signal.h`头文件中查看。 三、信号处理函数——`signal`与`sigaction` 1. `signal`函数:这是一个标准C库中的函数,用于注册信号处理函数。它接受一个信号编号和一个处理函数指针,返回之前设置的信号处理函数。但是`signal`函数有一些限制,比如不能同时保存旧的处理函数,并且不支持SA_RESTART标志,可能导致某些系统调用被意外打断。 2. `sigaction`函数:POSIX标准提供的更强大、更灵活的信号处理函数。它可以设置新的信号处理函数,同时保留旧的处理函数,支持更多的选项,如SA_RESTART,使得被信号中断的系统调用可以自动重试。`sigaction`函数的原型如下: ```c int sigaction(int signo, const struct sigaction *restrict act, struct sigaction *restrict oact); ``` 其中,`signo`是信号编号,`act`指向新定义的信号处理行为结构体,`oact`如果非NULL,则会存储当前的信号处理行为。 四、`struct sigaction`结构体 `struct sigaction`定义了信号处理的行为,包括信号处理函数、信号标志以及信号掩码等。例如: ```c struct sigaction { void (*sa_handler)(int); // 信号处理函数 sighandler_t sa_sigaction; // 对于SA_SIGINFO标志,使用此字段 sigset_t sa_mask; // 信号掩码,在处理信号时阻止这些信号 int sa_flags; // 信号标志,如SA_RESTART void (*sa_restorer)(void); // 用于旧版本的信号恢复函数 }; ``` 五、使用`sigaction`函数的例子 以下是一个简单的`sigaction`函数使用的例子,将SIGINT信号(由Ctrl+C产生)的处理函数设置为`ouch`,当进程接收到SIGINT信号时,`ouch`函数会被调用: ```c #include <signal.h> #include <stdio.h> #include <unistd.h> void ouch(int sig) { printf("\nOUCH! - I got signal %d\n", sig); // 恢复SIGINT的默认行为 (void)sigaction(SIGINT, NULL, NULL); } int main() { // 使用sigaction设置SIGINT信号的处理函数为ouch struct sigaction act; act.sa_handler = ouch; sigemptyset(&act.sa_mask); act.sa_flags = 0; if (sigaction(SIGINT, &act, NULL) == -1) { perror("sigaction"); return 1; } // 主程序的其他逻辑... while (1) { // ... } return 0; } ``` 总结来说,`sigaction`函数是Linux系统中处理信号的关键工具,它提供了更高级别的控制,允许开发者定制信号处理的行为,包括保存旧的处理函数、设置信号掩码以及选择不同的信号处理模式。这对于编写复杂、健壮的多线程或守护进程程序非常重要。