了解Unix中的fork机制

时间:2012-10-18 10:49:45

标签: c unix multiprocessing fork

我试图找出父子进程的行为。 以下是我的代码

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

int main(void)
{
    int i,j,cnt=0;
    int pid,present_pid;
    int a[10];
    for(i=0; i<10; i++) {
        a[i] = i;
    }

    i = 0;
    j = 5;
    present_pid = getpid();
    printf("Now in process %d\n",getpid());
    printf("\n*******************before fork******************\n");
    for(i=0;i<10;i++) {
        printf("  %d",a[i]);
    }
    printf("\n*******************before fork******************\n");

    int ret = fork();
    if(ret == 0) {
        printf("\n*******************after fork******************\n");
        printf("Now in process %d\n",getpid());
        printf("Child Process created");
        for(i=0; i<5; i++) {
            a[i]= +1;
            i++;
        }
    }
    else if(ret > 0) {
        printf("\nNow in process %d\n",getpid());
        for(j=5; j<10; j++) {
            a[j] = +1;
            j++;
        }
        wait();
    }

    for(i=0;i<10;i++) {
        printf("  %d",a[i]);
    }
    return 0;
}

这是程序的输出

Now in process 12248

*******************before fork******************
  0  1  2  3  4  5  6  7  8  9
*******************before fork******************

*******************after fork******************
Now in process 12249
Child Process created  1  1  3  3  5  5  6  7  8  9
Now in process 12248
  0  1  2  3  4  6  6  8  8 

因此,最初只有一个进程12248,它会分叉另一个进程(12249)。现在这两个过程都是并行的(如果我错了,请纠正我)。理想情况下,孩子应该 a 的内容添加1 仅限于前半部分,而父级应该对第二部分执行相同操作。但正如您所看到的那样,输出并不像预期的那样。请提出建议..

3 个答案:

答案 0 :(得分:3)

fork创建的进程是一个真正重量级的操作系统进程,而不仅仅是一个轻量级的线程!创建的进程不会与分叉的进程共享任何内存。相反,内存被复制(懒惰,所谓的写时复制),所以你现在实际上有两个数组a,每个进程写入他自己的a副本。

答案 1 :(得分:1)

您的代码中有2个小错误。通常我们甚至都没有注意到它们的存在。

  1. a[i]= +1;哦,亲爱的。我想你想写a[i] += 1a[i]++
  2. 冗余i++j++for循环已为您完成此操作。
  3. 纠正它们,你会得到你期望的答案。

答案 2 :(得分:0)

首先对代码进行一些更改

 printf("Now in process %d\n",getpid());
        printf("Child Process created");
        for(i=0; i<5; i++)
         {
   -->         a[i]+= 1;
    -->     //   i++; //comment this line you are jumping 2 steps in this loop
         }

至于fork()

的概念

每当你执行fork()调用时,都会为子进程创建进程地址空间的精确副本,并且在fork()调用之后将程序计数器设置为该行

在你的案例之后

     int ret = fork();
Program Counter-->    if(ret == 0)
                           {

下,

Now both the process run parallel

是父进程并行运行但在执行完成后等待来自子进程的SIGCHLD信号。

如果子进程返回SIGCHLD信号但父进程尚未收到(即父进程处于等待状态),则子进程被称为ZOMBIE进程。

如果父进程突然中止且子进程仍在运行(或处于READY状态),则子进程称为ORPHAN进程。在这种情况下,名为init的进程负责收集子进程的状态。

最后,程序流程。 父进程最初运行。

int ret = fork();//A child process is created

然后此代码在子进程中执行

        if(ret == 0)
      {
        printf("\n*******************after fork******************\n");
        printf("Now in process %d\n",getpid());
        printf("Child Process created");
        for(i=0; i<5; i++)
         {
            a[i] += 1;
            //i++;
         }
      }
       else if(ret > 0)//this condition is false in child process
      {
          // rest of code
      }

//最后这是优秀的

for(i=0;i<10;i++)
  {
    printf("  %d",a[i]);
  }
return 0;
    then child process returns SIGCHLD signal

以下代码在父进程中执行

        else if(ret > 0)//this is true for parent process
      {
        printf("\nNow in process %d\n",getpid());
        for(j=5; j<10; j++)
          {
            a[j] = +1;
            j++;
          }
        wait();
      }

    for(i=0;i<10;i++)
      {
        printf("  %d",a[i]);
      }
    return 0;

}

注意:父进程也返回SIGCHLD信号,此信号由init进程收集

每当生成一个新进程时,默认情况下是init进程的子进程