C 语言信号处理
信号(Signal)是操作系统用来通知进程发生了某种事件的一种机制。在C语言中,信号处理是系统编程的重要组成部分,允许程序对特定事件(如用户按下Ctrl+C)做出响应。本文将详细介绍C语言中的信号处理机制,并通过代码示例和实际案例帮助你理解其应用。
什么是信号?
信号是操作系统向进程发送的一种异步通知。它可以由硬件异常、用户输入、或其他进程触发。常见的信号包括:
SIGINT
:用户按下Ctrl+C时发送的信号。SIGTERM
:请求终止进程的信号。SIGSEGV
:非法内存访问时触发的信号。
信号处理允许程序捕获这些信号并执行自定义操作,而不是默认行为(如终止进程)。
信号处理函数
在C语言中,信号处理的核心函数是 signal()
和 sigaction()
。下面我们将逐步介绍这些函数的使用方法。
1. 使用 signal()
函数
signal()
函数用于设置信号处理函数。它的原型如下:
#include <signal.h>
void (*signal(int signum, void (*handler)(int)))(int);
signum
:要处理的信号编号(如SIGINT
)。handler
:信号处理函数,接收一个整数参数(信号编号)。
示例:捕获 SIGINT
信号
以下代码展示了如何捕获 SIGINT
信号并执行自定义操作:
#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()
是更强大的信号处理函数,提供了更多的控制选项。它的原型如下:
#include <signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
signum
:要处理的信号编号。act
:指向struct sigaction
的指针,包含新的信号处理配置。oldact
:用于保存旧的信号处理配置。
示例:使用 sigaction()
捕获 SIGTERM
信号
以下代码展示了如何使用 sigaction()
捕获 SIGTERM
信号:
#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
信号,程序可以在终止前执行清理操作(如关闭文件、释放资源)。
void cleanup() {
printf("执行清理操作...\n");
}
void handle_sigterm(int signum) {
cleanup();
exit(0);
}
2. 防止程序意外终止
通过捕获 SIGSEGV
信号,程序可以在发生段错误时记录日志或尝试恢复。
void handle_sigsegv(int signum) {
printf("发生段错误!\n");
// 记录日志或尝试恢复
}
总结
信号处理是C语言系统编程中的重要概念,允许程序对特定事件做出响应。本文介绍了如何使用 signal()
和 sigaction()
函数捕获和处理信号,并通过实际案例展示了其应用场景。
信号处理函数应尽量简短,避免执行复杂操作,以免影响程序的稳定性。
附加资源与练习
推荐资源
- GNU C Library: Signal Handling
- 《UNIX环境高级编程》(Advanced Programming in the UNIX Environment)
练习
- 编写一个程序,捕获
SIGALRM
信号并实现一个简单的定时器。 - 修改示例代码,使其在捕获
SIGINT
信号后退出程序。 - 使用
sigaction()
实现一个信号处理函数,屏蔽其他信号直到当前信号处理完成。
通过实践这些练习,你将更深入地理解C语言信号处理的机制和应用。