for 循环中的 fork

发布于 2024-08-21 23:09:25 字数 817 浏览 4 评论 0原文

我对下面的代码及其行为有疑问:

#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 计算机上工作。

I have a doubt in the following piece of code and its behaviour:

#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;
}

I initially thought that the code will spawn a process and skip out of the loop.
Thereby,
1 spawns 2 and skips out.
2 spawns 3 and skips out
3 spawns 4 and skips out
4 spawns 5 and skips out.

I tried executing this code and was surprised by the answer i got ( for the printf of i in the code). Here is the output

 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

Can Anyone please explain to me what is going on here.
NOTE: I am working on a Solaris machine.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

情绪少女 2024-08-28 23:09:25

更新

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

由于优先级规则,后者相当于 if (pid[i] = (fork() == -1))。每次循环时它都会将 0 分配给 pid[i],因此父进程认为它们是子进程并且不会跳出循环。


我同意你对应该发生什么的分析。父进程应该生成一个子进程,然后退出,因此每个 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 不会被刷新,因此当父进程和子进程都刷新其输出缓冲区时,您会得到多个打印输出。这可能是你的问题的原因。 FWIW 在我的 Mac 上,每个打印输出都有两次。

Update

You're missing a set of parentheses in your updated code. That should be if ((pid[i] = fork()) == -1) not if (pid[i] = fork() == -1)!

The latter is equivalent to if (pid[i] = (fork() == -1)) due to precedence rules. It ends up assigning 0 to pid[i] each time through the loop, so the parents think they are child processes and don't break out of the loop.


I agree with your analysis of what should happen. The parent should spawn a child and then quit, so each i=n printout should only show up once.

Are you sure you typed it in exactly as specified in your question? I ran your program (with minor modifications) and got the output you predicted:

$ 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

Note that I moved the \n in the printout to the end. When you put it at the beginning of the line you end up with stdout not being flushed, so you get multiple printouts when the parent and child processes both flush their output buffers. That might be the cause of your problem. FWIW on my Mac I got each printout twice.

后eg是否自 2024-08-28 23:09:25

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

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

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

Fork creates a duplicate process, containing everything the parent does, including file handles, etc. The only difference is the return value of fork(): the parent sees the pid, the child sees zero.

The first iteration creates the first child. Its copy of i is also 1, same as parent. The child breaks out of the loop. I get different results from you when I run it:

[wally@zf ~]$ ./a.out
i=1
i=2
i=3
i=4
べ繥欢鉨o。 2024-08-28 23:09:25

你使用什么风格的 Unix? fork 是否有可能不返回 int ?

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

What flavor of Unix are you using. Is there any chance fork isn't returning an int?

In that case the pid[i] > 0 compare might fail.

追星践月 2024-08-28 23:09:25

该表达式

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

不会达到您的预期。你可能想说

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

The expression

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

won't do what you expect. You probably meant to say

if ((pid[i] = fork()) == -1) {
冷清清 2024-08-28 23:09:25

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

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

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

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

Each child process is continuing the loop with the current value of i when spawned. As a result, the first process prints an i of 1 and then spawns a child. Next, both of those process print an i of 2 and spawn a child, for a total of four processes. All four of those print an i of 3 and each spawn a new process, and finally, all 8 processes print a value of 4.

EDIT: Sorry, I overlooked the part where the parent was supposed to be exiting the loop. As for why that's not happening, it might be because the PID is stored as a signed integer but is high enough to pass the maximum signed value, making it negative. Does it work if you make this replacement?

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

to

else if(pid[i] != 0) break;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文