我正在编写一个使用第三方 C 库的可执行文件(libmodbus如果重要的话)通过串行设备进行通信(在我的例子中,/dev/ttyUSB0
或者类似于通过基于 FTDI 芯片组的 USB 到 RS485 适配器进行 RS-485 通信)。这个基于 CLI 参数的可执行文件可以启动命令(在我的例子中,就像 modbus 客户端一样)然后等待响应(在我的例子中,来自外部 modbus 服务器),或者监听传入的命令(在我的例子中,就像modbus 服务器)然后生成响应。
我想自动测试我的可执行文件,而不需要某些外部设备。换句话说,我想启动可执行文件的两个实例,其中:
- 第一个实例进入 modbus 客户端模式并用于
/dev/xxxx
通信 - 第二个实例置于 modbus 服务器模式并用于
/dev/yyyy
通信 - 设置
/dev/xxxx
和/dev/yyyy
都充当串行设备,本质上是同一根电线的两端。
从我读到的内容来看pty 联机帮助页,我相信/dev/xxxx
和/dev/yyyy
是伪终端的两端。这让我想到了我的问题:
- 手册页引用了 BSD 风格的伪终端,这似乎更适合我想要做的事情。
- 我对 BSD 风格的伪终端的理解正确吗?
- 如果是这样,是否可以在非 BSD Linux 发行版上创建 BSD 风格的伪终端?具体来说,我使用的是 debian 10、11、12(以及基于 debian 的版本,例如 Ubuntu 20.04、22.04)
- 该手册页还引用了 UNIX 98 伪终端,它们是使用
posix_openpt()
.然而,即使在后续的grantpt()
and之后,我也只能为 pty 的客户端提供unlockpt()
一个设备,而主端只是可执行文件内的一个文件描述符。/dev/pts
- 我的理解是(松散地基于像这样的代码) 正确的?
- 如果是这样,我可以使用什么技巧将主端文件描述符转换为正确的,
/dev/xxxx
这是唯一可用的 API获取 modbus 上下文
- 是否还有其他“标准”Linux 工具可以完成我想要做的事情?看起来像这样的工具这里提到的那些期望将可执行文件的 STDIO 连接到 pty。
答案1
您可以使用以下命令设置 PTY“虚拟串行端口”socat
。
socat \
pty,rawer,echo=0,link=/tmp/portA \
pty,rawer,echo=0,link=/tmp/portB
这将创建两个 PTY 设备和两个到这些设备的符号链接。在我的系统上,上面的命令创建了:
$ ls -l /tmp/port*
lrwxrwxrwx 1 lars lars 11 Jul 24 11:49 /tmp/portA -> /dev/pts/20
lrwxrwxrwx 1 lars lars 11 Jul 24 11:49 /tmp/portB -> /dev/pts/21
您可以将这些 pty 设备视为串行端口。例如,我可以连接slcand
到这些设备来创建 CANbus 接口:
slcand -o -c -f -s6 $(readlink /tmp/portA)
slcand -o -c -f -s6 $(readlink /tmp/portB)
或者我可以连接picocom
到每个端口并通过虚拟链接聊天。在一个窗口中:
picocom $(readlink /tmp/portA)
在另一个窗口中:
picocom $(readlink /tmp/portB)
ETC。
UNIX-98 pty 和 BSD 样式 pty 的行为相同;区别在于它们的分配方式(UNIX-98 pty 是动态分配的,而 BSD 样式 pty 是预分配设备)。
然而,即使在随后的 grantpt() 和 unlockpt() 之后,我只能为 pty 的客户端提供一个 /dev/pts 设备,而主端只是可执行文件内的一个文件描述符。
这是正确的;要链接两个 pty 以创建虚拟串行线,您的代码需要打开两个 pty 设备,然后处理两者之间的数据移动(这就是socat
上面示例中所做的操作)。