伪终端主机读取它刚刚写入的内容

发布于 2024-11-08 00:45:16 字数 796 浏览 3 评论 0原文

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

我有一个生成伪终端的 python 进程,将 pty 的从属端符号链接到文件(因此进程可以创建文件名的 pyserial 对象),而主端由我的 pty 生成进程保留并读取;当数据进入一个主站时,数据会被记录下来,然后写入其他主站。如果倾听过程始终存在,这种方法就有效。

问题是虚拟设备死亡或从未启动(这是该项目的有效用例)。在我的系统上,似乎如果数据写入pty的主端,如果从端没有任何监听,则在该主端上调用read将返回刚刚写入的数据!这意味着设备多次接收相同的数据——这不好!

示例:

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

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

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

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

提前致谢!

I'm working on a project that interfaces "virtual devices" (python processes) that use serial port connections with real devices that also use serial ports, and I'm using pseudoterminals to connect several(more than 2) of these serial-port communications processes (modeling serial devices) together, and I've hit a bit of a snag.

I've got a python process that generates pseudoterminals, symlinks the slave end of the pty to a file (so the processes can create a pyserial object to the filename), while the master ends are kept by my pty generating process and read; when data comes in on one master, the data is logged and then written to the other masters. This approach works if the listening process is always there.

The problem is when the virtual device dies or is never started (which is a valid use case for this project). On my system, it seems, that if data is written to a master end of a pty, if there is nothing listening to the slave end, calling read on that master will return the data that was just written! This means that devices receive the same data more than once -- not good!

Example:

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

I would prefer that the call to read() block until the slave sends data. In fact, this is the behavior of the slave device -- it can write, and then os.read(slave,1) will block until the master writes data.

My "virtual devices" need to be able to pass a filename to open a serial port object; I've attempted to symlink the master end, but that causes my virtual devices to open /dev/ptmx, which creates a new pseudoterminal pair instead of linking back to the slaves that already exist!

Is there any way to change the behavior of the master? Or even just get a filename to the master that corresponds to a slave device (not just /dev/ptmx)?

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

纸伞微斜 2024-11-15 00:45:16

我很确定这是因为默认情况下回显处于打开状态。要从 Python termios 文档 借用,您可以这样做:

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)

I'm pretty sure this is because echoing is on by default. To borrow from the Python termios docs, you could do:

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)

You can use the following to restore the old settings:

termios.tcsetattr(master, termios.TCSADRAIN, old_settings)
裸钻 2024-11-15 00:45:16

如果有人发现这个问题,而 jszakmeister 的答案不起作用,这对我有用。

openpty 似乎在打开 echo 的情况下以规范模式创建 pty。这不是人们所期望的。您可以使用 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)

In case someone finds this question, and jszakmeister's answer doesn't work, here is what worked for me.

openpty seems to create pty's in canonical mode with echo turned on. This is not what one might expect. You can change the mode using the tty.setraw function, like in this example of a simple openpty echo server:

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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文