问题:
我有两台通过串行接口连接的 Linux 机器。我使用 ppp 在它们之间进行通信(我必须这样做,因为这是项目要求)。通信速度为9600位/秒。我需要实时测量使用的带宽(位/秒),即系统运行时的带宽。最初我想我会使用ifstat -btwTWS -i ppp0
,因为这就是这些工具的设计目的。然而,显示的值远远超过 9600 位/秒。它徘徊在 12.09 Kbits/s 左右。我确实问过为什么会发生这种情况,回应是这可能是由于压缩造成的。这确实有道理。然而,我需要的是压缩后和解压缩发生之前的实际位/秒。
我最初解决这个问题的方法是:
最初我想使用某种能够显示数据速率的串行流量嗅探器。我已经尝试了几种,但每当我尝试连接时,/dev/ttyUSB0
都会收到资源繁忙错误。发生这种情况是因为 PPP 正在接管该设备。
我解决这个问题的第二种方法:
我想创建一个伪串口,将其连接到真实的串口。然后PPP将接管伪串行端口,我将嗅探真实串行端口上的流量。这是图表:
-------------------- -------------------------
| | | |
| PPP | | sniffer |
| ------------- | | ------------------ |
| | /dev/pty0 |---|---------|---| /dev/ttyUSB0 | |
| ------------- | | ------------------ |
| | | |
-------------------- -------------------------
我的理解是socat
可以做到这一点。我一直在阅读此内容,但找不到任何允许我这样做的选项。
所以这是我的问题:
如何使用 socat 创建伪终端并连接到真实的串行端口?这可能吗?
答案1
您应该能够socat
在简单的命令中使用,例如
socat pty,link=$HOME/myserial,rawer /dev/ttyUSB0,rawer 2>&1
~/myserial
这将创建到pty 的符号链接,并且 pty 的任何 i/o 都会复制到串行端口或从串行端口复制。更进一步,您可以添加选项-v
以将 i/o 复制到 stderr,并将-x
其以十六进制打印,并带有以下形式的标题行:
< 2019/01/12 18:16:36.528942 length=12 from=310 to=321
其中第一个字符是方向<
或>
,长度是复制的字节数。使用十六进制可确保标题行不会与原始数据混淆。这是一个可能的 awk 脚本来解析它。大约每 10 秒它就会在一个方向上写出当前每秒的字节数。
socat -v -x pty,link=$HOME/myserial,rawer /dev/ttyUSB0,rawer 2>&1 |
awk '
/^[><]/{ split($3,x,":"); tod = (x[1]*60+x[2])*60+x[3];
split($4,x,"="); len = x[2]+0;
dir = $1=="<" ? "rx" : "tx";
if(tod-lasttod[dir]>=10){
printf "%s %f\n",dir,(len+tot[dir])/(tod-lasttod[dir])
lasttod[dir] = tod
tot[dir] = 0
}else tot[dir] += len
}'
为了简单起见,每个方向都是单独处理的,并且您需要将时间固定在午夜。典型的输出可能是
tx 2.398754
rx 0.000425
tx 2.398772
rx 61.768501