fork() 在 C++ 中的工作

Working of fork() in C++

本文关键字:工作 C++ fork      更新时间:2023-10-16

我在C++有这个程序。

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

using namespace std;
int main()
{
    cout<<"*n";
    fork();
    cout<<"An";
    fork();
    cout<<"Bn";
    fork();
    cout<<"Cn";
    return 0;
}

输出为:

*
A
B
C
*
A
B
C

我认为应该是:

*
A
B
C
A
B
C
B
C
C

说明:"*"应通过一个过程打印。现在,在fork()之后,应该打印2个"A",子"B"和"C"。

链接到代码

根据对该问题的评论,答案是 ideone.com 在线编译器中的fork只是将您限制为进程的一个实例,并缓冲您的输出。

更新:实际上,它也在撒谎:http://ideone.com/oXqqwM 表明fork()声称成功,但只有第一个会生成您的流程的新副本。

我怀疑如果你检查fork()的返回值,你会得到一些关于你所看到的令人惊讶的行为的线索——除了第一个之外,所有的行为都会返回 -1——如果你使用std::endl你可能会避免第一个*

预期的结果是,此时每个fork()都会复制正在运行的进程,因此与前一个字符相比,您希望看到每个字符的两倍,除了缓冲意味着在fork()时缓冲区中可能仍有以前的字符。

因此,预计有 1 个或多个"*"、2 个或更多"A"、4 个或更多"B"或 8 个或更多"C",但如果fork()失败,数字将被封顶。

对 1 "*"、"2 个 A"、3 个"B"和 4 个"C"的期望表明你忽略了从fork()出来的两个过程都会到达下一个fork(),所以你加倍,而不是递增一个。

所以...如果您得到不止一个*那么就会发生一些奇怪的事情,我怀疑它是特定于实现的...... fork将为每个子进程提供文件描述符的副本,包括stdout...所以在你的实现中,它也获得了 std::cout 流的有效副本......它已经有一个加载了*的缓冲区......

我认为如果您更改程序以包含刷新,您将看到与我相同的操作:

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

using namespace std;
int main()
{
    cout<< "*n";
    flush(cout);
    fork();
    cout<<"An";
    flush(cout);
    fork();
    cout<<"Bn";
    flush(cout);
    fork();
    cout<<"Cn";
    flush(cout);
    return 0;
}