在C语言编程中,信号是操作系统用于通知进程发生了某种事件的一种异步通信方式,比如用户按下中断键、进程执行出错等情况都会触发信号。signal函数是C语言标准库中用于注册信号处理函数的接口,通过它可以指定当特定信号发生时进程要执行的操作。

信号与signal函数基础
常见的系统信号包括SIGINT(用户按下Ctrl+C触发)、SIGTERM(终止进程信号)、SIGSEGV(段错误信号)等,每个信号都有默认的处理动作,比如终止进程、忽略信号等。signal函数的作用就是修改某个信号的默认处理动作,将其替换为我们自定义的处理逻辑。
signal函数的原型定义在<signal.h>头文件中,语法如下:
void (*signal(int sig, void (*func)(int)))(int);这个原型看起来比较复杂,我们可以将其拆解为两个部分:
- 第一个参数sig:要注册处理函数的信号编号,比如SIGINT、SIGTERM等,这些宏定义在<signal.h>中。
- 第二个参数func:指向信号处理函数的指针,这个处理函数需要接收一个int类型的参数(即触发的信号编号),返回值为void。如果func取值为SIG_IGN则表示忽略该信号,取值为SIG_DFL则表示恢复信号的默认处理动作。
signal函数的基本使用步骤
使用signal函数实现信号处理通常分为三个步骤:
- 包含必要的头文件,主要是<signal.h>和<stdio.h>、<stdlib.h>等常用头文件。
- 定义信号处理函数,函数的参数和返回值需要符合signal函数的要求。
- 在主函数中调用signal函数,为指定的信号注册我们定义的处理函数。
完整示例代码
下面是一个捕获SIGINT信号的示例,当用户按下Ctrl+C时,不会直接终止进程,而是执行我们自定义的处理逻辑:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
// 自定义信号处理函数
void signal_handler(int sig) {
if (sig == SIGINT) {
printf("n捕获到SIGINT信号,进程不会直接退出,3秒后继续运行n");
sleep(3);
}
}
int main() {
// 为SIGINT信号注册自定义处理函数
if (signal(SIGINT, signal_handler) == SIG_ERR) {
printf("注册信号处理函数失败n");
return 1;
}
printf("进程启动,PID为%d,按下Ctrl+C测试信号捕获n", getpid());
// 让进程持续运行,等待信号触发
while (1) {
sleep(1);
}
return 0;
}
编译运行上述代码后,在终端按下Ctrl+C,会看到我们定义的处理逻辑被执行,进程不会直接退出,等待3秒后继续运行。如果要终止进程,可以按下Ctrl+\触发SIGQUIT信号,该信号的默认处理动作是终止进程并生成核心转储文件。
signal函数的使用注意事项
- signal函数的可移植性问题:不同操作系统对signal函数的实现存在差异,比如在BSD系统中,信号处理函数执行后会自动将信号的处理动作恢复为默认,而System V系统中不会。如果需要更好的可移植性,建议使用sigaction函数替代signal函数。
- 信号处理函数中不要调用不可重入函数:信号处理函数是异步执行的,如果在处理函数中调用了不可重入函数(比如printf、malloc等),可能会导致程序出现不可预期的行为,尽量只做简单的标志位修改等操作。
- 信号的不可靠性:早期的信号机制是不可靠的,信号可能会丢失,同一信号在处理函数执行期间再次触发可能不会被捕获,这个问题在后续的POSIX标准中得到了改进,但使用时仍需要注意。
signal函数与sigaction函数的对比
虽然signal函数使用简单,但在实际生产环境中更推荐使用sigaction函数,两者的对比如下:
| 对比项 | signal函数 | sigaction函数 |
|---|---|---|
| 可移植性 | 较差,不同系统实现有差异 | 较好,符合POSIX标准,各系统实现一致 |
| 功能丰富度 | 功能简单,仅能注册处理函数 | 功能丰富,可以指定信号处理时的掩码、信号传递的额外信息等 |
| 信号处理稳定性 | 可能存在信号丢失、处理函数重置等问题 | 信号处理行为可控,不会出现意外的处理动作重置 |
如果只是做简单的信号测试或者编写临时的小程序,使用signal函数就足够了,如果是正式的项目开发,建议优先选择sigaction函数来实现信号处理逻辑。
signal函数C语言信号处理signal_handler信号注册修改时间:2026-06-20 22:45:21