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

父进程向4个子进程发送SIGUSR1/SIGUSR2信号失败问题求助

问题修复与代码优化

错误分析

原代码存在多个核心问题导致子进程无法接收信号:

  • 父进程调用kill时错误传入数组名pid,而非当前子进程的PIDpid[i],导致信号发送到无效进程。
  • 父进程未按子进程PID奇偶性发送对应信号,而是同时发送两种信号,不符合需求。
  • 子进程仅sleep(1)就退出,存在竞态条件:父进程可能在子进程完成信号处理函数注册前就发送信号,子进程会因默认信号处理规则直接终止;且即使注册成功,1秒内未收到信号也会直接退出,无法等待信号。
  • 信号处理函数未初始化current_time,直接调用ctime会输出无效时间,需先调用time(&current_time)获取当前时间。
  • exit(&status)是错误用法,exit参数应为整数退出码,而非指针。

修复后的代码

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <time.h>

void sigusr1_handler();
void sigusr2_handler();

int main()
{
    pid_t pid[4];
    int i;

    for (i = 0; i < 4; i++)
    {
        pid[i] = fork();

        if (pid[i] == 0)
        {
            pid_t child_pid = getpid();
            // 根据PID奇偶注册对应信号处理函数
            if (child_pid % 2 == 1)
            {
                signal(SIGUSR1, sigusr1_handler);
            }
            else
            {
                signal(SIGUSR2, sigusr2_handler);
            }
            // 无限等待信号,直到收到信号后退出
            while (1) {
                pause(); // 暂停进程直到收到信号
            }
            exit(0);
        }
        else if (pid[i] > 0)
        {
            // 给子进程足够时间注册信号处理函数
            sleep(1);
            // 根据子进程PID奇偶发送对应信号
            if (pid[i] % 2 == 1)
            {
                printf("PARENT: 向PID为%d的子进程发送SIGUSR1\n", pid[i]);
                kill(pid[i], SIGUSR1);
            }
            else
            {
                printf("PARENT: 向PID为%d的子进程发送SIGUSR2\n", pid[i]);
                kill(pid[i], SIGUSR2);
            }
        }
        else
        {
            perror("fork失败");
            exit(1);
        }
    }

    // 父进程等待所有子进程结束
    for (i = 0; i < 4; i++)
    {
        waitpid(pid[i], NULL, 0);
    }

    return 0;
}

void sigusr1_handler()
{
    // 重新注册信号(避免信号处理函数被重置为默认)
    signal(SIGUSR1, sigusr1_handler);
    printf("CHILD(PID=%d): 收到SIGUSR1\n", getpid());
    
    time_t current_time;
    time(&current_time); // 获取当前时间
    char *c_time_string = ctime(&current_time);
    printf("SIGUSR1 接收时间: %s", c_time_string);
    
    // 处理完信号后退出子进程
    exit(0);
}

void sigusr2_handler()
{
    signal(SIGUSR2, sigusr2_handler);
    printf("CHILD(PID=%d): 收到SIGUSR2\n", getpid());
    
    time_t current_time;
    time(&current_time);
    char *c_time_string = ctime(&current_time);
    printf("SIGUSR2 接收时间: %s", c_time_string);
    
    exit(0);
}

修复说明

  1. 父进程通过pid[i]获取当前子进程的PID,根据奇偶性发送对应信号,确保信号发送正确。
  2. 父进程添加sleep(1),避免在子进程未完成信号注册前发送信号,解决竞态问题。
  3. 子进程使用while(1) + pause()无限等待信号,直到收到信号后处理并退出,确保不会提前终止。
  4. 信号处理函数中补充time(&current_time),正确获取当前时间并输出。
  5. 父进程最后通过waitpid等待所有子进程结束,避免子进程变为孤儿进程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 19:25:30