注册SIGTERM和SIGHUP信号,通过sigaction设置处理函数,修改volatile标志位,主循环检测标志并退出,最后执行清理操作。

在 Linux 开发中,程序常常需要在接收到系统信号时进行优雅退出,比如释放资源、关闭文件描述符、保存状态等。常见的信号包括 SIGTERM(请求终止)和 SIGHUP(终端挂起或控制进程结束)。正确处理这些信号可以避免数据丢失或资源泄漏。
使用 signal() 或更推荐的 sigaction() 函数注册信号处理函数。后者更可靠,能避免某些平台上的默认行为问题。
示例:用 sigaction 捕获 SIGTERM 和 SIGHUP
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
<p>volatile sig_atomic_t keep_running = 1;</p><p>void handle_signal(int sig) {
if (sig == SIGTERM || sig == SIGHUP) {
keep_running = 0; // 安全地通知主循环退出
}
}</p><p>void setup_signal_handlers() {
struct sigaction sa;
sa.sa_handler = handle_signal;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0; // 不使用 SA_RESTART,以便阻塞调用能及时中断</p><pre class="brush:php;toolbar:false;"><pre class="brush:php;toolbar:false;">sigaction(SIGTERM, &sa, NULL);
sigaction(SIGHUP, &sa, NULL);}
大多数守护进程或服务程序运行在一个主循环中。通过全局标志变量判断是否继续运行。
示例:
int main() {
setup_signal_handlers();
<pre class="brush:php;toolbar:false;"><pre class="brush:php;toolbar:false;">while (keep_running) {
// 执行业务逻辑,例如 accept、read、定时任务等
// 假设有一个非繁忙等待
for (int i = 0; i < 10 && keep_running; i++) {
sleep(1); // 实际中可能是 poll/epoll 等
}
printf("Working...\n");
}
// 走到这一步说明收到退出信号
printf("Shutting down gracefully...\n");
// 执行清理操作
cleanup_resources();
return 0;}
信号处理函数中只能调用异步信号安全(async-signal-safe)的函数,如 write、_exit,不能调用 printf、malloc 等。
因此,最佳实践是仅在信号处理函数中修改 volatile sig_atomic_t 类型的标志位,把具体清理工作留给主循环完成。
常见注意事项:
可通过命令行发送信号验证行为:
# 查看进程 PID ps aux | grep your_program <h1>发送 SIGTERM</h1><p>kill -TERM <pid></p><h1>或发送 SIGHUP</h1><p>kill -HUP <pid>
观察程序是否输出清理信息并正常退出。
基本上就这些。关键是注册信号、设置标志、主循环检查、执行清理。不复杂但容易忽略细节导致无法优雅退出。
以上就是Linux 开发:如何处理信号 (SIGTERM, SIGHUP) 实现优雅退出的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号