首页 > 解决方案 > 无法从外部进程读取 PTY(伪终端文件)

问题描述

我正在打开一个 PTY(在 Python/Linux 中)并写信给它。我可以通过minicom完美地阅读它。但是,我无法在另一个 Python(或 C++)程序中读取它。这是一个最小化的示例:

producer.py(打开 pty / 写入它):

import os, sys
from time import sleep
master_fd, slave_fd = os.openpty()
print "minicom -D %s" % os.ttyname( slave_fd )
for i in range(0,30): 
    d = str(i % 10)
    os.write( master_fd, d )
    sys.stdout.write( d )
    sys.stdout.flush()
    sleep( 2 )
os.close( slave_fd )
os.close( master_fd )
print "\nDone"    

consumer.py(尝试打开/读取):

import os, sys
from time import sleep
pts=raw_input("Enter pts number:")
while True:
    fd=0
    try:
        fd=os.open('/dev/pts/%d' % (pts,), 
            os.O_RDONLY | os.O_NONBLOCK )
        sys.stdout.write( os.read(fd, 1 ) )  
        sys.stdout.flush()       
    except Exception as e: print e
    if fd: os.close(fd)    
    sleep(1)        

读取的结果总是:

[Errno 11] 资源暂时不可用

如果我以阻塞模式阅读,它只会阻塞,直到生产者终止。然后,它说该文件不存在。

我花了几天时间尝试设置各种模式、权限、锁等,但似乎没有什么能让我到任何地方。这种事情很容易与常规文件一起工作。另外,请再次注意minicom 可以毫无障碍地读取 pty。此外,使用lsof我可以看到 minicom 和我的 consumer.py 脚本确实打开了文件——这只是在 python 示例中不起作用的读取。那么minicom的秘密是什么?我尝试在 minicom 源代码中找到这样的东西,但我没有成功找到我可以使用的任何东西。

理想情况下,我的制作人会使其易于打开和阅读(就像在我的消费者示例中一样),但如果我能看到这项工作,我愿意修改任何一端......

标签: pythonclinuxpty

解决方案


是什么让您认为您无法打开 PTY?您的代码中没有任何内容提供有关哪个系统调用失败的信息。

最可能的情况是os.read()调用失败并显示错误代码EAGAIN(aka EWOULDBLOCK),因为您已在非阻塞模式下打开 PTY。没有要读取的数据,因为 PTY 是 tty,并且 tty 最初处于“熟”模式,这意味着在发送行尾字符或某些中断字符之前,不会将任何输入传递给消费者。Minicom 可能会通过 termios 调用将 pty 置于“原始”模式,您也应该这样做。

我猜您并不想将 PTY 置于非阻塞模式。除非您设置事件轮询或选择循环,否则您将反复收到EAGAIN“错误”(这不是真正的错误),并且您真的不想在重试之前等待整整一秒钟。(您也不是真的想关闭并重新打开 PTY。)建议您将 PTY 留在阻塞模式,但将其配置为在每次击键时立即返回(再次,使用termios)。


推荐阅读