Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 这个fork()是如何工作的_C++_C_Linux - Fatal编程技术网

C++ 这个fork()是如何工作的

C++ 这个fork()是如何工作的,c++,c,linux,C++,C,Linux,你能告诉我,为什么这个程序的输出是这样的: 1. 2. 2. 5. 5. 3. 4. 5. 4. 5. 3. 4. 5. 4. 五, 快速解释为什么会这样?谢谢 main() { printf("1\n"); fork(); printf("2\n"); if(fork()==0) { printf("3\n"); fork(); printf("4\n"); } printf("5\n");

你能告诉我,为什么这个程序的输出是这样的: 1. 2. 2. 5. 5. 3. 4. 5. 4. 5. 3. 4. 5. 4. 五,

快速解释为什么会这样?谢谢

main()
{
    printf("1\n");
    fork();
    printf("2\n");
    if(fork()==0)
    {
        printf("3\n");
        fork();
        printf("4\n");
    }
    printf("5\n");
}

这是因为您并不总是测试
fork()
调用结果。零结果路径将保留为父进程,而else部分将作为子进程执行。因为您没有测试每个代码都遵循
fork()调用将在两个进程中重复(并执行)。

假设没有对
fork
的调用失败,则程序的输出应被认为是这样的:

1
2     2
  3     3
  4 4   4 4
5 5 5 5 5 5
每列表示一个进程的输出。它们都以某种随机顺序被序列化到
stdout
,只受以下约束:在一列中,每个字符不能出现在其正上方的字符之前;每列中最上面的字符不能出现在上面和左边的字符之前

注意,现在您的程序依赖于C库,注意到stdout是一个终端,因此将其设置为行缓冲。如果在运行程序时将
stdout
重定向到一个文件或管道,则可能会得到完全不同的输出,例如

$ ./a.out | tr '\n' ' '
1 2 5 1 2 5 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5
。。。因为在这种情况下,所有的输出都会被缓冲,直到从
main
返回,并且缓冲会被复制到每个子进程中。添加

setvbuf(stdout, 0, _IONBF, 0);

在第一个
之前,printf
语句将防止输出重复。(在这种情况下,您可以使用
\u IOLBF
来代替,但是
\u IOLBF
对于这样的代码更安全。)

以图形方式显示会更容易一些,但是每次调用fork()时,都会有另一个进程继续执行相同的代码。因此:

进程1(原始进程):打印1,然后创建进程2,打印2,然后创建进程3,但不返回0,然后打印5

进程2:打印2,然后创建进程4,但不返回0,然后打印5

流程3:打印3,然后创建流程5,打印4,打印5

流程4:打印3,然后创建流程6,打印4,打印5

流程5:打印4,打印5

流程6:打印4,打印5

但它们都发生在相似的时间,所以你为什么会得到这些数字


希望有帮助。第一次回答

Micheal,我需要查看fork()方法内部的代码才能确定,但由于它正在打印数字和额外的数字,我能想到的唯一可能的解释是,您的fork()方法可能有自己的打印方法


Robin

以某种方式来看,假设在fedora中,父对象有机会首先执行,然后是子对象,但在其他类似ubuntu的情况下,子对象有优先权,在此基础上,您将看到输出。在这个范围内与printf函数没有关系,但是我们可以预测这个方法的主体将在这里执行多少次。我附上一张图片,这可能对您有所帮助。

这里,当1只打印一个进程时。在执行第一个fork之后,两个不同的进程都有fork,但都在if语句中。因此,一个再次创建了两个过程,但只有一个有机会进入if身体。再次执行fork,并再次生成新进程。公式为工艺总数量=2*n。其中n是函数中fork()方法的数目。因此,总共六种方法对打印任何数字(如2、3、4)都有一定的条件,但5对所有方法都是通用的,因此5将打印六次。 也许我的帖子对你有帮助 谢谢
asif aftab

由于输出缓冲区的执行顺序和继承,输出是不确定的,确定的方法是

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

main()
{
  printf("1\n");
  fflush(stdout);
  if (fork()) wait(0);
  printf("2\n");
  fflush(stdout);
  if(fork()==0)
    {
      printf("3\n");
      fflush(stdout);
      if (fork()) wait(0);
      printf("4\n");
    } else wait();
  printf("5\n");
}
#包括
#包括
main()
{
printf(“1\n”);
fflush(stdout);
如果(fork())等待(0);
printf(“2\n”);
fflush(stdout);
如果(fork()==0)
{
printf(“3\n”);
fflush(stdout);
如果(fork())等待(0);
printf(“4\n”);
}否则等待();
printf(“5\n”);
}
使用
fork()
我们创建了一个子进程,并且没有父进程或子进程的执行模式保证,如前所述

如果您想要有一个执行模式,最好检查父[pid不是0]或子[pid是0]的
fork()
,并使其中一个处于休眠状态,以便调度器将另一个置于执行状态


您可以找到更多信息。

实际上,此输出并不总是相同的,因为printf不是线程安全的,因此,可能是当printf试图将某些内容输出到stdout时,它被阻止,无法打印。您必须尝试线程安全功能,如C++中的CUT .@ FrnANDO.ReYES。问题是关于分叉进程,线程安全不会造成(相关)差异。在<<代码> Fooe<代码>之前,始终遵守代码> FFLUH(STDUT)< /COD>和<代码> FLUHUP(STDRR)< /代码>,这将防止缓冲数据输出twice@alexgirao好的方面(在大多数Unix C库中,OP依赖于终端输出的自动行缓冲)。关于这一点,我在回答中添加了一些内容。有关
fork
,请参阅-它创建一个子进程,在fork语句之后继续执行。谢谢,这很有帮助。谢谢,这很有帮助。谢谢,这很有帮助。