You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现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;
}

关键修改说明

  1. 调整通信顺序:C进程启动后先写入自身PID到管道,Python读取PID后再发送数据和信号,避免管道阻塞
  2. 完善SIGUSR1处理:在C的信号处理函数中直接执行打印逻辑,使用write保证异步信号安全
  3. 优化资源管理:Python用with语句自动管理文件,C进程合理关闭管道,主循环添加休眠降低CPU消耗
  4. 修复逻辑错误:移除Python中重复关闭文件的代码,确保通信流程顺畅

运行步骤

  1. 编译并启动C程序:
    gcc tomcat.c -o tomcat_c
    ./tomcat_c
    
  2. 启动Python程序:
    python3 tomcat.py
    

内容的提问来源于stack exchange,提问作者HyperCoderSuperion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 03:52:00