同一主机下C++应用通过串口实现互相收发消息的方法(Linux环境)
Linux同主机C++程序串口通信问题解答
结论
完全可以实现,不需要额外外接物理串口硬件,通过Linux系统自带的伪终端(PTY)能力就能模拟完整的串口通信链路,原有适配物理串口的C++代码几乎不需要修改就能直接复用。
实现原理
Linux的伪终端是成对的内核虚拟设备,分为主端和从端,写入主端的数据会原样透传到从端,写入从端的数据也会原样透传到主端,通信逻辑和物理串口的收发逻辑完全一致,完全可以用来模拟两个程序之间的串口通信链路。
可落地实现方案
方案1:依赖socat快速搭建虚拟串口对(适合快速调试)
- 首先安装socat工具, Debian/Ubuntu系直接执行
apt install socat,RHEL/CentOS系执行yum install socat - 执行命令创建虚拟串口对:
socat -d -d pty,raw,echo=0 pty,raw,echo=0 - 命令执行后会输出两个伪终端的路径,例如:
/dev/pts/3
/dev/pts/4
- 两个C++程序分别打开其中一个路径,按正常Linux串口操作流程配置参数、收发数据即可,两个程序之间就能正常通过串口逻辑互发消息。
方案2:纯C++代码实现(无第三方依赖)
不需要依赖外部工具,直接通过POSIX标准API在程序中创建伪终端对:
- 在其中一个C++程序中调用
posix_openpt()打开伪终端主端 - 依次调用
grantpt()、unlockpt()配置主端权限 - 调用
ptsname()获取伪终端从端的文件路径 - 另一个C++程序直接打开上一步得到的从端路径,按串口操作逻辑读写即可
通用串口操作代码片段
// 打开串口/伪终端的通用代码 int fd = open("/dev/pts/3", O_RDWR | O_NOCTTY | O_NDELAY); if (fd < 0) { // 自定义错误处理逻辑 } struct termios opt; tcgetattr(fd, &opt); // 配置波特率,示例为9600 cfsetispeed(&opt, B9600); cfsetospeed(&opt, B9600); // 配置数据位、停止位、校验位等参数 opt.c_cflag &= ~CSIZE; opt.c_cflag |= CS8; // 8位数据位 opt.c_cflag &= ~PARENB; // 无校验 opt.c_cflag &= ~CSTOPB; // 1位停止位 tcsetattr(fd, TCSANOW, &opt); // 收发数据直接调用read/write系统调用 char buf[1024]; int recv_len = read(fd, buf, sizeof(buf)); int send_len = write(fd, "test msg", 8);
注意事项
- 用socat创建的伪终端对会随socat进程退出而销毁,需要长期使用可以把socat命令配置为systemd守护进程托管
- 伪终端的串口参数配置仅需要两边程序保持一致即可,不会有物理串口的电平、丢包等硬件层面的问题,非常适合用来做串口应用的本地调试
- 普通用户默认拥有自己创建的伪终端的读写权限,不需要额外修改/dev路径下的文件权限
内容的提问来源于stack exchange,提问作者Dave
相关产品推荐
相关产品推荐

