Linux实现虚拟串口通信-socat

在Linux开发中,我们常需要调试串口通信程序,但有时缺少真实的串口硬件(如USB转串口模块、单片机)。此时,通过软件模拟虚拟串口是高效的解决方案------借助Linux自带的伪终端(Pseudoterminal,

PTY)机制,可创建一对"相互连接"的虚拟串口,让两个程序像操作真实串口一样进行数据交互。本文将详细讲解如何用 socat

工具快速创建虚拟串口,并通过实际示例验证两个程序的通信效果。

一、核心原理:虚拟串口的本质是"伪终端对"

Linux中的虚拟串口并非真实的硬件接口,而是基于"伪终端对"实现的逻辑通道。一个伪终端对包含两个端点:主设备(master)从设备(slave),数据会在两个端点间双向同步传输------从主设备发送的数据会被从设备接收,反之亦然。

我们将这两个端点模拟为"串口设备文件"(如 /dev/ttyS0、/dev/ttyS1),让两个程序分别绑定这两个设备文件,即可实现"程序A→虚拟串口→程序B"的通信链路,完全模拟真实串口的交互逻辑。

二、准备工具:安装socat

socat 是Linux下功能强大的"数据转发工具",支持多种协议和设备的连接,其中就包括伪终端对的创建,是模拟虚拟串口的首选工具。

安装命令:

  1. Debian/Ubuntu :
    sudo apt update && sudo apt install socat -y

  2. CentOS/Fedora :
    sudo dnf install socat -y

  3. 验证安装:
    socat -V

    若输出版本信息(如 socat 1.7.4.4),说明安装成功。

三、步骤1:创建虚拟串口对

通过 socat 命令可直接创建一对相互绑定的虚拟串口,命令格式如下:

bash 复制代码
socat -d -d pty,raw,echo=0,link=/dev/ttyV0 pty,raw,echo=0,link=/dev/ttyV1

命令参数解释:

  • -d -d:输出调试信息(两次 -d 表示详细程度,可省略,便于排查问题);

  • pty:指定创建伪终端设备;

  • raw:设置串口为"原始模式",禁用缓冲区和特殊字符处理(模拟真实串口的无缓冲传输);

  • echo=0:关闭回显功能(避免发送的数据被自身回显,干扰通信);

  • link=/dev/ttyV0:为伪终端设备创建软链接(简化设备名,原伪终端名较长,如 /dev/pts/10),ttyV0ttyV1是自定义的虚拟串口名,可修改(建议用 ttyV 前缀,避免与真实串口 ttyS 冲突)。

执行命令后,终端会输出类似以下的调试信息,说明虚拟串口对创建成功:

text 复制代码
2026/01/14 15:30:00 socat[12345] N PTY is /dev/pts/10
2026/01/14 15:30:00 socat[12345] N PTY is /dev/pts/11
2026/01/14 15:30:00 socat[12345] N starting data transfer loop with FDs [5,5] and [7,7]

此时,/dev/ttyV0 和 /dev/ttyV1 就是一对相互通信的虚拟串口,且软链接已自动创建(可通过 ls -l /dev/ttyV* 查看链接关系)。

⚠️ 注意:创建虚拟串口的终端窗口需保持打开状态(socat 进程运行中),若关闭窗口,虚拟串口会自动消失。

四、步骤2:验证虚拟串口通信(基础测试)

我们先用两个终端窗口模拟"两个程序",通过 catecho 命令测试虚拟串口的双向通信功能。

测试1:单向通信(终端1→终端2)

  1. 打开 终端1 (接收端):绑定 /dev/ttyV0,监听数据:
    cat /dev/ttyV0

  2. 打开 终端2 (发送端):绑定 /dev/ttyV1,发送数据:
    echo "Hello, Virtual Serial Port!" > /dev/ttyV1

  3. 观察结果:终端1会立即显示终端2发送的字符串,说明单向通信正常。

测试2:双向通信(终端1与终端2互发)

  1. 终端1(绑定 /dev/ttyV0):用 read 命令接收数据,同时可发送数据:
    while read -r line; do echo "终端1收到:$line"; done < /dev/ttyV0

  2. 终端2(绑定 /dev/ttyV1):同样用循环接收并发送数据:
    while read -r line; do echo "终端2收到:$line"; done < /dev/ttyV1

  3. 测试互发:

  • 在终端1输入 echo "Hi from V0" > /dev/ttyV0,终端2会显示"终端2收到:Hi from V0";
  • 在终端2输入 echo "Hi from V1" > /dev/ttyV1,终端1会显示"终端1收到:Hi from V1"。

五、步骤3:两个程序通过虚拟串口通信(实战示例)

下面用 Python 编写两个简单的串口程序(发送端+接收端),模拟真实应用场景下的程序间通信。

前提:安装Python串口库

两个程序需用到 pyserial 库,安装命令:
pip install pyserial

程序1:虚拟串口发送端(send.py,绑定 /dev/ttyV1)

python 复制代码
import serial
import time

# 配置虚拟串口参数(波特率、超时时间等,需与接收端一致)
ser = serial.Serial(
    port='/dev/ttyV1',    # 绑定虚拟串口V1
    baudrate=9600,        # 波特率(虚拟串口可任意设置,真实串口需匹配)
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS,
    timeout=1             # 读取超时时间(秒)
)

# 循环发送数据
try:
    print("发送端启动,开始发送数据...")
    count = 0
    while True:
        data = f"Test data {count}: Hello Virtual Serial!\n"
        ser.write(data.encode('utf-8'))  # 编码为字节流发送
        print(f"已发送:{data.strip()}")
        count += 1
        time.sleep(2)  # 每2秒发送一次
except KeyboardInterrupt:
    print("\n发送端退出")
    ser.close()  # 关闭串口

程序2:虚拟串口接收端(recv.py,绑定 /dev/ttyV0)

python 复制代码
import serial

# 配置虚拟串口参数(与发送端完全一致)
ser = serial.Serial(
    port='/dev/ttyV0',
    baudrate=9600,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS,
    timeout=1
)

# 循环接收数据
try:
    print("接收端启动,等待数据...")
    while True:
        if ser.in_waiting > 0:  # 检测是否有数据可读
            data = ser.readline().decode('utf-8').strip()  # 读取一行数据并解码
            print(f"接收端收到:{data}")
except KeyboardInterrupt:
    print("\n接收端退出")
    ser.close()

运行程序并验证

  1. 确保之前创建虚拟串口的终端窗口仍打开(socat 进程运行中);

  2. 打开 终端3 ,运行接收端程序:
    python recv.py

  3. 打开 终端4 ,运行发送端程序:
    python send.py

  4. 观察结果:接收端会每隔2秒收到发送端发送的测试数据,类似以下输出:

    接收端启动,等待数据...

    接收端收到:Test data 0: Hello Virtual Serial!

    接收端收到:Test data 1: Hello Virtual Serial!

    接收端收到:Test data 2: Hello Virtual Serial!

六、常见问题与注意事项

1. 权限问题:Permission denied

现象:运行程序或访问 /dev/ttyV0 时提示"权限拒绝"。

解决:将当前用户加入 dialout 用户组(Linux串口设备默认属于该组),命令:
sudo usermod -aG dialout $USER

执行后注销当前用户并重新登录,权限即可生效。

2. 虚拟串口消失

原因:创建虚拟串口的 socat 进程被终止(如关闭终端窗口)。

解决:重新执行 socat 创建命令,确保该终端窗口持续打开。

3. 程序通信失败

排查方向:

  • 两个程序的串口参数(波特率、数据位、停止位、校验位)是否完全一致;
  • 程序绑定的虚拟串口是否正确(需分别绑定 ttyV0 和 ttyV1,不可重复);
  • 虚拟串口是否正常创建(用 ls -l /dev/ttyV* 检查软链接)。

4. 自定义虚拟串口名

若不想用 ttyV0/ttyV1,可修改 socat 命令中的 link 参数,如 link=/dev/ttyS10link=/dev/mySerial0,但需避免与系统真实串口名冲突(真实串口通常为 ttyS0-ttyS3)。

相关推荐
蓝队云计算10 分钟前
蓝队云部署OpenClaw深度指南:避坑、优化与安全配置,从能用做到好用
运维·安全·云计算
Kaede610 分钟前
提示dns服务器未响应,需要做哪些事?
运维·服务器
CRUD酱13 分钟前
CentOS的yum仓库失效问题解决(换镜像源)
linux·运维·服务器·centos
We....32 分钟前
鸿蒙与Java跨平台Socket通信实战
java·服务器·tcp/ip·arkts·鸿蒙
zly350035 分钟前
VMware vCenter Converter Standalone 转换Linux系统,出现两个磁盘的处理
linux·运维·服务器
珠海西格43 分钟前
1MW光伏项目“四可”装置改造:逆变器兼容性评估方法详解
大数据·运维·服务器·云计算·能源
Albert Edison1 小时前
【Python】函数
java·linux·python·pip
General_G1 小时前
Linux中的信号
linux·运维·服务器
诸神缄默不语1 小时前
当无法直接用apt instll时,Linux如何离线安装软件包(以make为例)
linux·运维·服务器
Sivan_Xin2 小时前
拒绝 If-Else 屎山:利用适配器模式(Adapter)构建第三方登录的“防腐层”实战
linux·python·适配器模式