如何隔离由socat和tee创建的与tty关联的PTY缓冲区?
解决串口TTY克隆后PTY互相阻塞的问题
问题根源
你当前的命令中,tee的两个输出分支是同步绑定的:当其中一个socat因为对应PTY未被读取、缓冲区满而阻塞时,tee无法继续向该分支写入数据,进而阻塞整个数据流,导致另一个PTY也无法接收新数据——本质是两个PTY共享了tee到socat的同一条同步管道,没有独立缓冲隔离。
解决方案
方案一:用UNIX域套接字实现完全独立的分流
这种方式通过中间套接字将串口数据分发到两个独立的socat进程,每个PTY拥有专属缓冲,互不影响:
- 启动串口到UNIX套接字的双向转发(支持多客户端,同时处理读写):
socat /dev/ttyACM0,rawer,nonblock,echo=0 UNIX-LISTEN:/tmp/serial_shared,mode=666,reuseaddr,fork,bidirectional
参数说明:
rawer:保持串口原始数据模式,避免格式转换干扰nonblock:非阻塞读取串口,防止无数据时进程挂起echo=0:关闭串口回显,避免写入数据被回读干扰fork:每个PTY连接都会创建独立子进程,实现分流隔离bidirectional:支持PTY向串口写入数据,满足你的写入需求
- 分别启动两个
socat进程创建独立PTY:
# 创建第一个独立PTY socat UNIX-CONNECT:/tmp/serial_shared PTY,rawer,link=/tmp/myPTY1,bufsize=2097152,nonblock # 创建第二个独立PTY socat UNIX-CONNECT:/tmp/serial_shared PTY,rawer,link=/tmp/myPTY2,bufsize=2097152,nonblock
参数说明:
bufsize=2097152:给每个PTY分配2MB独立缓冲,可根据数据量调整大小nonblock:PTY端非阻塞写入,即使PTY未被读取,进程也不会阻塞,数据暂存到专属缓冲
方案二:用buffer命令为每个分支添加独立缓冲
直接修改原命令,为tee的每个分支添加独立缓冲进程,避免单一分支阻塞整个数据流:
socat /dev/ttyACM0,rawer,echo=0 SYSTEM:'tee >(buffer -s 2M | socat - "PTY,rawer,link=/tmp/myPTY1") | buffer -s 2M | socat - "PTY,rawer,link=/tmp/myPTY2"'
buffer -s 2M:为每个分支分配2MB独立缓冲,当PTY未被读取时,数据暂存在缓冲中,不会阻塞tee的输出,另一个分支可正常接收数据
验证方法
打开两个终端窗口,分别执行:
cat /tmp/myPTY1 cat /tmp/myPTY2
关闭其中一个窗口的cat进程,另一个窗口仍能持续接收串口数据;重新打开关闭的cat,会读取到缓冲中的所有数据。
内容的提问来源于stack exchange,提问作者Dan Pit
相关产品推荐
相关产品推荐

