C进程fork()

Sri*_*aju 3 c unix process parent-child

我正在UNIX中探索父进程和子进程概念.我写了这个小代码,认为x不.或过程将被创建.但它创造了一个不同的数字 -

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main(int argv, char *argc[])
{
    int i;
    pid_t childpid;

    for(i=0; i<3; i++)
    {
        childpid = fork();
        if(childpid == -1)
        {
            perror("Failed to Fork");
            return 1;
        }

        if(childpid == 0)
            printf("You are in Child: %ld\n", (long)getpid());
        else
            printf("You are in Parent: %ld\n", (long)getpid());
    }
    return 0;
}

OUTPUT:
You are in Parent: 30410
You are in Child: 30411
You are in Parent: 30410
You are in Child: 30412
You are in Parent: 30411
You are in Parent: 30410
You are in Child: 30413
You are in Child: 30414
You are in Parent: 30412
You are in Parent: 30411
You are in Child: 30415
You are in Child: 30416
You are in Parent: 30413
You are in Child: 30417
Run Code Online (Sandbox Code Playgroud)

我理解,在某种fork()情况下,父母或孩子可能会在执行中获得优先权.这不是困扰我,困扰我的是正在执行的进程数.为什么是14?而不是一些2 ^ n数字,如果我们正在执行,fork(); fork(); fork()即fork一个接一个地会发生什么.

我错过了什么?

更新:再澄清一次 -

fork函数复制父内存映像,以便新进程接收父进程的地址空间的副本.

这是什么意思?这是不是意味着 -

  1. 子进程在fork()语句后开始执行?
  2. 子进程获取父进程变量的副本?所以如果x=3在fork之上,子进程是否会将此x看作3?

pax*_*blo 12

8个进程正在执行,只是因为循环,其中一些进程打印了不止一次.

如果您对输出进行排序:

You are in Parent: 30410
You are in Parent: 30410
You are in Parent: 30410

You are in Parent: 30411
You are in Parent: 30411
You are in Child: 30411

You are in Parent: 30412
You are in Child: 30412

You are in Parent: 30413
You are in Child: 30413

You are in Child: 30414

You are in Child: 30415

You are in Child: 30416

You are in Child: 30417
Run Code Online (Sandbox Code Playgroud)

那么你可以看到只有8个唯一的进程ID.

原因很微妙.因为子进程从父进程继承(几乎)所有内容,所以它也获得循环的当前状态.我说"差不多",因为某些事情是不同的,例如PID(显然),父PID(同样明显)和某些资源限制(取决于操作系统).

因此,当i == 0叉成两个时,处理0 .他们的下一个周期都在i == 1.这两个都将在下一个周期进行分配i == 2.等等.

如果检查下图,则可以看到创建过程.

      ____A____
     /    |    \
    B_    C_    D
    | \     \
    E  F     G
     \
      H
Run Code Online (Sandbox Code Playgroud)

线/,|\表示在其中点叉i0,12分别.

请注意,E从父级创建的进程(例如)i == 1将只分叉i == 2.换句话说,它的创建是|为了它的下一步是\.

类似地,B/(i == 0)创建的那个只会用|(i == 1)和\(i == 2)分叉.

如果你感兴趣的其他信息,叉,看到我的大量文章在这里,并在Linux下的不同叉选项内部的一些细节在这里.