在for循环中fork

时间:2010-02-13 03:24:48

标签: fork unix

我对以下代码及其行为表示怀疑:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

#define N 5
#define nt 1

int pm[N][2],pid[N];
int i,j,size;
char s[100];
int count=0;

int main()
{
 for(i=1;i<N;i++)
    {
      printf("\n i=%d",i);

      if(pid[i]=fork() == -1)
        {
          printf("\n fork not wrking");
          exit(1);
        }
      else if(pid[i]>0)
        {
          printf(" \n pid:%3d\n",pid[i]);
        break;
        }

    }
return 0;
}

我最初认为代码会产生一个进程并跳过循环。 因此,
1产生2并跳出。
2产生3并跳出来 3产生4并跳出来 4个产卵5并跳出来。

我尝试执行此代码并且对我得到的答案感到惊讶(对于代码中的i的printf)。这是输出

 i=1
 i=2
 i=3
 i=2
 i=4
 i=3
 i=3
 i=3
 i=4
 i=4
 i=4
 i=4
 i=4
 i=4
 i=4

任何人都可以向我解释这里发生了什么。 注意:我正在使用Solaris计算机。

5 个答案:

答案 0 :(得分:7)

更新

您在更新的代码中缺少一组括号。那应该是if ((pid[i] = fork()) == -1)而不是if (pid[i] = fork() == -1)

由于优先规则,后者等同于if (pid[i] = (fork() == -1))。每次循环时,它最终会为pid[i]分配0,因此父母认为它们是子进程,并且不会突破循环。


我同意你对应该发生的事情的分析。父母应该生成一个孩子,然后退出,因此每个i=n打印输出应该只显示一次。

您确定要按照问题中指定的方式输入吗?我运行你的程序(稍加修改)并获得你预测的输出:

$ cat fork.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

#define N 5

int main() {
    int pid[N], i;

    for(i=1;i<N;i++) /* What’s the total number of processes? */
    {
    printf("i=%d\n",i); // Output of all the is
    if((pid[i]=fork())==-1) exit(1);
    else if(pid[i] > 0) break;
    }

    return 0;
}
$ gcc -o fork fork.c
$ ./fork
i=1
i=2
$ i=3
i=4

请注意,我将打印输出中的\n移到了最后。当你把它放在行的开头时,你最终没有被刷新stdout,所以当父和子进程都刷新它们的输出缓冲区时你会得到多个打印输出。这可能是导致问题的原因。在我的Mac上FWIW我每次打印两次。

答案 1 :(得分:1)

Fork创建一个重复的进程,包含父进程所做的所有事情,包括文件句柄等。唯一的区别是fork()的返回值:父进程看到pid,子进程看到零。

第一次迭代创建第一个子节点。它的i副本也是1,与父级相同。孩子突破了循环。当我运行它时,我会得到不同的结果:

[wally@zf ~]$ ./a.out
i=1
i=2
i=3
i=4

答案 2 :(得分:1)

表达式

if (pid[i] = fork() == -1) {

不会做你期望的。你可能想说

if ((pid[i] = fork()) == -1) {

答案 3 :(得分:0)

每个子进程在生成时都会以i的当前值继续循环。结果,第一个进程打印i为1,然后生成一个子进程。接下来,这两个进程都打印i为2并生成一个子进程,总共有四个进程。所有这四个打印i为3,每个生成一个新进程,最后,所有8个进程打印值为4。

编辑:抱歉,我忽略了父母应该退出循环的部分。至于为什么没有发生这种情况,可能是因为PID存储为有符号整数但是足够高以传递最大有符号值,使其为负数。如果你做这个替换它会起作用吗?

else if(pid[i] > 0) break;

else if(pid[i] != 0) break;

答案 4 :(得分:0)

你使用什么样的Unix? fork有没有返回int的机会?

在那种情况下,pid [i]> 0比较可能会失败。