跳到主要内容

C 语言信号处理

信号(Signal)是操作系统用来通知进程发生了某种事件的一种机制。在C语言中,信号处理是系统编程的重要组成部分,允许程序对特定事件(如用户按下Ctrl+C)做出响应。本文将详细介绍C语言中的信号处理机制,并通过代码示例和实际案例帮助你理解其应用。

什么是信号?

信号是操作系统向进程发送的一种异步通知。它可以由硬件异常、用户输入、或其他进程触发。常见的信号包括:

  • SIGINT:用户按下Ctrl+C时发送的信号。
  • SIGTERM:请求终止进程的信号。
  • SIGSEGV:非法内存访问时触发的信号。

信号处理允许程序捕获这些信号并执行自定义操作,而不是默认行为(如终止进程)。


信号处理函数

在C语言中,信号处理的核心函数是 signal()sigaction()。下面我们将逐步介绍这些函数的使用方法。

1. 使用 signal() 函数

signal() 函数用于设置信号处理函数。它的原型如下:

c
#include <signal.h>

void (*signal(int signum, void (*handler)(int)))(int);
  • signum:要处理的信号编号(如 SIGINT)。
  • handler:信号处理函数,接收一个整数参数(信号编号)。

示例:捕获 SIGINT 信号

以下代码展示了如何捕获 SIGINT 信号并执行自定义操作:

c
#include <stdio.h>
#include <signal.h>
#include <unistd.h>

void handle_sigint(int signum) {
printf("捕获到 SIGINT 信号!\n");
}

int main() {
signal(SIGINT, handle_sigint); // 设置信号处理函数
while (1) {
printf("运行中...\n");
sleep(1);
}
return 0;
}

输入/输出示例:

运行中...
运行中...
^C捕获到 SIGINT 信号!
运行中...
备注

按下 Ctrl+C 会触发 SIGINT 信号,程序会调用 handle_sigint() 函数并继续运行。

2. 使用 sigaction() 函数

sigaction() 是更强大的信号处理函数,提供了更多的控制选项。它的原型如下:

c
#include <signal.h>

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
  • signum:要处理的信号编号。
  • act:指向 struct sigaction 的指针,包含新的信号处理配置。
  • oldact:用于保存旧的信号处理配置。

示例:使用 sigaction() 捕获 SIGTERM 信号

以下代码展示了如何使用 sigaction() 捕获 SIGTERM 信号:

c
#include <stdio.h>
#include <signal.h>
#include <unistd.h>

void handle_sigterm(int signum) {
printf("捕获到 SIGTERM 信号!\n");
}

int main() {
struct sigaction sa;
sa.sa_handler = handle_sigterm;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;

sigaction(SIGTERM, &sa, NULL); // 设置信号处理函数

while (1) {
printf("运行中...\n");
sleep(1);
}
return 0;
}

输入/输出示例:

运行中...
运行中...
捕获到 SIGTERM 信号!
运行中...
提示

sigaction() 提供了更细粒度的控制,例如屏蔽其他信号或设置标志位。


实际应用场景

信号处理在实际编程中有广泛的应用,以下是一些常见场景:

1. 优雅地终止进程

通过捕获 SIGTERM 信号,程序可以在终止前执行清理操作(如关闭文件、释放资源)。

c
void cleanup() {
printf("执行清理操作...\n");
}

void handle_sigterm(int signum) {
cleanup();
exit(0);
}

2. 防止程序意外终止

通过捕获 SIGSEGV 信号,程序可以在发生段错误时记录日志或尝试恢复。

c
void handle_sigsegv(int signum) {
printf("发生段错误!\n");
// 记录日志或尝试恢复
}

总结

信号处理是C语言系统编程中的重要概念,允许程序对特定事件做出响应。本文介绍了如何使用 signal()sigaction() 函数捕获和处理信号,并通过实际案例展示了其应用场景。

警告

信号处理函数应尽量简短,避免执行复杂操作,以免影响程序的稳定性。


附加资源与练习

推荐资源

练习

  1. 编写一个程序,捕获 SIGALRM 信号并实现一个简单的定时器。
  2. 修改示例代码,使其在捕获 SIGINT 信号后退出程序。
  3. 使用 sigaction() 实现一个信号处理函数,屏蔽其他信号直到当前信号处理完成。

通过实践这些练习,你将更深入地理解C语言信号处理的机制和应用。