我正在调试与串行设备的通信,我需要查看双向流动的所有数据。
在 Linux 上这似乎应该很容易,其中串口由文件表示。 有没有什么方法可以让我做一种“双向 Tee”,让我的程序连接到一个管道,将数据复制到文件中,并将其洗牌到实际的串行端口设备/从实际的串行端口设备中洗牌?
我想我什至可能知道如何编写这样一个庞然大物,但这似乎并不简单,特别是要让所有的ioctl通过端口配置等。
有人已经建造过这样的东西吗? 它似乎太有用了(对于调试串行设备驱动程序的人来说),以至于不应该存在。
strace对此非常有用。您可以可视化所有 ioctl 调用,并解码相应的结构。以下选项对于您的情况似乎特别有用:
-e 读取=设置
对读取的所有数据执行完整的十六进制和 ASCII 转储 文件描述符中列出 指定的集合。例如,要查看所有 文件描述符 3 上的输入活动 5 使用 -e read=3,5。请注意,这 独立于正常的跟踪 read(2) 系统调用的 由选项-e控制 跟踪=已读。
-e 写=设置
执行完整的十六进制和 ASCII 转储写入文件的所有数据 指定中列出的描述符 放。例如,查看所有输出 文件描述符 3 和 5 上的活动 使用-e write=3,5。请注意,这是 独立于正常的追踪 write(2) 系统调用是 由选项-e控制 跟踪=写入。
我发现 pyserial 非常有用,所以如果你喜欢 Python,那么编写这样的东西应该不会太难。
一个简单的方法是编写一个打开的应用程序 pty 的主端和被测 tty。 那么你会 将您的 tty 应用程序传递给 pty 的从属端作为“tty 设备”。
tcgetattr()
来监控 pty 属性
master 并在真实 tty 上调用 tcsetattr()
(如果属性发生更改)。
select()
两个 fd 双向复制数据并将其复制到日志。
我查看了很多串行嗅探器。所有这些都基于创建虚拟串行端口并从该端口嗅探数据的想法。但是,任何波特率/奇偶校验/流量更改都会中断连接。
所以,我写了自己的嗅探器:)。现在大多数串口只是USB转串口转换器。我的嗅探器通过 debugfs 从 USB 收集数据,解析它并输出到控制台。此外,还记录任何波特率更改、流量控制、线路事件和串行错误。该项目处于早期开发阶段,目前仅支持 FTDI。
与当前的最佳答案类似,但有更多细节。特别是,all
的
set值是有效的,您可能仍然想使用
trace=read,write
来获取命令的时间戳:
$ strace -tt -e write=all -e read=all -e trace=ioctl,read,write -o output_file.txt picocom /dev/ttyACM0 -b 9600
picocom v3.1
port is : /dev/ttyACM0
flowcontrol : none
baudrate is : 9600
parity is : none
databits are : 8
stopbits are : 1
escape is : C-a
local echo is : no
noinit is : no
noreset is : no
hangup is : no
nolock is : no
send_cmd is : sz -vv
receive_cmd is : rz -vv -E
imap is :
omap is :
emap is : crcrlf,delbs,
logfile is : none
initstring : none
exit_after is : not set
exit is : no
Type [C-a] [C-h] to see available commands
Terminal ready
OK
Terminating...
Thanks for using picocom
$ cat output_file.txt
20:05:57.183751 read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`^\2\0\0\0\0\0"..., 832) = 832
<snip>
20:05:57.187281 ioctl(3, TCGETS, {c_iflag=IGNPAR, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|, c_cflag=B9600|CS8|CREAD|HUPCL|CLOCAL, c_lflag=, ...}) = 0
20:05:57.187455 ioctl(3, TCGETS2, {c_iflag=IGNPAR, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|, c_cflag=B9600|CS8|CREAD|HUPCL|CLOCAL, c_lflag=, ...}) = 0
20:05:57.187536 ioctl(3, TIOCMGET, [TIOCM_DTR|TIOCM_RTS|TIOCM_CTS]) = 0
20:05:57.187607 ioctl(3, TCSETSF2, {c_iflag=IGNPAR, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|, c_cflag=B9600|CS8|CREAD|HUPCL|CLOCAL, c_lflag=, ...}) = 0
20:05:57.187673 ioctl(3, TCGETS2, {c_iflag=IGNPAR, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|, c_cflag=B9600|CS8|CREAD|HUPCL|CLOCAL, c_lflag=, ...}) = 0
20:05:57.187736 ioctl(3, TIOCMGET, [TIOCM_DTR|TIOCM_RTS|TIOCM_CTS]) = 0
20:05:57.187797 ioctl(3, TCGETS2, {c_iflag=IGNPAR, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|, c_cflag=B9600|CS8|CREAD|HUPCL|CLOCAL, c_lflag=, ...}) = 0
20:05:57.187859 ioctl(3, TIOCMGET, [TIOCM_DTR|TIOCM_RTS|TIOCM_CTS]) = 0
20:05:57.187921 ioctl(0, TCGETS, {c_iflag=ICRNL|IUTF8, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|OPOST|ONLCR, c_cflag=B38400|CS8|CREAD, c_lflag=ISIG|ICANON|ECHO|ECHOE|ECHOK|IEXTEN|ECHOCTL|ECHOKE, ...}) = 0
20:05:57.188007 ioctl(0, TCGETS, {c_iflag=ICRNL|IUTF8, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|OPOST|ONLCR, c_cflag=B38400|CS8|CREAD, c_lflag=ISIG|ICANON|ECHO|ECHOE|ECHOK|IEXTEN|ECHOCTL|ECHOKE, ...}) = 0
20:05:57.188083 ioctl(0, TCGETS2, {c_iflag=ICRNL|IUTF8, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|OPOST|ONLCR, c_cflag=B38400|CS8|CREAD, c_lflag=ISIG|ICANON|ECHO|ECHOE|ECHOK|IEXTEN|ECHOCTL|ECHOKE, ...}) = 0
20:05:57.188146 ioctl(0, TCSETSF2, {c_iflag=IUTF8, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|ONLCR, c_cflag=B38400|CS8|CREAD, c_lflag=ECHOE|ECHOK|ECHOCTL|ECHOKE, ...}) = 0
20:05:57.188211 ioctl(0, TCGETS2, {c_iflag=IUTF8, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|ONLCR, c_cflag=B38400|CS8|CREAD, c_lflag=ECHOE|ECHOK|ECHOCTL|ECHOKE, ...}) = 0
20:05:57.188313 write(1, "Type [C-a] [C-h] to see availabl"..., 44) = 44
| 00000 54 79 70 65 20 5b 43 2d 61 5d 20 5b 43 2d 68 5d Type [C-a] [C-h] |
| 00010 20 74 6f 20 73 65 65 20 61 76 61 69 6c 61 62 6c to see availabl |
| 00020 65 20 63 6f 6d 6d 61 6e 64 73 0d 0a e commands.. |
20:05:57.188388 write(1, "Terminal ready\r\n", 16) = 16
| 00000 54 65 72 6d 69 6e 61 6c 20 72 65 61 64 79 0d 0a Terminal ready.. |
20:05:58.905359 read(0, "+", 16) = 1
| 00000 2b + |
20:05:58.905539 write(3, "+", 1) = 1
| 00000 2b + |
20:05:59.044609 read(0, "+", 16) = 1
| 00000 2b + |
20:05:59.044779 write(3, "+", 1) = 1
| 00000 2b + |
20:05:59.183396 read(0, "+", 16) = 1
| 00000 2b + |
20:05:59.183541 write(3, "+", 1) = 1
| 00000 2b + |
20:06:00.186642 read(3, "O", 128) = 1
| 00000 4f O |
20:06:00.186816 write(1, "O", 1) = 1
| 00000 4f O |
20:06:00.187552 read(3, "K", 128) = 1
| 00000 4b K |
20:06:00.187622 write(1, "K", 1) = 1
| 00000 4b K |
20:06:00.188688 read(3, "\r", 128) = 1
| 00000 0d . |
20:06:00.188752 write(1, "\r", 1) = 1
| 00000 0d . |
20:06:00.928486 read(0, "\1", 16) = 1
| 00000 01 . |
20:06:01.156588 read(0, "\30", 16) = 1
| 00000 18 . |
20:06:01.156740 write(1, "\r\n", 2) = 2
| 00000 0d 0a .. |
20:06:01.156821 write(1, "Terminating...\r\n", 16) = 16
| 00000 54 65 72 6d 69 6e 61 74 69 6e 67 2e 2e 2e 0d 0a Terminating..... |
20:06:01.156896 ioctl(3, TCFLSH, TCIOFLUSH) = 0
20:06:01.156960 ioctl(3, TCSETS2, {c_iflag=IGNPAR, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|, c_cflag=B9600|CS8|CREAD|HUPCL|CLOCAL, c_lflag=, ...}) = 0
20:06:01.157028 ioctl(3, TCGETS2, {c_iflag=IGNPAR, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|, c_cflag=B9600|CS8|CREAD|HUPCL|CLOCAL, c_lflag=, ...}) = 0
20:06:01.157093 write(1, "Thanks for using picocom\r\n", 26) = 26
| 00000 54 68 61 6e 6b 73 20 66 6f 72 20 75 73 69 6e 67 Thanks for using |
| 00010 20 70 69 63 6f 63 6f 6d 0d 0a picocom.. |
20:06:01.157164 ioctl(3, TCSBRK, 1) = 0
20:06:01.357326 ioctl(3, TCFLSH, TCIFLUSH) = 0
20:06:01.357451 ioctl(3, TCSETS2, {c_iflag=IGNPAR, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|, c_cflag=B9600|CS8|CREAD|HUPCL|CLOCAL, c_lflag=, ...}) = 0
20:06:01.358944 ioctl(0, TCSBRK, 1) = 0
20:06:01.559254 ioctl(0, TCFLSH, TCIFLUSH) = 0
20:06:01.559398 ioctl(0, TCSETS2, {c_iflag=ICRNL|IUTF8, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|OPOST|ONLCR, c_cflag=B38400|CS8|CREAD, c_lflag=ISIG|ICANON|ECHO|ECHOE|ECHOK|IEXTEN|ECHOCTL|ECHOKE, ...}) = 0
20:06:01.559772 +++ exited with 0 +++