【问题标题】:Go pipe write end being closed, why?Go pipe write end 被关闭,为什么?
【发布时间】:2021-06-30 05:28:49
【问题描述】:

我刚刚阅读了一些 Go 代码,它们执行以下操作:

type someType struct {
    ...
    ...
    rpipe io.ReadCloser
    wpipe io.WriteCloser
}

var inst someType

inst.rpipe, inst.wpipe, _ := os.Pipe()
cmd := exec.Command("some_binary", args...)
cmd.Stdout = inst.wpipe
cmd.Stderr = inst.wpipe
if err := cmd.Start(); err != nil {
    ....
}
inst.wpipe.Close()
inst.wpipe = nil

some_binary 是一个长期运行的进程。

  1. 为什么inst.wpipe 关闭并设置为零?如果不关闭会怎样?关闭 inst.wpipe 是否常见/必要?
  2. dup2(pipe_fd[1], 1)cmd.Stdout = inst.wpipe; inst.wpipe.Close() 的 C 类似物吗?

【问题讨论】:

  • 哦,抱歉,打错了。让我修复它。 stdout 和 stderr 都设置为 wpipe。

标签: linux go


【解决方案1】:

该代码是想要读取其他程序生成的输出的典型程序。 os.Pipe() 函数返回一对连接的 os.File 实体(或者,在错误时——不应简单地忽略——不),其中第二个(wwpipe)实体上的写入显示为第一个 (r / rpipe) 实体上的可读字节。但是——这是你第一个问题的一半答案的关键——读者如何知道所有作者何时完成写作?

为了让读者获得 EOF 指示,所有有权或有权访问管道写入端的写者必须调用close 操作。通过将管道的写入端传递给以cmd.Start() 开头的程序,我们允许该命令访问管道的写入端。当该命令关闭该管道时,具有访问权限的实体之一已关闭该管道。但另一个具有访问权限的实体尚未关闭它:我们拥有写访问权限。

为了查看 EOF,我们必须关闭对 我们的wpipe 的访问,并使用wpipe.Close()。所以回答前半部分:

  1. 为什么inst.wpipe 关闭并设置为零?

set-to-nil 部分可能有也可能没有任何功能;你应该检查其余的代码,看看是否有。

  1. dup2(pipe_fd[1], 1)cmd.Stdout = inst.wpipe; inst.wpipe.Close()?的C类似物

不准确。 dup2 级别在 POSIX 操作系统区域中较低,而 cmd.Stdout 处于更高(与操作系统无关)级别。 cmd.Start() 的 POSIX 实现将在调用 fork(或类似的东西)之后像这样调用 dup2(或类似的东西)。 inst.wipe.Close() 的 POSIX 等效项是 close(wfd),其中 wfdwpipe 中的 POSIX 文件号。

在没有任何更高级别的 C 代码中,我们会有类似的内容:

int fds[2];

if (pipe(fds) < 0) ... handle error case ...
pid = fork();
switch (pid) {
case -1: ... handle error ...

case 0: /* child */
    if (dup2(fds[1], 1) < 0 || dup2(fds[1], 2) < 0) ... handle error ...
    if (execve(prog, args, env) < 0) ... handle error ...
    /* NOTREACHED */

default: /* parent */
    if (close(fds[1]) < 0) ... handle error ...
    ... read from fds[0] ...
}

(尽管如果我们足够小心地检查来自 close 的错误,我们可能应该足够小心地检查 pipe 系统调用是否返回了描述符 0 和 1,或 1 和 2,或者2 和 3,在这里——尽管我们可能通过确保 0、1 和 2 至少对/dev/null 开放来处理这个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-27
    • 2012-04-08
    • 2014-12-25
    • 1970-01-01
    相关资源
    最近更新 更多