我仍然不明白为什么pid = 11310的子进程创建pid = 11312的子进程
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main(){
pid_t pid[2];
for (int i = 0; i<2; i++){
pid[i] = fork();
if ( pid[i] == 0){
printf("[child] pid %d from [parent] pid %d\n",getpid(),getppid());
}
}
}
我的期望:
[child] pid 11310 from [parent] pid 11309
[child] pid 11311 from [parent] pid 11309
但是实际结果:
[child] pid 11310 from [parent] pid 11309
[child] pid 11311 from [parent] pid 11309
[child] pid 11312 from [parent] pid 11310
答案 0 :(得分:1)
fork()
通过复制调用过程来创建子过程,并将其从被调用点一分为二。子进程和父进程在单独的内存空间中运行 1)。在fork()
时,两个存储空间的内容相同。也就是说,fork()
时子进程中变量的值与父进程中的值相同。
在for
循环的第一次迭代中:
pid[i] = fork();
// this will create child process and both parent and child process proceed with next statement
if ( pid[i] == 0){ // only child process will enter to this if block
printf("[child] pid %d from [parent] pid %d\n",getpid(),getppid());
}
输出显示:
[child] pid 11310 from [parent] pid 11309
在执行for
循环主体之后,由于i
,在父进程和子进程地址空间中循环控制变量i++
的值都会增加。
因此,在第二次迭代中,父级和子级地址空间中i
的值均为1
。
现在,父(PID: 11309)
和子(PID: 11310)
都将执行for
循环主体,并且两者都将创建一个子进程。这就是子进程(PID: 11310)
创建另一个子(PID: 11312)
的原因。
11309----- --|
| | |---------> First iteration
11310 | --| --|
| | |---> Second iteration
11312 11311 --|
在第三次迭代中,在所有i
进程中,2
的值将为4
,循环条件i<2
将导致false
,并且所有该过程将退出。
您的代码中存在一个严重问题-如果父进程完成运行并在子进程之前退出会发生什么?
在这种情况下,子进程将变为orphan process,并且您可能将父PID设置为1
而不是原始父进程ID,因为孤立进程可能会重新绑定为 init 进程,通常分配给PID 1
。
要解决此问题,必须在退出前为其所有子进程设置父wait。
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void) {
pid_t pid;
// You can take number of child process to be create as input from user
for (int i = 0; i < 2; i++) {
pid = fork();
if (pid == 0) {
printf("[child] pid %d from [parent] pid %d\n", getpid(), getppid());
break;
}
}
if (pid != 0) {
int cpid;
int status;
while ((cpid = wait(&status)) > 0)
printf("Parent (%d): child (%d) exited with status 0x%.4x\n", (int)getpid(), cpid, status);
}
return 0;
}
1)有一个名为写时复制的概念,这是对页表进行设置的一种优化,以便父级和子级进程开始共享所有相同的内存,并且在需要时,仅复制由任一进程写入的页面。这意味着父进程和子进程都共享同一数据的副本,并且一旦它们中的任何一个进行写操作,就会进行复制,并且一个进程的内存中的任何更改在另一个进程中都不可见。