Linux C编程:fork()与waitpid()使用问题及操作系统实验实现疑问
问题解答
疑问1:n≥3时输出乱序与结果正确性
- 你n=3的输出是正确的:连续执行n次fork的总进程数为
2^n,你当前输出了8个进程信息,数量符合要求,pid和ppid的对应关系也没有逻辑错误。 - 乱序属于正常现象:fork生成的所有进程由操作系统内核独立调度,执行顺序没有固定规则,PART1仅要求输出进程信息的场景下不需要修复。如果要避免父进程提前结束导致子进程变为孤儿进程(ppid被置为1),可以在原始父进程最后加等待逻辑,等所有子进程退出后再结束自身。
疑问2:PART2逻辑说明
- 伪代码里的
if parent指代每次fork调用后的父进程,不是仅指初始的原始父进程。fork调用会给父进程返回子进程的pid值,给子进程返回0,可以通过返回值判断当前进程角色。 waitpid(pid)里的pid就是fork调用返回给父进程的子进程pid值。- 这段伪代码的实际运行逻辑是:每次fork之后,父进程立刻阻塞等待当前子进程完全退出,然后直接break跳出循环结束自身;只有子进程会继续执行下一轮循环,最终生成「原始父进程→子进程1→子进程2→…→子进程n」的链式进程结构,总共有n+1个进程,和PART1的2^n个进程的生成逻辑完全不同。
疑问3:输出顺序控制思路
- 不需要单独打印原始父进程的话,可以先保存初始进程的pid到变量
init_pid = getpid(),在打印逻辑前加判断,如果当前进程pid等于init_pid就先执行自身的打印,再进入fork循环即可。 - 要完全控制所有进程的输出顺序,有两种常用实现思路:
- 加进程同步:用共享内存实现信号量,所有进程必须拿到信号量才能执行打印,打印完成后释放信号量给下一个进程
- 父进程统一收集输出:子进程把自己的pid和ppid通过管道发送给父进程,父进程按创建顺序或者接收顺序统一打印所有信息
代码修改参考
PART1 优化版(避免孤儿进程+输出csv格式)
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/wait.h> int main() { int i,n; pid_t init_pid = getpid(); FILE *fptr; printf("enter n \n"); scanf("%d",&n); fptr = fopen("process_result.csv", "w"); fprintf(fptr, "pid,ppid\n"); for (i=0; i < n; i++) { pid_t fork_ret = fork(); if (fork_ret == 0) { // 子进程跳出循环,执行打印逻辑 break; } } pid_t cur_pid = getpid(); pid_t cur_ppid = getppid(); printf("pid=%d,ppid=%d\n", cur_pid, cur_ppid); fprintf(fptr, "%d,%d\n", cur_pid, cur_ppid); // 只有原始父进程需要等待所有子进程退出后再关闭文件 if (cur_pid == init_pid) { while(wait(NULL) > 0); fclose(fptr); } return 0; }
PART2 实现版(按伪代码要求实现链式fork)
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/wait.h> int main() { int i,n; FILE *fptr; printf("enter n \n"); scanf("%d",&n); fptr = fopen("chain_process_result.csv", "w"); fprintf(fptr, "pid,ppid\n"); for (i=0; i < n; i++) { pid_t fork_ret = fork(); if (fork_ret > 0) { // 当前是父进程,等待子进程退出后直接结束循环 waitpid(fork_ret, NULL, 0); break; } // 子进程继续下一轮循环 } pid_t cur_pid = getpid(); pid_t cur_ppid = getppid(); printf("pid=%d,ppid=%d\n", cur_pid, cur_ppid); fprintf(fptr, "%d,%d\n", cur_pid, cur_ppid); fclose(fptr); return 0; }
内容的提问来源于stack exchange,提问作者SudoShwetanshu
相关产品推荐
相关产品推荐

