C语言通过SIGSTOP、SIGCONT控制子进程按序循环执行问题
现有代码问题
- 进程创建与调度耦合:父进程每创建一个子进程就立刻执行调度、阻塞等待子进程退出,此时后续子进程尚未创建,且子进程为死循环逻辑,
waitpid会永久阻塞导致流程卡死。 - 调度逻辑仅执行一轮:调度代码嵌套在子进程创建的循环内,跑完p0到p4的单次序列后就无后续逻辑,无法实现无限循环调度。
- 初始状态不符合要求:子进程创建后虽先收到SIGSTOP,但立刻被发送SIGCONT唤醒,无法做到启动时所有子进程默认停止。
- 信号注册位置错误:
signal(SIGCONT, &handler)写在父进程的fork循环内,子进程未注册对应信号处理,且父进程注册该信号无实际作用。
修复思路
- 拆分创建和调度逻辑:先完成所有5个子进程的创建,每创建一个就立刻发送SIGSTOP使其停止,保证所有子进程创建完成后全处于停止状态,满足初始状态要求。
- 独立实现循环调度:维护当前运行子进程的索引,每次仅唤醒当前索引对应的子进程,运行指定时长后发送SIGSTOP将其停止,再更新索引为下一个值,通过取模操作实现索引循环。
- 清理无效逻辑:去掉会永久阻塞的
waitpid调用,将信号处理函数注册到子进程逻辑内。
修复后可运行代码
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <sys/wait.h> #define N 5 // 子进程SIGCONT信号处理函数 void cont_handler(int sig) { if (sig == SIGCONT) { printf("子进程收到继续运行信号\n"); } } int main() { int pid[N]; int cur_proc = 0; // 记录当前调度运行的子进程索引 // 第一步:创建所有子进程,创建后立刻停止,保证初始全停 for (int i = 0; i < N; i++) { pid[i] = fork(); if (pid[i] == 0) { // 子进程执行逻辑 signal(SIGCONT, cont_handler); while (1) { printf("当前运行子进程 p%d\n", i); usleep(50000); // 每50ms打印一次,避免输出刷屏 } exit(0); } // 父进程给刚创建的子进程发停止信号 kill(pid[i], SIGSTOP); } // 第二步:无限循环轮转调度 while (1) { // 唤醒当前索引的子进程 kill(pid[cur_proc], SIGCONT); // 让当前子进程运行1秒 sleep(1); // 停止当前运行的子进程 kill(pid[cur_proc], SIGSTOP); // 更新下一个调度的子进程索引,到末尾后回到0 cur_proc = (cur_proc + 1) % N; } // 优雅退出逻辑(正常运行不会走到这里,可加SIGINT捕获触发) for (int i = 0; i < N; i++) { kill(pid[i], SIGKILL); waitpid(pid[i], NULL, 0); } return 0; }
代码说明
- 初始状态符合要求:所有子进程创建完成后第一时间被SIGSTOP暂停,调度逻辑启动前无任何运行中的子进程。
- 单进程运行保证:每次调度仅给当前索引的子进程发送SIGCONT,运行到时间后立刻发SIGSTOP暂停,任意时刻最多只有一个子进程处于运行状态。
- 循环调度符合要求:通过
cur_proc = (cur_proc + 1) % N实现索引轮转,固定按p0→p1→p2→p3→p4→p0的顺序循环调度。 - 编译运行命令:
gcc schedule.c -o schedule && ./schedule,运行后可观察到子进程按固定顺序轮转输出,按Ctrl+C可终止程序。
内容的提问来源于stack exchange,提问作者Hicham Zakroum
相关产品推荐
相关产品推荐

