Linux下的伪串行通信

2024-05-16 23:37:11 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个应用程序,我想模拟设备和“调制解调器”之间的连接。设备将连接到串行端口,并通过该端口与软件调制解调器进行通信。

出于测试目的,我希望能够使用模拟软件设备来测试发送和接收数据。

示例Python代码

device = Device()
modem  = Modem()
device.connect(modem)

device.write("Hello")
modem_reply = device.read()

现在,在我的最后一个应用程序中,我将只传递/dev/ttyS1或COM1或其他供应用程序使用的内容。 但我怎么能在软件里做到这一点呢?我正在运行Linux,应用程序是用Python编写的。

我试过做一个FIFO(mkfifo ~/my_fifo),这确实有效,但是我需要一个FIFO来写,一个FIFO来读。我想要的是打开~/my_fake_serial_port并读写它。

我还使用了pty模块,但也不能让它工作。我可以从pty.openpty()中获取主文件和从文件描述符,但尝试读取或写入它们只会导致IOError Bad File Descriptor错误消息。

更新

注释指出了SO问题Are there some program like COM0COM in linux?,它使用socat来设置虚拟串行连接。 我是这样用的:

socat PTY,link=$HOME/COM1 PTY,link=$HOME/COM2

谢谢你们给了我宝贵的信息。 我选择接受Vinay Sajips的回答,因为这是我在socat建议出现之前所寻求的解决方案。看来效果还不错。


Tags: 端口目的应用程序home调制解调器软件mydevice
3条回答

下面是pythonic版本的pts仿真(caf)串行通信:

from serial import Serial

driver = MyDriver()  # what I want to test
peer = serial.Serial()
driver.port.fd, peer.fd = posix.openpty()
driver.port._reconfigurePort()
peer.setTimeout(timeout=0.1)
peer._reconfigurePort()
driver.start()

# peer.write("something")
# driver.get_data_from_serial()

它比模拟串行有一些优点,即使用串行代码和一些串行端口人工制品。

如果要测试串行端口的打开,可以交换主端口和从端口,并使用os.ttyname(salve_fd)作为串行端口名。不过,我不能保证交换主从的副作用。最值得注意的是,你可以关闭和重新打开奴隶,但如果你关闭主奴隶也死亡。

如果您的测试代码在同一个进程中运行,这就像一个符咒。我还没有用多个/单独的过程来解决这些问题。

你用的是伪终端。为此,您的模拟软件设备需要首先打开一个伪终端主机-这是当它与您正在测试的串行软件对话时,它将读取和写入的文件描述符。然后,它需要授予对伪终端从机的访问和解锁权限,并获取从机设备的名称。然后它应该在某个地方打印出从设备的名称,这样您就可以告诉其他软件打开它作为串行端口(即,该软件将打开类似/dev/pts/0的名称,而不是/dev/ttyS1)。

然后模拟器软件只从伪终端的主端读写。在C语言中,它看起来是这样的:

#define _XOPEN_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>

int main(int argc, char *argv[])
{
    int pt;

    pt = open("/dev/ptmx", O_RDWR | O_NOCTTY);
    if (pt < 0)
    {
        perror("open /dev/ptmx");
        return 1;
    }

    grantpt(pt);
    unlockpt(pt);

    fprintf(stderr, "Slave device: %s\n", ptsname(pt));

    /* Now start pretending to be a modem, reading and writing "pt" */
    /* ... */
    return 0;
}

希望这很容易转换成Python。

最好使用pyserial与串行端口通信,您只需创建serial.Serial类的模拟版本,该类实现readreadlinewrite和您需要的任何其他方法。

相关问题 更多 >