gpt4 book ai didi

multithreading - stdin、stdout 和 stderr 是共享的吗?

转载 作者:行者123 更新时间:2023-12-01 02:13:57 25 4
gpt4 key购买 nike

我试图了解三个流的行为 - stdout , stdinstderr .我无法从任何教科书中得到答案,所以我来到了这里。

我知道这三个存储在文件描述符表中,文件描述符为 0 (stdin)、1 (stdout) 和 2 (stderr)。我也知道这些不仅仅是文件描述符,而是可以重定向的 I/O 流。好的,那么分享怎么样?

考虑三种情况:

  • 当 fork() 被调用时 :子进程和父进程共享文件描述符,但它们是否具有相同的 stdin、stdout 和 stderr ?
  • 创建线程时 : 线程共享文件描述符,但 I/O 流?
  • 当 execl() 被调用时 : 在这种情况下,当前的过程镜像会被新的过程镜像覆盖。如果我这样做 execl("./a.out", "a.out", NULL); ,那么这个新的可执行文件会得到 stdin、stderr 和 stdout 的新副本吗?

  • 欢迎所有明智的答案。

    最佳答案

    为了了解正在发生的事情,请考虑这些是跨越流程边界的通信 channel 。我将避免称它们为流,因为它们用于不同的上下文,但它们是相关的。

    现在,首先,文件描述符只是表示这些 channel 的进程特定表的索引,它们基本上是一种不透明的句柄。但是,这是第一个答案:由于线程是进程的一部分,它们也共享这些描述符,因此如果您从两个线程写入同一个 channel ,它会通过同一个 channel 离开,因此在进程之外,两个线程是无法区分的。

    然后,当 fork() 被调用时,进程被有效地复制。这是通过写时复制优化完成的,但这仍然意味着它们也有代表这些通信 channel 的不同表。一个进程中索引为 2 的条目与 fork 中索引为 2 的条目不同。如果您创建了 C FILE*,则对于进程内的任何结构都是相同的。或 C++ std::stream在一个之上,它也与其他数据一起被复制。

    当 execl() 被调用时,进程仍然“拥有”某些对外的 channel 。这些是从管理进程的操作系统分配给它的。这意味着索引 2 仍然可以用于与外界进行通信。在启动时,运行时库将创建例如FILE* 在 C 中用于三个众所周知的 channel stdin、stdout 和 stderr。

    剩下的问题是当一个进程 fork 到外部 channel 时会发生什么。在这里,答案很简单, channel 是关闭的还是继承的,可以在每个 channel 的基础上进行配置。如果它是继承的,它在子进程中仍然可用。任何写入继承 channel 的内容也将在父进程的输出结束的地方结束。

    关于 fork 进程的标准输入,我实际上不确定,我认为输入默认是关闭的输入之一,因为将输入发送到多个目标没有意义。此外,我从未发现需要在子进程中实际处理来自 stdin 的输入,除非该输入是由父进程专门提供的(类似于 shell 中的管道,尽管它们是兄弟而不是父进程)。

    注意:我不确定这个描述是否清楚,请不要犹豫询问,我会尽力改进以让您理解。

    关于multithreading - stdin、stdout 和 stderr 是共享的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26687602/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com