如何用fork()创建4个子进程并通过waitpid()按指定顺序输出(禁用sleep)
实现指定顺序的进程输出(无sleep同步)
要让父进程P0创建的4个子进程P1-P4按P4→P1→P3→P2的顺序输出PID,最后P0输出,且不依赖sleep(),可以用信号+waitpid的同步方式,完全避免时序猜测问题。
以下是健壮的C语言实现代码:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <sys/wait.h> #include <errno.h> int main() { pid_t pids[4]; // 索引对应关系:0=P1, 1=P2, 2=P3, 3=P4 int i; // 创建4个子进程P1-P4 for (i = 0; i < 4; i++) { pids[i] = fork(); if (pids[i] == -1) { perror("fork failed"); exit(EXIT_FAILURE); } else if (pids[i] == 0) { // 子进程:阻塞等待SIGUSR1信号 sigset_t wait_mask; sigemptyset(&wait_mask); sigaddset(&wait_mask, SIGUSR1); // 安全等待信号,避免信号丢失 if (sigsuspend(&wait_mask) == -1 && errno != EINTR) { perror("sigsuspend failed"); exit(EXIT_FAILURE); } // 输出自身进程信息 printf("进程P%d PID: %d\n", i+1, getpid()); exit(EXIT_SUCCESS); } } // 父进程按指定顺序唤醒子进程并等待其完成输出 // 唤醒P4并等待退出 kill(pids[3], SIGUSR1); waitpid(pids[3], NULL, 0); // 唤醒P1并等待退出 kill(pids[0], SIGUSR1); waitpid(pids[0], NULL, 0); // 唤醒P3并等待退出 kill(pids[2], SIGUSR1); waitpid(pids[2], NULL, 0); // 唤醒P2并等待退出 kill(pids[1], SIGUSR1); waitpid(pids[1], NULL, 0); // 父进程最后输出自身信息 printf("进程P0 PID: %d\n", getpid()); return 0; }
核心逻辑说明:
- 子进程阻塞机制:每个子进程创建后,通过
sigsuspend()进入安全阻塞状态,只有收到父进程的SIGUSR1信号才会唤醒并输出PID,确保不会提前执行输出操作。 - 父进程顺序控制:父进程按要求的输出顺序,依次向对应子进程发送唤醒信号,并用
waitpid()等待子进程完全退出(即输出完成)后,再触发下一个子进程,严格保证输出顺序的准确性。 - 无sleep依赖:全程通过信号和进程等待机制实现同步,完全不需要
sleep()来预估进程执行时间,彻底避免了时序不确定性导致的顺序混乱问题。
编译运行方式:
将代码保存为process_order.c,执行以下命令编译运行:
gcc process_order.c -o process_order ./process_order
运行后会严格按照P4→P1→P3→P2→P0的顺序输出每个进程的PID。
内容的提问来源于stack exchange,提问作者Rishi Chowdhury
相关产品推荐
相关产品推荐

