linux中可自定义处理sigint(2号信号)以实现优雅退出,但sigkill(9号)和sigstop(19号)无法捕获;需用sigaction()注册异步信号安全的处理函数,避免不安全操作。

Linux中捕获并处理SIGINT(编号2,通常由Ctrl+C触发)的关键,是让进程在收到该信号时不直接终止,而是执行你指定的逻辑——比如清理资源、保存状态或优雅退出。
注册自定义信号处理函数
用signal()或更推荐的sigaction()函数告诉内核:当SIGINT到来时,调用你的处理函数。
-
signal(SIGINT, handler)最简方式,但有移植性和竞态风险 -
sigaction()更健壮,能精确控制屏蔽字、是否重启被中断的系统调用等 - 处理函数原型必须是
void handler(int sig),参数为接收到的信号编号
注意不可捕获的例外信号
SIGINT可以自由捕获和自定义,但有两个信号永远例外:
- SIGKILL(9号):强制终止,内核直杀,无法忽略、阻塞或捕捉
- SIGSTOP(19号):强制暂停,同样不能被程序干预
这意味着你对SIGINT的处理逻辑,不会影响这两个信号的行为。
在无 root/sudo 权限的环境(云容器、VPS、隔离主机)中安装并配置 OpenClaw 浏览器工具的 headless Chrome。适用场景:...
处理函数内应避免不安全操作
信号处理函数运行在异步上下文中,属于“异步信号安全”受限环境:
- 只能调用异步信号安全函数(如
write()、_exit()),避免用printf()、malloc()、pthread_create()等 - 不要访问可能被主流程修改的全局变量,除非用
volatile sig_atomic_t类型 - 若需复杂逻辑(如日志、文件写入),建议仅设标志位,由主循环检测后处理
典型使用示例(sigaction方式)
以下代码注册SIGINT处理函数,在收到Ctrl+C时打印提示并退出:
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
void handle_sigint(int sig) {
write(1, "Caught SIGINT — cleaning up...\n", 33);
_exit(0); // 安全退出,不触发stdio缓冲区操作
}
int main() {
struct sigaction sa = {0};
sa.sa_handler = handle_sigint;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGINT, &sa, NULL);
while(1) pause(); // 等待信号
return 0;
}</stdio.h></unistd.h></signal.h>
编译运行后按Ctrl+C,会输出提示并退出,而非默认的“Terminated”。










