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

如何向fork+execl创建的子进程发送信号?含启停控制场景

让bar控制foo启停及发送其他信号的实现方案

嘿,你的需求很清晰——用bar来启动并控制那个一开始就暂停的foo程序,对吧?目前你的bar代码有个小问题:fork之后没保存子进程的PID,导致没法精准给foo发信号。咱们来修改一下,让bar完全掌控foo的运行状态。

先回顾下你的基础代码,我稍微补全了头文件(不然编译会报错):

foo程序代码

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

int main(int argc, char * argv[]) { 
    kill(getpid(), SIGSTOP); 
    while(1) { 
        printf("foo\n"); 
        // 加个sleep避免输出刷屏,方便观察效果
        sleep(1);
    } 
    return 0; 
}

修改后的bar程序代码

核心就是保存子进程PID,然后用kill函数发送各种信号:

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

int main(int argc, char * argv[]) { 
    pid_t pid = fork(); 
    if (pid == 0) { 
        // 子进程:执行foo,注意路径要对(如果和bar同目录就用./foo)
        execl("./foo", "foo", NULL); 
        // 如果execl执行失败,打印错误信息
        perror("Failed to execute foo");
        return 1;
    } else if (pid > 0) {
        // 父进程:这里就是控制逻辑的核心
        printf("Foo process started with PID: %d\n", pid);

        // 先等1秒,确保foo已经执行了SIGSTOP进入暂停状态
        sleep(1);

        // 发送SIGCONT,让foo恢复打印
        printf("Sending SIGCONT to foo...\n");
        kill(pid, SIGCONT);

        // 让foo运行3秒
        sleep(3);

        // 发送SIGSTOP,暂停foo的打印
        printf("Sending SIGSTOP to foo...\n");
        kill(pid, SIGSTOP);

        // 等待2秒,确认foo确实暂停了
        sleep(2);

        // 再次发送SIGCONT恢复运行
        printf("Sending SIGCONT again to resume foo...\n");
        kill(pid, SIGCONT);

        // 再运行3秒后,发送SIGTERM终止foo
        sleep(3);
        printf("Sending SIGTERM to terminate foo...\n");
        kill(pid, SIGTERM);

        // 等待子进程结束,避免产生僵尸进程
        waitpid(pid, NULL, 0);
    } else {
        // fork失败的情况,打印错误
        perror("Failed to fork process");
        return 1;
    }
    return 0; 
}

关键知识点说明

  • 保存子进程PID:fork成功后,父进程会获得子进程的PID,这是后续给foo发信号的唯一标识,必须保存好。
  • 常用信号说明:用kill(pid, signal)函数就能给指定PID的进程发信号,常用信号包括:
    • SIGCONT:恢复暂停的进程
    • SIGSTOP:暂停进程(无法被捕获或忽略)
    • SIGTERM:请求进程终止(可以被捕获处理)
    • SIGKILL:强制终止进程(无法被捕获,慎用)
  • 错误处理:添加perror可以快速定位fork或execl失败的原因,调试起来更方便。
  • 避免僵尸进程:用waitpid等待子进程退出,不然子进程终止后会变成僵尸进程,占用系统资源。

编译运行步骤

  1. 编译两个程序:
    gcc foo.c -o foo
    gcc bar.c -o bar
    
  2. 运行bar:
    ./bar
    
    你会看到清晰的控制流程:foo先暂停,然后开始每秒打印"foo",3秒后暂停,2秒后恢复,最后被终止。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:37:11