为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
jeck猫 2022-08-24 10:49:32
我刚刚阅读了一些Go代码,它执行了如下操作:type someType struct {    ...    ...    rpipe io.ReadCloser    wpipe io.WriteCloser}var inst someTypeinst.rpipe, inst.wpipe, _ := os.Pipe()cmd := exec.Command("some_binary", args...)cmd.Stdout = inst.wpipecmd.Stderr = inst.wpipeif err := cmd.Start(); err != nil {    ....}inst.wpipe.Close()inst.wpipe = nilsome_binary是一个长时间运行的进程。为什么关闭并设置为 nil?如果它没有关闭会发生什么?关闭inst.wpipe是否常见/必要?inst.wpipe的 C 类比是 ?dup2(pipe_fd[1], 1)cmd.Stdout = inst.wpipe; inst.wpipe.Close()
查看完整描述

1 回答

?
慕的地8271018

TA贡献1796条经验 获得超4个赞

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

要使读取器获得 EOF 指示,具有或有权访问管道写入端的所有编写器都必须调用该操作。通过将管道的写入端传递给我们以 开始的程序,我们允许该命令访问管道的写入端。当该命令关闭该管道时,具有访问权限的其中一个实体已关闭该管道。但是另一个具有访问权限的实体尚未关闭它:我们有写入访问权限。closecmd.Start()

要查看 EOF,则必须使用 关闭对 的访问。 所以回答前半部分:wpipewpipe.Close()

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

集合到部分可能具有任何功能,也可能不具有任何功能;您应该检查代码的其余部分,以确定它是否确实如此。nil

  1. 是 C 类比dup2(pipe_fd[1], 1)cmd.Stdout = inst.wpipe; inst.wpipe.Close()?

不完全是。该级别在 POSIX OS 区域中向下,而在较高(独立于操作系统)级别。POSIX 的实现最终将在调用(或等效项)后调用(或等效项)。等效的 POSIX 是 中的 POSIX 文件编号。dup2cmd.Stdoutcmd.Start()dup2forkinst.wipe.Close()close(wfd)wfdwpipe

在没有任何更高层次的包装的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] ...

}

(尽管如果我们足够小心地检查来自 的错误,我们可能应该足够小心地检查系统调用是否在这里给了我们描述符0和1,或1和2,或2和3 - 尽管也许我们通过确保0,1和2至少对)进行处理。closepipe/dev/null


查看完整回答
反对 回复 2022-08-24
  • 1 回答
  • 0 关注
  • 142 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号