C语言中按下Ctrl+C时删除FIFO文件的信号处理函数问题
问题分析与解决方案
嘿,我一眼就揪出你代码里的核心问题啦:信号处理函数的签名不符合标准,这会导致程序运行时出现未定义行为,根本没法正常执行你想要的FIFO删除操作。
核心问题
POSIX标准明确规定,信号处理函数的原型只能是:
void handler(int sig);
而你写的sigintHandler多了一个char * myfifo参数,这完全不符合要求——当内核触发信号处理函数时,只会传递信号编号这一个参数,多余的参数会直接造成栈混乱,函数里的unlink自然也没法正确执行。
两种修复方案
方案1:用全局变量存储FIFO路径(简单直接)
把FIFO路径定义为全局变量,这样信号处理函数就能直接访问到它,是最容易上手的解决方式:
#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #include <unistd.h> #include <signal.h> #define MAX_BUF 512 char *g_myfifo; // 全局变量存储FIFO路径 void sigintHandler(int sig_num) { puts("Hello you there, please don't leave!"); if (g_myfifo != NULL) { // 可选:检查删除操作是否成功 if (unlink(g_myfifo) == -1) { perror("Failed to delete FIFO"); } else { printf("Deleted FIFO file: %s\n", g_myfifo); } } exit(0); } int main() { g_myfifo = "/tmp/my_fifo"; // 先初始化全局变量 mkfifo(g_myfifo, 0666); // 注册SIGINT信号处理函数 signal(SIGINT, sigintHandler); // 这里写你的主逻辑(比如读写FIFO的代码) // ... return 0; }
方案2:用sigaction传递上下文(优雅避全局)
如果你不想用全局变量,可以借助sigaction的扩展机制传递自定义上下文,不过这种方式更适合自定义信号场景,对于Ctrl+C触发的SIGINT,需要额外处理上下文的存储:
#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #include <unistd.h> #include <signal.h> #include <string.h> #define MAX_BUF 512 static char s_fifo_path[256]; // 用静态全局变量存储路径,避免污染全局命名空间 void sigintHandler(int sig_num, siginfo_t *info, void *ucontext) { puts("Hello you there, please don't leave!"); if (strlen(s_fifo_path) > 0) { if (unlink(s_fifo_path) == -1) { perror("Failed to delete FIFO"); } else { printf("Deleted FIFO file: %s\n", s_fifo_path); } } exit(0); } int main() { strcpy(s_fifo_path, "/tmp/my_fifo"); mkfifo(s_fifo_path, 0666); struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_sigaction = sigintHandler; sa.sa_flags = SA_SIGINFO; // 启用带扩展参数的信号处理函数 // 注册信号处理规则 sigaction(SIGINT, &sa, NULL); // 主逻辑代码 // ... return 0; }
额外小提示
- 一定要先初始化FIFO路径,再注册信号处理函数,避免删除空路径导致错误。
- 加上
perror判断删除结果,能帮你快速排查权限不足、文件不存在之类的问题。
内容的提问来源于stack exchange,提问作者Oussema Ben Abdallah
相关产品推荐
相关产品推荐

