macOS 虚拟串口通信技术笔记
一、目标
在 macOS 环境下,使用 socat 工具虚拟创建一对相互连接的串口(如 /dev/ttys001 和 /dev/ttys002),并使用 Python 验证其双向通信能力。
二、环境准备
1. 安装 socat
socat 是实现虚拟串口的核心工具,推荐使用 Homebrew 安装。
# 检查 Homebrew 是否安装
# brew --version
# 如果未安装 socat,执行安装
brew install socat
2. 安装 Python 串口库
使用 pip 或 pip3 安装 pyserial 库。
pip3 install pyserial
三、使用 socat 创建虚拟串口对
socat 通过创建两个伪终端(PTY)并自动连接它们,实现数据的双向转发。
关键命令
在一个独立的 Terminal 窗口中运行此命令,并保持其运行状态,不要关闭。
socat -d -d pty,raw,echo=0,link=/dev/ttys001 pty,raw,echo=0,link=/dev/ttys002
命令说明
| 参数/路径 | 含义 |
|---|---|
-d -d |
开启调试模式,显示 socat 创建的底层设备名。 |
pty |
创建一个伪终端设备(Pseudo Terminal)。 |
raw,echo=0 |
设置终端为原始模式(Raw Mode),并关闭回显,适合数据通信。 |
link=/dev/ttys001 |
在 /dev/ 目录下创建符号链接 ttys001 指向第一个 PTY。 |
link=/dev/ttys002 |
在 /dev/ 目录下创建符号链接 ttys002 指向第二个 PTY。 |
注意: 实际在 macOS 上,
socat可能会在/tmp/下创建链接,例如/tmp/ttyV0。您的脚本中使用了/dev/ttys001,这表示socat创建的链接已经指向了/dev下的设备。请以socat实际输出为准。您的成功案例使用了/dev/ttys001和/dev/ttys002。
四、Python 验证脚本 (serial_test.py)
使用 Python 脚本验证两个虚拟串口是否能双向通信。
脚本代码 (已验证)
from re import search
import serial
import time
# 端口配置,与 socat 创建的链接路径一致
PORT_A = '/dev/ttys001'
PORT_B = '/dev/ttys002'
BAUDRATE = 9600
TEST_DATA = b"Hello from Serial Port A!"
def setup_serial_port(port):
"""尝试打开指定端口"""
try:
# timeout=1 表示读取操作最多等待 1 秒
ser = serial.Serial(port=port, baudrate=BAUDRATE, timeout=1)
print(f"成功打开端口: {port}")
return ser
except serial.SerialException as e:
print(f"无法打开端口: {e}")
return None
def test_communication():
"""测试 A 发送,B 接收的单向通信"""
ser_a = setup_serial_port(PORT_A)
ser_b = setup_serial_port(PORT_B)
if not ser_a or not ser_b:
print("至少一个端口打开失败,请检查 socat 是否正在运行")
return
print("-" * 60)
try:
# 1. 端口A发送数据
print(f"{PORT_A} 发送数据: {TEST_DATA.decode()}")
ser_a.write(TEST_DATA)
ser_a.flush() # 确保数据立即发送
time.sleep(0.1)
# 2. 端口B接收数据
received_data = ser_b.read(len(TEST_DATA))
# 3. 验证结果
print(f"{PORT_B} 接收数据: {received_data.decode()}")
if received_data == TEST_DATA:
print("\n通信测试成功! 两个虚拟串口可以相互通信")
else:
print("\n通信测试失败, 接收到的数据不匹配")
except Exception as e:
print(f"发生错误: {e}")
finally:
# 4. 关闭端口
if ser_a and ser_a.is_open:
ser_a.close()
if ser_b and ser_b.is_open:
ser_b.close()
print("-" * 60)
print("所有端口已关闭")
if __name__ == "__main__":
test_communication()
运行和结果
python3 serial_test.py
# 您的成功结果
成功打开端口: /dev/ttys001
成功打开端口: /dev/ttys002
------------------------------------------------------------
/dev/ttys001 发送数据: Hello from Serial Port A!
/dev/ttys002 接收数据: Hello from Serial Port A!
通信测试成功! 两个虚拟串口可以相互通信
------------------------------------------------------------
所有端口已关闭
五、关键故障排除回顾
1. Python 模块问题
- 错误:
ModuleNotFoundError: No module named 'serial' - 解决: 缺少
pyserial库。运行pip install pyserial或pip3 install pyserial。
2. C#/.NET 引用问题 (针对未来 C# 开发)
- 错误:
CS1069或CS0234(找不到SerialPort或System.Text) - 解决: 确保项目引用了必要的 NuGet 包和命名空间。
dotnet add package System.IO.Ports- 在 C# 文件顶部添加
using System.IO.Ports;和using System.Text;。
3. 串口端口问题
- 问题:
无法打开端口: [Errno 16] Resource busy - 解决: 端口已被其他程序占用。确保
socat进程正在运行且没有其他程序(如 IDE 的内置工具)尝试访问这些端口。 - 问题:
无法打开端口: [Errno 2] No such file or directory - 解决: 检查 Python 脚本中的
PORT_A/B路径是否与socat命令中link=指定的路径完全一致。

浙公网安备 33010602011771号