代码之家  ›  专栏  ›  技术社区  ›  Derek Litz

关于管道的基本问题

  •  1
  • Derek Litz  · 技术社区  · 15 年前

    关于我不确定的管道,我有一些基本问题。

    a)如果写入管道的进程被终止(即sigkill sigint),标准行为是什么?它冲洗管道吗?或者行为未定义?

    b)如果流程正常返回,标准行为是什么?是否保证冲洗管道并关闭管道?(当然没有明确地这么做)。

    我希望这些答案尽可能笼统,但实际上,如果完全取决于操作系统规范,我可以接受!但是,如果有一个POSIX标准或者当前定义的Windows行为,我将非常感谢您的了解。

    谢谢。

    2 回复  |  直到 15 年前
        1
  •  2
  •   Jonathan Leffler Toon Krijthe    15 年前

    A.如果写入管道的进程被终止(即sigkill-sigint),标准行为是什么?它冲洗管道吗?或者行为未定义?

    Sigkill决不允许任何清理-进程会死掉。对于sigint,这取决于进程是否处理信号。如果是这样,它可能会通过exit(2)退出,这将刷新标准的I/O文件句柄。问题是-管道是连接到标准输出还是通过popen()?如果是,则为未处理的缓冲数据 可以 冲洗;如果没有,则没有缓冲数据,因此冲洗无关紧要。

    如果管道中有未读的数据,那么该数据将保留在管道中,以备读者收集——假设有一个读者。

    B.如果进程正常返回,标准行为是什么?是否保证冲洗管道并关闭管道?(当然没有明确地这么做)。

    这取决于管道是否通过标准I/O连接。如果没有,则没有挂起的内容。如果是,那么是的,当标准I/O流关闭时,缓冲区中的任何材料都将被刷新。


    谢谢你提供信号和未读数据的信息,但是我对标准的I/O管道连接有点困惑。在您提到popen()之后,我查找了它,并且手册页说它的返回值与I/O流相同,并且流在默认情况下是完全缓冲的。我只是不清楚这两者之间的区别,也不明白区别来自何处。

    创建管道的基本系统调用是 pipe(2) . 它创建两个文件描述符,一个用于管道的读取端,一个用于写入端。如果您对它们不做任何其他操作,那么它们仍然是文件描述符,具有未缓冲的输出(通过写入(2)和相关的系统调用)。如果进程终止,则应用程序中没有缓冲;管道将关闭。

    如果你使用 popen(3) 然后它会为你做更多的工作。它仍然调用 管道(2) 创建管道,但它会 fork(2) . 子进程安排管道的正确配置并启动子进程。父级还关闭管道的未使用端,并使用 fdopen(3) 为调用进程创建一个标准的I/O文件流。

    对于文件流,如果I/O缓冲区中有数据,则关闭或等效操作将确保刷新未处理的数据并关闭文件描述符。

        2
  •  1
  •   Richard Pennington    15 年前

    正常的行为是,当进程终止时,所有文件描述符都将关闭。这意味着管道和其他打开的文件描述符一样,是正常关闭的。

    不过,管道有一个有趣的地方:在POSIX中,如果一个进程写入一个已关闭的管道,那么编写器将得到一个信号sigpipe。


    编辑:

    警告:S SIGX终止和正常终止的区别在于,与任何其他文件写入一样,您可能会丢失已缓冲(通过文件写入)但尚未写入文件描述符的数据。