C++实现定期中断子进程,超时终止父子进程的问题求助
问题描述
程序A通过fork()执行程序B,要求每5秒中断程序B对应的进程;若用户在规定时间内按下任意键,则恢复进程运行,之后再次按相同时间间隔中断;若未按键,则提前终止程序A和程序B。以下是我尝试的代码,但无法正常运行,作为C++新手,希望得到建议或解决方案。
#include <iostream> #include <chrono> #include <unistd.h> #include <sys/wait.h> #include <signal.h> using namespace std; using namespace chrono; int pid; void signal_handler(int signum) { cout << "Programm B is interrupted. Please enter any key within 5 or the programm will be terminated" << endl; kill(pid,SIGSTOP); alarm(5); pause(); alarm(5); } int main(int argc, char* argv[]) { //Usage if(string(argv[1]) == "h" || string(argv[1]) == "help"){ cout << "usage" << endl; return 0; } signal(SIGALRM, signal_handler); pid = fork(); if (pid == 0) { cout << "Name of programm B: " << argv[1] << endl; cout << "PID of programm B: " << getpid() << endl; execvp(argv[1], &argv[1]); } else if (pid > 0) { cout << "PID of programm A: " << getpid() << endl; high_resolution_clock::time_point t1 = high_resolution_clock::now(); waitpid(pid, nullptr, 0); high_resolution_clock::time_point t2 = high_resolution_clock::now(); auto duration = duration_cast<milliseconds>(t2 - t1).count(); cout << "Computing time: " << duration << "ms" << endl; } else { cerr << "error << endl; return 1; } return 0; }
问题分析与修复方案
原代码核心问题
- 未启动初始闹钟:主进程没有设置第一个
alarm(5),导致不会触发第一次中断。 pause()逻辑缺陷:pause()会等待任意信号,无法精准捕获用户按键,且没有处理输入缓冲问题。- 信号处理逻辑错误:中断进程后没有恢复操作(缺少
kill(pid, SIGCONT)),重复设置闹钟会覆盖定时。 waitpid阻塞:主进程调用waitpid(pid, nullptr, 0)会一直阻塞到子进程结束,无法循环执行定时中断。- 参数检查缺失:直接访问
argv[1]未做argc判断,易导致崩溃。 - 语法错误:
cerr << "error << endl;存在字符串闭合错误。
修复后的代码
#include <iostream> #include <chrono> #include <unistd.h> #include <sys/wait.h> #include <signal.h> #include <cstring> #include <fcntl.h> #include <errno.h> using namespace std; using namespace chrono; int pid; bool user_responded = false; void alarm_handler(int signum) { cout << "\n程序B已中断,请在5秒内按任意键恢复,否则将终止所有程序\n"; kill(pid, SIGSTOP); user_responded = false; // 设置超时闹钟 alarm(5); // 将标准输入设为非阻塞模式 int flags = fcntl(STDIN_FILENO, F_GETFL, 0); fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK); char c; while (true) { if (read(STDIN_FILENO, &c, 1) > 0) { user_responded = true; kill(pid, SIGCONT); cout << "\n程序B已恢复运行\n"; alarm(5); // 重新设置下一次中断 break; } // 若超时被信号中断或用户已响应,退出循环 if (user_responded) break; usleep(100000); // 降低CPU占用 } // 恢复标准输入为阻塞模式 fcntl(STDIN_FILENO, F_SETFL, flags); // 超时未响应,终止所有进程 if (!user_responded) { cout << "\n超时未响应,终止程序A和B\n"; kill(pid, SIGKILL); exit(0); } } int main(int argc, char* argv[]) { // 参数合法性检查 if (argc < 2) { cerr << "用法: " << argv[0] << " <程序B路径> [参数]\n"; cerr << "输入" << argv[0] << " help 查看帮助\n"; return 1; } if (strcmp(argv[1], "help") == 0 || strcmp(argv[1], "h") == 0) { cout << "用法: " << argv[0] << " <程序B路径> [参数]\n"; cout << "每5秒中断程序B,按任意键恢复;5秒未按键则终止所有程序\n"; return 0; } // 设置信号处理 signal(SIGALRM, alarm_handler); // 忽略Ctrl+C信号,避免直接终止主进程 signal(SIGINT, SIG_IGN); pid = fork(); if (pid == 0) { cout << "程序B名称: " << argv[1] << endl; cout << "程序B PID: " << getpid() << endl; execvp(argv[1], &argv[1]); // execvp执行失败时的错误处理 cerr << "执行程序B失败: " << strerror(errno) << endl; exit(1); } else if (pid > 0) { cout << "程序A PID: " << getpid() << endl; high_resolution_clock::time_point t1 = high_resolution_clock::now(); // 启动第一个5秒中断闹钟 alarm(5); // 循环等待子进程状态,同时响应信号 int status; while (waitpid(pid, &status, WNOHANG) == 0) { pause(); // 阻塞等待信号触发 } high_resolution_clock::time_point t2 = high_resolution_clock::now(); auto duration = duration_cast<milliseconds>(t2 - t1).count(); cout << "总运行时间: " << duration << "ms" << endl; } else { cerr << "fork失败: " << strerror(errno) << endl; return 1; } return 0; }
关键修复说明
- 启动初始闹钟:主进程fork后立即调用
alarm(5),触发第一次中断逻辑。 - 非阻塞输入处理:用
fcntl将标准输入设为非阻塞,配合usleep避免CPU空转,同时精准捕获用户按键。 - 完善信号逻辑:中断后等待用户输入,按键则恢复进程并重新设置闹钟;超时则直接终止A和B。
- 参数与错误处理:增加
argc检查,处理fork、execvp的错误场景,修正原代码语法错误。
内容的提问来源于stack exchange,提问作者Raizel
相关产品推荐
相关产品推荐

