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

如何停止并恢复execvp()调用对应的进程?子进程与execvp()进程暂停问题咨询

问题核心分析与解决方案

你这里其实存在两个关键误解,先帮你理清楚:

1. execvp() 不会创建新进程,PID和fork出的子进程完全一致

当你在fork的子进程中调用execvp()时,它不会生成新的PID——这个系统调用是直接替换当前子进程的内存空间、代码段等所有内容,进程的PID保持不变。所以你最初的思路里,直接kill(child, SIGSTOP)就能暂停execvp()启动的程序,不存在“获取execvp启动进程PID”的问题,因为两者是同一个进程。

那为什么你的示例代码里看起来没生效?问题出在你用了system()而不是execvp()。

2. 示例代码中system()的坑:它会额外fork一个进程

system()函数的工作流程是:

  • 先fork一个子进程
  • 在这个子进程中调用shell去执行你的脚本
  • 原进程(也就是你代码里的processB)会等待shell执行完成

所以你的loop.sh实际上是shell进程的子进程,而processB是那个等待shell的进程。这时候你给processB发SIGSTOP,只是暂停了等待的进程,shell和loop.sh还在正常运行,自然看不到计数停止。

解决方案:替换system()为exec族函数

要解决这个问题,直接用execvp()(或execlp()等)代替system(),让fork出的子进程直接变成loop.sh的进程,这样PID就是processB,父进程发送信号就能直接控制它。

修正后的代码示例:

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

int main(int argc, char *argv[]) {
    int status;
    pid_t processB = fork();
    if (processB == 0) {
        // 用execlp直接执行脚本,替换当前子进程
        execlp("/bin/bash", "/bin/bash", "~/loop.sh", nullptr);
        // 如果exec失败才会走到这里
        perror("exec failed");
        _exit(1);
    } else {
        for (;;) {
            sleep(5);
            std::cout << "Sending SIGSTOP to processB..." << std::endl;
            kill(processB, SIGSTOP);
            std::cout << "Should have stopped counting" << std::endl;
            sleep(3);
            std::cout << "Sending SIGCONT to processB..." << std::endl;
            kill(processB, SIGCONT);
            
            // 检查子进程是否退出
            if (waitpid(processB, &status, WNOHANG) == processB) {
                std::cout << "Child process exited, exiting monitor." << std::endl;
                _exit(0);
            }
        }
    }
    return 0;
}

对应的loop.sh保持不变(注意要确保脚本有可执行权限):

#!/bin/bash
counter=0
while :; do
    counter=$((counter+1))
    echo $counter
    sleep 1
done

验证效果

运行修正后的程序后,你会看到:

  • 前5秒计数正常输出
  • 然后暂停3秒,期间没有计数输出
  • 恢复后继续计数
    这说明SIGSTOP和SIGCONT确实作用在了loop.sh进程上。

额外说明

如果你因为某些原因必须使用system(),那需要额外获取shell启动的loop.sh的PID,这会复杂很多(比如通过解析/proc文件系统或者跟踪子进程),但完全没必要——用exec族函数是最直接、高效的方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 09:07:45