如果程序读取和写入同一个缓冲区会发生什么?

问题描述 投票:0回答:3

我遇到的是我写了一个简单的Python脚本,名为

tt.py
:

import time

while True:
    print(123)
    time.sleep(0.5)

我通过

python tt.py &
运行它,它将持续输出到终端
123
。如果我在输入
l
几秒钟后输入字符
s
,则命令
ls
可以正常工作。

但是为什么,据我所知,有一点伪终端:主控端和从属端。我认为 bash 的 stdin、stdout、stderr 被重定向到从属端。所以在我看来,bash 应该返回像

l123\n123\n...s
not find 这样的命令。

更普遍的问题是,当它们指向相同的文件描述符时,bash 如何知道哪个是输出哪个是输入?

或者我在这种情况下哪里理解错了,提前谢谢!


更新:

我知道 stdin 和 stdout 指向不同的描述符,但它们可以指向相同的描述符,对吗?

所以在我看来,python 脚本的标准输出到 psuedoterminal 的从属端,而终端在主控端显示流。似乎我不明白终端标准输入如何转到 bash 的标准输入。不是先去master端然后去slave端然后bash吗?

如果是这样,我认为主端的事情会变得混乱,因为它同时接收 python 脚本的输出和终端的输入。

python bash terminal pty
3个回答
4
投票

伪终端由两个独立的数据通道组成,并且每个通道都有自己的缓冲区。

有一个通道将写入从属 pty 的数据传输到主 pty。还有另一个通道将写入主 pty 的数据传输到从 pty。

写入 pty 从属端的任何内容都由连接到主端的进程读取。在本例中,它是您的终端应用程序。它在终端窗口中显示此数据。

python
ls
都在写入从属pty,并且它们的输出显示在窗口中。

当应用程序从从属 pty 读取时,它会获取其他进程写入主控端的内容。终端应用程序写入您在键盘上键入的内容,而不是发送到从属端的输出。

因此 python 脚本的输出不会被 shell 读取为输入。

如果两个方向不独立,则每个生成输出并读取输入的程序都会完全混乱,因为它最终会读取自己的输出。


4
投票

您误解了 POSIX 标准流 的工作原理。有单独的流用于输入(

stdin
),以及用于正常和错误输出(
stdout
stderr
)。这些并不是唯一可能的流。

当您将进程放入后台(使用

&
)时,该进程将继承与 bash 相同的标准流。所以Python进程
stdout
与bash
stdout
是同一个流。然而,Bash 不从标准输出读取。您的 PTY(终端)只是显示写入标准输出流的所有数据。

明确地说:bash 永远不会在其

stdin
上接收Python写入stdout的数据。您在键盘上输入的字符将发送到 bash 进程
stdin
流,与 Python 进程生成的输出完全分开。

请注意,从 bash 和 Python 的角度来看,它们只是连接到标准流(它们可以测试流是否连接到终端),流是否连接到真实终端并不重要或伪终端。伪终端也不会将 Python 输出发送回 bash;它的行为就像任何终端一样;从连接的程序接收到的数据被视为键盘输入。 PTY 的主从端都知道如何处理输入和输出并将它们分开:

graph of keyboard and display connected to a PTY, which in turn is connected to a bash and python process 一般来说,您会在屏幕上看到

ls

回显,因为 PTY 设置为

echo input
(bash 在收到输入后不会将其写回)。


2
投票
所以在我看来,bash 应该返回像 l123 这样的命令 123 ...没有找到。

交互模式下的

bash

运行其

stdin
上提供的命令(例如键盘输入)。子进程(在本例中为 python)写入从
bash
继承的 stdout(例如,显示)。默认情况下,标准输出数据不会进入标准输入(尽管
如果您愿意,可以这样做
)。 在这种情况下,

python

是否是bash的后台/前台工作并不重要(它不会改变python输出的位置,我们不关心这里的

stty tostop
)或者
pseudoterminal
是否是使用或者您直接查看consolebash 可以使用 fork、exec 系统调用来启动子进程,并且
dup2
来配置其 stdin/stdout/stderr 流,例如,
通过递归调用实现的管道
——单个命令没有重定向。

© www.soinside.com 2019 - 2024. All rights reserved.