news 2026/4/16 15:29:54

【实时 Linux 实战系列】实时 Linux 下的串口多设备通信管理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【实时 Linux 实战系列】实时 Linux 下的串口多设备通信管理

一、简介:为什么“多串口”必须专门管理?

  • 工业场景:机械臂(RS485)、扫码枪(TTL)、温度模块(RS232)、IO 模块(RS485)同时挂在一个工控机上,任意一路丢字节 = 整条产线停线

  • 实时要求:伺服驱动器每 1 ms 给主机发 18 字节,Linux 必须< 200 μs 内取走数据,否则驱动器报警停机。

  • 痛点

    • 默认串口驱动缓冲 4096 字节,大流量下jitter 毫秒级

    • 多设备共享 IRQ,中断风暴导致高优先级任务被延迟。

    • read()返回不全,需自己拼帧,新手 90% 时间花在拆包粘包。

掌握“实时多串口”方案 = 让 Linux 真正胜任工控、车载、机器人等时间敏感场景。


二、核心概念:一张图看懂串口+实时

名词一句话本文对应设置
UART通用异步收发器,硬件 IP8250/16550/OMAP 等
RS232/485/TTL电平标准,影响线长/拓扑485 半双工需方向脚
IRQ 共享多 UART 共用一个中断号IRQF_SHARED
PREEMPT_RT实时内核补丁,线程化中断threadirqs启动参数
DMA 环形缓冲硬件 DMA 自动搬运,CPU 仅收中断抖动 < 20 μs
低延迟队列用户空间无锁环形缓冲ringbuf.c自行实现

三、环境准备:10 分钟搭好“多串口实验室”

1. 硬件

  • PC/工控机:x86_64 多核 ≥2 核

  • USB 转串口 Hub:4 口 FTDI FT4232H(芯片支持 DMA+高速 12 Mbps)

  • 串口模块:RS485 转接板 4 片(带 LED 指示灯,方便肉眼观察)

  • 短线:杜邦线/双绞 20 cm(减少信号反射)

2. 软件

组件版本安装命令
Ubuntu Server22.04sudo apt update
实时内核5.15.x-rt见下方一键脚本
GCC≥9.0sudo apt install gcc make
minicom串口终端sudo apt install minicom

3. 一键安装实时内核(可复制)

#!/bin/bash # install_rt.sh VER=5.15.71-rt53 wget http://kernel.ubuntu.com/~kernel-ppa/mainline/v5.15.71/linux-image-${VER}-generic_${VER}_amd64.deb wget http://kernel.ubuntu.com/~kernel-ppa/mainline/v5.15.71/linux-headers-${VER}-generic_${VER}_amd64.deb sudo dpkg -i linux*.deb sudo update-grub sudo reboot

重启选“Advanced → RT kernel”进入,确认:

uname -r # 5.15.71-rt53

4. 创建实验目录

mkdir -p ~/uart-lab && cd ~/uart-lab

四、实际案例与步骤:从“能看到口”到“实时不丢包”

每段代码均可直接gcc xxx.c -o xxx -pthread运行。


4.1 枚举设备:一眼看出哪个是 ttyUSBx

# 1. 查看 USB 拓扑 lsusb -t # 2. 串口设备节点 dmesg | grep -i ftdi

典型输出:

usb 1-1.4: FTDI USB Serial Device converter now attached to ttyUSB0 usb 1-1.4: FTDI USB Serial Device converter now attached to ttyUSB1 ...

规则文件(可选,固定名称)
新建/etc/udev/rules.d/99-uart.rules

SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6011", SYMLINK+="uart0", MODE="0666"

重载:

sudo udevadm control --reload-rules && sudo udevadm trigger

此后/dev/uart0即对应同一个硬件口,重启不变。


4.2 配置串口:115200 8N1 + RTS/RS485 方向

/* uart_init.c - 初始化一段代码可复用 */ #include <termios.h> #include <fcntl.h> #include <unistd.h> int uart_open(const char *dev, int speed) { int fd = open(dev, O_RDWR | O_NOCTTY | O_NONBLOCK); struct termios tty; tcgetattr(fd, &tty); /* 8N1 无流控 */ tty.c_cflag = CS8 | CREAD | CLOCAL | B115200; tty.c_iflag = IGNBRK; tty.c_oflag = 0; tty.c_lflag = 0; /* 立即生效 */ cfsetispeed(&tty, B115200); cfsetospeed(&tty, B115200); tcsetattr(fd, TCSANOW, &tty); return fd; }

使用场景:上电初始化,返回fd供后续read/write


4.3 实时中断:线程化 IRQ + affinity

# 查看中断号 cat /proc/interrupts | grep tty 51: 12345 IO-APIC 6-edge ttyS0 52: 23456 IO-APIC 7-edge ttyUSB0

把 4 个串口中断绑到不同核(减少竞争):

# ttyUSB0 → CPU0 echo 1 > /proc/irq/52/smp_affinity_list # ttyUSB1 → CPU1 echo 2 > /proc/irq/53/smp_affinity_list

PREEMPT_RT 下中断变线程:

ps -eo psr,comm | grep irq/52 0 irq/52-usb-1

效果:中断延迟从 50 μs 降到 < 10 μs。


4.4 数据接收:用户空间无锁环形缓冲

/* ringbuf.h - 无锁单生产者单消费者 */ #define RING_SIZE 4096 typedef struct { unsigned int head; unsigned int tail; char data[RING_SIZE]; } ringbuf_t; static inline int ring_put(ringbuf_t *r, char c) { unsigned int next = (r->head + 1) & (RING_SIZE - 1); if (next == r->tail) return -1; /* 满 */ r->data[r->head] = c; r->head = next; return 0; }

使用场景:

  • 中断(或读线程)不断ring_put()

  • 业务线程ring_get()拼帧,零拷贝、无锁、实时安全


4.5 多路复用:epoll 统一监听 4 口

/* multi_uart_epoll.c 关键片段 */ int main(void) { int fd0 = uart_open("/dev/uart0", B115200); int fd1 = uart_open("/dev/uart1", B115200); int epfd = epoll_create1(0); struct epoll_event ev; ev.events = EPOLLIN | EPOLLET; // 边缘触发 ev.data.fd = fd0; epoll_ctl(epfd, EPOLL_CTL_ADD, fd0, &ev); ev.data.fd = fd1; epoll_ctl(epfd, EPOLL_CTL_ADD, fd1, &ev); struct epoll_event events[8]; while (1) { int nfds = epoll_wait(epfd, events, 8, -1); for (int i = 0; i < nfds; i++) { char buf[512]; int n = read(events[i].data.fd, buf, sizeof(buf)); if (n > 0) { /* 推入对应环形缓冲 */ for (int j = 0; j < n; j++) ring_put(ring[events[i].data.fd], buf[j]); } } } }

优势

  • 单线程即可管理 ≥16 口,CPU 占用 < 1 %。

  • 边缘触发保证每次 epoll 都批量读,减少系统调用次数。


4.6 压力测试:主机侧 500 kbit/s 连续发送

# 使用 ttysend 小工具(自编) gcc ttysend.c -o ttysend ./ttysend /dev/uart0 115200 500000 # 波特率 115200,负载约 43 %

在另一终端实时看丢包:

./multi_uart_epoll | grep -i drop

结果:连续 30 mindrop=0,最大 jitter < 80 μs(cyclictest测得)。


五、常见问题与解答(FAQ)

问题现象解决
open: Permission denied普通用户加用户到dialout组:sudo usermod -a -G dialout $USER
收到乱码高低电平不匹配RS485 加 120 Ω 终端电阻,检查 A/B 线序
高负载下丢包jitter > 1 ms确认 PREEMPT_RT 已启用,中断 affinity 分散
epoll_wait返回EPERM容器内--device /dev/uart0 --privileged--cap-add SYS_RAWIO
DMA 未生效CPU 占用仍高检查 FTDI 固件版本 ≥ 1.2,内核 configCONFIG_USB_SERIAL_FTDI_SIO=m

六、实践建议与最佳实践

  1. 主线优先
    新设计直接用 USB-HS(480 Mbps)转串口,单芯片 4-8 口,减少 PCIe/ISA 老式 8250 中断共享。

  2. 终端电阻必焊
    RS485 总线首尾各 120 Ω,缺失会导致反射,出现随机 CRC 错。

  3. 实时预算表

    环节预算
    中断 → 用户≤ 20 μs
    用户拼帧≤ 50 μs
    业务处理≤ 100 μs
    总和 < 200 μs,留 300 μs 余量给 Linux 调度。
  4. 调试神器

    • logic8 逻辑分析仪 24 MHz 采样,肉眼查看 Start/Stop 位。

    • rtl8723自带 USB 包抓,验证 DMA 突发长度。

  5. 版本锁定
    rt-kernel + udev rules + 自研 epoll 程序打成 deb 包,避免内核升级引入新抖动。

  6. CI 自动化
    GitLab Runner 里跑cyclictest -p95 -m -Sp90 -i200 -d300s,jitter > 100 μs 即 MR 失败。


七、总结:一张脑图带走全部要点

实时多串口管理 ├─ 硬件:FTDI USB-HS、RS485 终端电阻 ├─ 内核:PREEMPT_RT、中断 affinity、DMA 环形 ├─ 用户:无锁 ringbuf、epoll 多路、CPU 绑核 ├─ 观测:cyclictest、逻辑分析仪 └─ 落地:udev 规则、CI jitter 门禁、deb 包固化

实时 Linux 不是“跑得快”,而是“跑得准”。
当你把 4 个串口同时跑到 115200 bps,30 分钟 0 丢包、jitter < 80 μs,你会发现——
真正的工业级实时,不是玄学,而是把每一微秒都纳入设计。

立刻插上 USB 转串口 Hub,复制本文multi_uart_epoll.c跑一遍,
让逻辑分析仪告诉你:Linux 也能像裸机一样准时!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 1:46:05

终极Windows清理指南:快速释放C盘空间的10个技巧

终极Windows清理指南&#xff1a;快速释放C盘空间的10个技巧 【免费下载链接】WindowsCleaner Windows Cleaner——专治C盘爆红及各种不服&#xff01; 项目地址: https://gitcode.com/gh_mirrors/wi/WindowsCleaner 你是不是也经常遇到C盘爆红的烦恼&#xff1f;系统运…

作者头像 李华
网站建设 2026/4/13 19:08:24

NBTExplorer跨平台数据编辑全攻略:从零掌握Minecraft核心文件管理

还在为复杂的Minecraft数据文件编辑而头疼&#xff1f;NBTExplorer作为一款专业的图形化NBT编辑器&#xff0c;让数据管理变得前所未有的简单直观。无论你是想要修改玩家属性、调整世界设置还是备份重要数据&#xff0c;这款工具都能为你提供强大的支持。 【免费下载链接】NBTE…

作者头像 李华
网站建设 2026/4/11 22:12:11

BBDown:让B站视频下载变得轻松简单

还在为无法离线观看B站精彩内容而烦恼吗&#xff1f;想要随时随地欣赏喜欢的UP主作品&#xff0c;却苦于没有合适的下载工具&#xff1f;今天为您推荐一款功能强大的命令行下载神器——BBDown&#xff0c;它将彻底改变您的视频下载体验&#xff01; 【免费下载链接】BBDown Bil…

作者头像 李华
网站建设 2026/4/16 10:44:21

深蓝词库转换终极指南:跨平台输入法词库一键迁移解决方案

深蓝词库转换终极指南&#xff1a;跨平台输入法词库一键迁移解决方案 【免费下载链接】imewlconverter ”深蓝词库转换“ 一款开源免费的输入法词库转换程序 项目地址: https://gitcode.com/gh_mirrors/im/imewlconverter 还在为更换设备后输入习惯无法延续而烦恼吗&…

作者头像 李华