如何停止并恢复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
相关产品推荐
相关产品推荐

