C语言进程管理异常:两次命令调用却执行三次的问题排查
C语言进程创建异常:命令重复执行问题
我正在测试用C语言编写程序创建并管理进程,目标是创建进程并执行两次不同的命令,流程如下:
- 创建新进程
- 打印该进程的PID
- 执行指定命令
- 进程退出
但遇到了奇怪的问题:执行单个命令时一切正常,但连续执行两次流程时,第二个命令会被执行两次,总共执行了三次命令。
我的代码
#include <sys/types.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <sys/wait.h> void launch_command(char command[]) { pid_t pid; pid = fork(); if(pid==0) { printf("Creating process %d from %d\n", getpid(),getppid()); system(command); exit(0); } else { if ((pid = fork()) == -1) perror("Error while creating a new process"); } } int main () { printf("Root process: %d\n",getpid()); launch_command("/bin/ls -l"); while(wait(NULL) >= 0); launch_command("/bin/date"); while(wait(NULL) >= 0); return 0; }
实际输出
$ ./a.out Root process: 8924 Creating process 8925 from 8924 Creating process 8928 from 8926 Sun 13 Nov 2022 23:54:51 EST total 128 -rwxr-xr-x 1 gg staff 49784 13 Nov 23:54 a.out -rw-r--r-- 1 gg staff 3499 11 Nov 10:59 create_process.c Creating process 8931 from 8924 Sun 13 Nov 2022 23:54:51 EST
期望输出
$ ./a.out Root process: 8924 Creating process 8925 from 8924 total 128 -rwxr-xr-x 1 gg staff 49784 13 Nov 23:54 a.out -rw-r--r-- 1 gg staff 3499 11 Nov 10:59 create_process.c Creating process 8931 from 8924 Sun 13 Nov 2022 23:54:51 EST
请问这种行为的原因是什么?
问题原因与修复方案
根本原因
问题出在launch_command函数的逻辑里:
- 第一次调用
fork()后,父进程进入else分支,但你在这个分支里又调用了一次fork(),创建了一个额外的子进程。 - 这个额外的子进程没有任何后续处理(既没执行目标命令也没主动退出),它会从
fork()的位置继续执行代码,也就是回到main函数的流程中。 - 当第一个
launch_command执行完,主进程进入wait循环等待所有子进程结束时,这个额外子进程也会执行到wait循环之后,然后调用第二个launch_command("/bin/date")——相当于主进程和这个额外子进程各自执行了一次date命令,所以最终date被执行了两次,加上第一次的ls,总共三次命令执行。
修复后的代码
只需要删除else分支里多余的fork()调用,让每个launch_command只创建一个子进程来执行命令:
#include <sys/types.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <sys/wait.h> void launch_command(char command[]) { pid_t pid; pid = fork(); if(pid == 0) { printf("Creating process %d from %d\n", getpid(), getppid()); system(command); exit(0); } else if (pid == -1) { perror("Error while creating a new process"); } } int main () { printf("Root process: %d\n", getpid()); launch_command("/bin/ls -l"); while(wait(NULL) >= 0); launch_command("/bin/date"); while(wait(NULL) >= 0); return 0; }
修复后运行,就会得到你期望的输出:只执行一次ls和一次date,没有多余的进程和命令执行。
内容的提问来源于stack exchange,提问作者NIGHTSCROLLER
相关产品推荐
相关产品推荐

