Linux Go管道写入端被关闭,为什么?

Linux Go管道写入端被关闭,为什么?,linux,go,Linux,Go,我只是读了一些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 c

我只是读了一些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
某些二进制文件是一个长期运行的过程

  • 为什么
    inst.wpipe
    关闭并设置为零?如果它不关闭会发生什么?关闭仪表管道是否常见/必要
  • dup2(pipe_fd[1],1)
    cmd.Stdout=inst.wpipe的C类似物;inst.wpipe.Close()

  • 该代码是希望读取其他程序生成的输出的典型程序。该函数返回一对连接的
    os.File
    实体(或者,如果出现不应简单忽略的错误,则返回),其中第二个(
    w
    wpipe
    )实体上的写入显示为第一个(
    r
    /
    rpipe
    )实体上的可读字节。但这是你第一个问题一半答案的关键,读者怎么知道所有作家都写完了

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

    要查看EOF,则必须使用
    wpipe.close()
    关闭对
    wpipe
    的访问。因此,答案是:

  • 为什么
    inst.wpipe
    关闭并设置为零
  • 设置为-
    nil
    部分可能有或可能没有任何功能;您应该检查代码的其余部分,以确定它是否存在

  • dup2(pipe_fd[1],1)
    cmd.Stdout=inst.wpipe的C类似物;inst.wpipe.Close()?
  • 不完全是这样。POSIX操作系统区域中的
    dup2
    级别降低,而
    cmd.Stdout
    级别更高(独立于操作系统)。
    cmd.Start()
    的POSIX实现在调用
    fork
    (或类似的东西)之后,将调用
    dup2
    (或类似的东西)。
    inst.wipe.Close()
    的POSIX等价物是
    Close(wfd)
    其中
    wfd
    wpipe
    中的POSIX文件号

    在没有任何更高级别包装的C代码中,我们会有如下内容:

    intfds[2];
    如果(管道(fds)<0)。。。处理错误案例。。。
    pid=fork();
    开关(pid){
    案例1:…处理错误。。。
    案例0:/*儿童*/
    如果(dup2(fds[1],1)<0 | | dup2(fds[1],2)<0)…处理错误。。。
    如果(execve(prog,args,env)<0)…处理错误。。。
    /*未到达*/
    默认值:/*父级*/
    如果(关闭(fds[1])<0)。。。
    …从fds[0]读取。。。
    }
    

    (虽然如果我们足够仔细地检查
    close
    中的错误,我们可能应该足够仔细地检查
    管道
    系统调用是否返回了描述符0和1,或1和2,或2和3,但在这里,我们可能会通过确保0、1和2至少对
    /dev/null
    打开来处理此问题。).

    哦,对不起,这是一个输入错误。让我来修复它。stdout和stderr都是,并设置为wpipe。