4

当我浏览帖子时,我在这里遇到了这个例子,据说proc1.stdout.close()需要调用适当的退出proc1,生成SIGPIPE

import subprocess

proc1 = subprocess.Popen(['ps', 'cax'], stdout=subprocess.PIPE)
proc2 = subprocess.Popen(['grep', 'python'], stdin=proc1.stdout,
                         stdout=subprocess.PIPE, stderr=subprocess.PIPE)

proc1.stdout.close() # Allow proc1 to receive a SIGPIPE if proc2 exits.
out, err = proc2.communicate()
print('out: {0}'.format(out))
print('err: {0}'.format(err))

但是,我不清楚这一点。请修正我的理解。

  1. SIGPIPE当 aPIPE尝试写入 closed时发生PIPE
  2. 作家PIPEproc1stdout,读者PIPEproc2stdin
  3. proc1退出时将proc2退出并proc1尝试将数据写入proc2's stdin PIPE。因为
    • proc2退出时stdin PIPE关闭proc2
    • SIGPIPE发生在,proc1因为proc1尝试写入已关闭proc2stdin PIPE.

据我了解,无论收盘如何,SIGPIPE都会发生并退出。proc1proc1stdout

我想念什么?


编辑

从@unutbu 的评论中阅读帖子后......

我认为复制的文件描述符(proc1.stdout)是写入器管道,而不是读取器管道。因此,有两个写入器 PIPE 和一个读取器 PIPE 相互连接。

因此,SIGPIPE将在proc2退出时生成,因为proc2只有一个具有阅读器管道的进程(退出时将关闭proc2)。

但是,上面的帖子似乎说通过复制有两个阅读器 PIPE,proc1.stdout因此SIGPIPE即使退出后也不会生成,proc2因为还有另一个阅读器 PIPE 打开。以下是帖子的一部分。

因此,通过立即关闭 p1.stdout,您可以确保从 dmesg stdout 读取的唯一剩余文件句柄是 grep 进程,如果该进程退出,dmesg 会收到 SIGPIPE。

我并不是说这个帖子是错误的,但我只是想修正我的理解。先感谢您。

4

1 回答 1

7
proc1 = subprocess.Popen(['ps', 'cax'], stdout=subprocess.PIPE)

在父进程和之间创建一个管道proc1

|        |         |       |
| parent |-<-----<-| proc1 |                   
|        | ^       |       |
           |                     
       p1.stdout   

p1.stdout是父母从proc1.

proc2 = subprocess.Popen(['grep', 'python'], stdin=proc1.stdout,
                         stdout=subprocess.PIPE, stderr=subprocess.PIPE)

将管道的副本从 proc1 连接到 proc2:

|        |         |       |         |       |
| parent |-<-----<-| proc1 |->----->-| proc2 | 
|        |         |       |         |       |

通过调用p1.stdout.close(),我们关闭了父进程的管道:

|        |         |       |         |       |
| parent |       <-| proc1 |->----->-| proc2 | 
|        |         |       |         |       |

现在当proc2终止时,它的管道一侧也关闭:

|        |         |       |         |       |
| parent |       <-| proc1 |->       | proc2 | 
|        |         |       |         |       |

下次proc1尝试写入管道时,会生成一个 SIGPIPE 信号,该信号允许proc1终止,因为它知道没有人在其管道的另一端监听。

于 2017-12-30T15:00:54.643 回答