Pseudoterminal master读取它刚才写的内容

时间:2011-05-19 16:30:35

标签: python pty

我正在开发一个项目,它将使用串行端口连接的“虚拟设备”(python进程)与也使用串行端口的真实设备进行接口,我正在使用伪终端来连接多个(超过2个)这些串口通信过程(建模串行设备)在一起,我遇到了一些障碍。

我有一个生成伪终端的python进程,将pty的slave端符号链接到文件(因此进程可以创建文件名的pyserial对象),而主结束由我的pty生成过程保存,读;当数据进入一个主设备时,数据会被记录,然后写入其他主设备。如果监听过程始终存在,则此方法有效。

问题是虚拟设备何时死亡或从未启动(这是此项目的有效用例)。在我的系统上,似乎如果将数据写入pty的主端,如果没有任何内容正在侦听从端,那么对该master执行read调用将返回刚写入的数据!这意味着设备不止一次地接收相同的数据 - 不好!

示例:

>>master, slave = pty.openpty()
>>os.write(master,"Hello!")
6
>>os.read(master,6)
'Hello!'

我希望read()的调用阻塞,直到从器件发送数据。实际上,这是从设备的行为 - 它可以写入,然后os.read(slave,1)将阻塞,直到主设备写入数据。

我的“虚拟设备”需要能够传递文件名才能打开串口对象;我试图对主端进行符号链接,但这导致我的虚拟设备打开/ dev / ptmx,这会创建一个新的伪终端对,而不是链接回已经存在的从属对象!

有没有办法改变主人的行为?或者甚至只是获取与从属设备相对应的主文件名(不仅仅是/ dev / ptmx)?

提前致谢!

2 个答案:

答案 0 :(得分:4)

我很确定这是因为默认情况下是回显。借用Python termios docs,你可以这样做:

master, slave = os.openpty()    # It's preferred to use os.openpty()
old_settings = termios.tcgetattr(master)
new_settings = termios.tcgetattr(master)   # Does this to avoid modifying a reference that also modifies old_settings
new_settings[3] = new_settings[3] & ~termios.ECHO
termios.tcsetattr(master, termios.TCSADRAIN, new_settings)

您可以使用以下内容恢复旧设置:

termios.tcsetattr(master, termios.TCSADRAIN, old_settings)

答案 1 :(得分:2)

如果有人发现这个问题,并且jszakmeister的回答不起作用,那么这对我有用。

openpty似乎在规范模式下创建pty,并启用了echo。这不是人们所期望的。您可以使用tty.setraw函数更改模式,就像在这个简单的openpty echo服务器示例中一样:

master, slave = os.openpty()
tty.setraw(master, termios.TCSANOW)
print("Connect to:", os.ttyname(slave))

while True:
    try:
        data = os.read(master, 10000)
    except OSError:
        break
    if not data:
        break
    os.write(master, data)