如何实现C代码检测Python发送的SIGUSR1信号并打印Hello World?
实现Python向C进程发送SIGUSR1并触发C打印Hello World
问题分析
现有代码存在以下核心问题:
- 管道通信顺序颠倒:Python先向管道写入字符串再读取C进程PID,但C进程实际是从该管道读取字符串,导致通信逻辑阻塞
- SIGUSR1触发逻辑缺失:C进程仅在收到信号时设置标志位,未执行打印
Hello World的操作 - 资源管理不规范:Python存在重复关闭文件描述符的问题,C进程主循环无休眠导致CPU占用过高
修改后的代码实现
Python代码
import os import signal # 清理残留FIFO管道 try: os.unlink('/tmp/tomcat_1') os.unlink('/tmp/tomcat_2') except FileNotFoundError: pass # 忽略SIGINT信号,避免进程意外终止 signal.signal(signal.SIGINT, lambda x,y: None) # 创建FIFO管道 os.mkfifo('/tmp/tomcat_1') # 用于C与Python的数据交互 os.mkfifo('/tmp/tomcat_2') # 用于C进程传递自身PID给Python # 读取C进程的PID with open('/tmp/tomcat_2', 'r') as pid_f: pid = int(pid_f.read().strip()) print(f"PYTHON: 获取到C进程PID: {pid}") # 向C进程发送初始字符串 with open('/tmp/tomcat_1', 'w') as w: w.write("F-14 TOMCAT") w.flush() # 发送SIGUSR1信号 os.kill(pid, signal.SIGUSR1) # 监听C进程返回的数据 try: with open('/tmp/tomcat_1', 'r') as r: while True: data = r.read() if data: print(f'PYTHON: 收到数据 {data}') finally: # 清理管道资源 os.unlink('/tmp/tomcat_1') os.unlink('/tmp/tomcat_2') print('PYTHON: 进程结束')
C代码
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <fcntl.h> #include <string.h> volatile sig_atomic_t g_sigint_flag = 0; volatile sig_atomic_t g_sigusr1_flag = 0; int fd_data; // /tmp/tomcat_1 数据管道 int fd_pid; // /tmp/tomcat_2 PID传递管道 // SIGINT信号处理:终止进程 void signal_handler(int signo) { if (signo == SIGINT) { printf("C: 收到SIGINT,准备终止\n"); g_sigint_flag = 1; } } // SIGUSR1信号处理:打印Hello World void sigusr1_handler(int signo) { if (signo == SIGUSR1) { // 使用write保证异步信号安全(printf并非严格异步安全,简单场景可替代) const char* msg = "C: Hello World\n"; write(STDOUT_FILENO, msg, strlen(msg)); g_sigusr1_flag = 1; } } int main(int argc, char ** argv) { // 注册信号处理函数 if (signal(SIGINT, signal_handler) == SIG_ERR) { perror("注册SIGINT处理函数失败"); return 1; } if (signal(SIGUSR1, sigusr1_handler) == SIG_ERR) { perror("注册SIGUSR1处理函数失败"); return 1; } // 写入自身PID到管道 fd_pid = open("/tmp/tomcat_2", O_WRONLY); if (fd_pid == -1) { perror("打开PID管道失败"); return 1; } char pid_buf[20]; snprintf(pid_buf, sizeof(pid_buf), "%d", getpid()); write(fd_pid, pid_buf, strlen(pid_buf)); close(fd_pid); // 打开数据管道读取初始数据 fd_data = open("/tmp/tomcat_1", O_RDWR); if (fd_data == -1) { perror("打开数据管道失败"); return 1; } char buf[1024]; ssize_t read_size = read(fd_data, buf, sizeof(buf)-1); if (read_size > 0) { buf[read_size] = '\0'; printf("C: 收到初始数据: %s\n", buf); } // 主循环等待信号或终止 while (!g_sigint_flag) { usleep(100000); // 休眠减少CPU占用 } close(fd_data); printf("C: 进程结束\n"); return 0; }
关键修改说明
- 调整通信顺序:C进程启动后先写入自身PID到管道,Python读取PID后再发送数据和信号,避免管道阻塞
- 完善SIGUSR1处理:在C的信号处理函数中直接执行打印逻辑,使用
write保证异步信号安全 - 优化资源管理:Python用
with语句自动管理文件,C进程合理关闭管道,主循环添加休眠降低CPU消耗 - 修复逻辑错误:移除Python中重复关闭文件的代码,确保通信流程顺畅
运行步骤
- 编译并启动C程序:
gcc tomcat.c -o tomcat_c ./tomcat_c - 启动Python程序:
python3 tomcat.py
内容的提问来源于stack exchange,提问作者HyperCoderSuperion
相关产品推荐
相关产品推荐

