什么是信号?

信号(Signal)是操作系统内核用来通知进程发生了某种事件的机制。可以把信号想象成手机的来电通知:

🎯 场景1:当你按下 Ctrl+C 时,终端程序会收到一个 SIGINT 信号(就像手机接到电话)

🎯 场景2:程序访问无效内存地址时,系统会发送 SIGSEGV 信号(就像手机收到电池过热的警告)

🎯 场景3:当一个子进程结束时,内核会向父进程发送 SIGCHLD 信号(就像手机收到短信通知)

信号是软件中断的一种形式,允许进程中断当前执行流程来处理特定事件。

<signal.h>的功能

这个头文件提供了信号处理所需的函数、类型和常量,主要包括:

  • 定义信号类型:如 SIGINT、SIGSEGV 等
  • 注册信号处理函数:告诉系统当特定信号到来时应该执行什么操作
  • 发送信号:允许进程向自己或其他进程发送信号
  • 阻塞信号:暂时阻止某些信号被接收

信号处理的哲学

信号处理就像消防演习 – 平时定义好应对突发事件的方案(信号处理函数),当警报响起(信号到来)时,程序会暂停当前工作,执行预定方案,完成后继续原来的任务。

常用信号类型

信号名称 默认操作 触发场景 数值
SIGINT 终止进程 用户按下中断键(Ctrl+C) 2
SIGQUIT 终止+核心转储 用户按下退出键(Ctrl+\) 3
SIGKILL 终止进程 强制杀死进程(无法捕获或忽略) 9
SIGSEGV 终止+核心转储 无效内存访问(段错误) 11
SIGTERM 终止进程 优雅终止进程(系统关机时常用) 15
SIGALRM 终止进程 定时器超时(闹钟信号) 14
SIGCHLD 忽略 子进程状态改变 17

注册信号处理函数

使用 signal() 函数告诉系统:”当某个信号出现时,请执行我指定的函数”。

函数原型

void (*signal(int sig, void (*func)(int)))(int);

这个看起来复杂的声明可以理解为:

signal(信号编号, 处理函数) -> 返回原来的处理函数

参数说明

  • sig:要处理的信号(如 SIGINT)
  • func:信号处理函数指针,也可以是特殊值:
    • SIG_IGN:忽略该信号
    • SIG_DFL:恢复默认处理

示例:捕获SIGINT信号

#include <stdio.h> #include <signal.h> // 信号处理函数 void sigint_handler(int sig) { printf("\n接收到SIGINT信号(%d)! 但我不退出,按Ctrl+\\退出程序\n", sig); } int main() { // 注册SIGINT信号处理函数 signal(SIGINT, sigint_handler); printf("按Ctrl+C试试...\n"); while(1) { // 无限循环,等待信号 } return 0; }

运行效果:按Ctrl+C不会终止程序,而是执行自定义操作

发送信号

可以使用 raise() 函数向当前进程发送信号:

函数原型

int raise(int sig);

示例:给自己发送信号

#include <stdio.h> #include <signal.h> void alarm_handler(int sig) { printf("叮铃铃! 闹钟响了 (SIGALRM)\n"); } int main() { signal(SIGALRM, alarm_handler); printf("设置3秒后闹钟...\n"); // 3秒后发送SIGALRM信号 alarm(3); printf("等待闹钟响起...\n"); pause(); // 暂停直到收到信号 return 0; }

输出:3秒后打印”叮铃铃! 闹钟响了 (SIGALRM)”

注意:

kill()函数可以向其他进程发送信号,但需要知道目标进程ID(PID),使用时需谨慎。

信号处理的重要注意事项

1. 异步执行风险

信号处理函数可能在程序运行的任何时刻被调用(异步执行),因此在处理函数中应避免调用不可重入函数(如printf、malloc等)。

2. 信号处理函数的限制

信号处理函数应该尽量简单,只设置标志位或执行简单操作。复杂操作应在主循环中处理。

3. 无法捕获的信号

SIGKILL(9) 和 SIGSTOP(19) 信号无法被捕获、阻塞或忽略,它们总是立即终止或暂停进程。

4. 信号处理函数重置

某些系统在信号处理函数执行后,会将该信号的处理方式重置为默认行为。为避免这种情况,可以在处理函数中重新注册。

5. 全局变量与volatile

在信号处理函数和主程序之间共享的变量应声明为volatile,防止编译器优化导致意外结果。