【问题标题】:Create N child processes from the same process then print PID of all child process with correlative parent process从同一个进程创建 N 个子进程,然后打印具有相关父进程的所有子进程的 PID
【发布时间】:2023-04-04 20:24:01
【问题描述】:

我还是不明白为什么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

【问题讨论】:

  • fork 创建一个子进程。子和父都从下一条语句开始执行。你似乎错过了第一个孩子也会fork一个新进程。

标签: c linux fork child-process


【解决方案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 在所有4 进程中的值将是2,循环条件i&lt;2 将导致false,并且所有进程都将退出。

您的代码中有一个严重问题 - 如果父进程完成运行并在子进程之前退出会发生什么?
在这种情况下,子进程将变为orphan process,并且您可能将父 PID 设为1,而不是原始父进程 ID,因为孤立进程可能重新成为 init 进程的父进程,该进程通常被分配PID1

要克服这个问题,您必须在退出之前为其所有子进程设置父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) 有一个称为Copy-on-Write的概念,这是一种优化,其中设置了页表,以便父进程和子进程开始共享所有相同的内存,并且仅在需要时复制任一进程写入的页面。这意味着父进程和子进程共享相同数据的副本,并且一旦它们中的任何一个进行写入,就会生成副本,并且一个进程的内存中的任何更改在另一个进程中不可见。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多