c++如何读取串口或管道设备文件_Linux设备节点IO【详解】

酷墨小哥_8247

酷墨小哥_8247

2026-03-25

791人浏览

原创

串口操作权限、读写阻塞、参数匹配及关闭清理四大问题需分别处理:加dialout组获权限;用O_NONBLOCK或VMIN/VTIME设读超时;显式配置termios波特率/数据位/校验位;close前调tcdrain和tcflush。

c++如何读取串口或管道设备文件_linux设备节点io【详解】

open() 串口设备节点失败:Permission denied 怎么办

Linux 下直接 open("/dev/ttyUSB0", O_RDWR) 报 Permission denied,大概率不是代码问题,而是权限没给。普通用户默认无权访问串口设备节点,系统不会自动放行。

实操建议:

  • 临时解决:用 sudo chmod 666 /dev/ttyUSB0(不推荐长期用)
  • 更稳妥:把当前用户加进 dialout 组,执行 sudo usermod -a -G dialout $USER,然后**完全退出并重登会话**(仅重启终端不够)
  • 验证是否生效:运行 groups 看输出里有没有 dialout;再试 open() 是否成功

注意:设备插拔后节点名可能变(如 /dev/ttyUSB1),别硬编码路径;udev 规则可固定名称,但那是另一层需求。

read() 返回 0 或阻塞:串口没设对非阻塞和超时

C++ 用 read() 从串口读数据,常遇到两种情况:要么卡住不动(默认阻塞),要么立刻返回 0(误判为 EOF)。根本原因是没配好文件描述符行为和串口属性。

实操建议:

  • 设非阻塞:fcntl(fd, F_SETFL, O_NONBLOCK),这样 read() 立即返回,没数据时 errno 是 EAGAIN 或 EWOULDBLOCK
  • 设超时更可控:用 termios 配置 c_cc[VMIN] 和 c_cc[VTIME] —— 比如 VMIN = 0, VTIME = 10 表示最多等 1 秒,有数据就立刻返,没数据也 1 秒后返回
  • 别漏掉 cfmakeraw():它清掉回显、信号、流控等干扰项,是串口通信的起点配置

常见错误:只改了 O_NONBLOCK 却没调 tcsetattr(),结果还是受默认 termios 影响,读写行为不可控。

write() 发不出数据或乱码:波特率/数据位/校验位不匹配

发出去的数据对方收不到,或收到一堆乱码,90% 是串口参数没对齐。C++ 本身不处理这些,全靠 termios 结构体设置,错一个字段就全崩。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载

实操建议:

  • 必须显式设置:用 cfsetispeed() 和 cfsetospeed() 设波特率(如 B115200),别依赖默认值
  • 关闭校验:设 ~PARENB;8 数据位:设 CS8;1 停止位:~CSTOPB —— 这是最常用组合,但得按硬件文档确认
  • 禁用软硬件流控:~IXON & ~IXOFF & ~CRTSCTS,否则 0x11/0x13 可能被吞掉

性能影响:波特率越高,对 CPU 和线缆质量要求越严;低于 9600 时 VTIME 超时值要相应放大,不然容易漏字节。

close() 后串口还占着?记得 tcdrain() 和清空缓冲区

程序退出前只调 close(fd),下次启动可能发现设备“忙”,或者残留数据干扰新连接。Linux 内核不会自动等发完,也不会清接收缓存。

实操建议:

  • 关之前先等发完:tcdrain(fd),它会阻塞直到输出队列空
  • 清输入缓冲:tcflush(fd, TCIFLUSH),避免上次未读数据污染下一次
  • 如果程序异常退出(比如 SIGSEGV),这些清理不会发生 —— 所以关键逻辑最好包在 RAII 类里,或至少用 atexit() 注册清理函数

容易被忽略的一点:某些 USB 转串口芯片(如 CH340)在 close() 后需要几十毫秒才能真正释放,短时间重复 open 可能失败,加个 usleep(100000) 更稳。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

2025.06.09

5194

18

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

2025.07.04

5371

25

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.18

6607

5

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2023.08.10

2748

6

磁盘配额是什么
磁盘配额是什么

磁盘配额是计算机中指定磁盘的储存限制,就是管理员可以为用户所能使用的磁盘空间进行配额限制,每一用户只能使用最大配额范围内的磁盘空间。php中文网为大家提供各种磁盘配额相关的内容,教程,供大家免费下载安装。

2023.06.21

4410

4

如何安装LINUX
如何安装LINUX

本站专题提供如何安装LINUX的相关教程文章,还有相关的下载、课程,大家可以免费体验。

2023.06.29

3693

10

linux find
linux find

find是linux命令,它将档案系统内符合 expression 的档案列出来。可以指要档案的名称、类别、时间、大小、权限等不同资讯的组合,只有完全相符的才会被列出来。find根据下列规则判断 path 和 expression,在命令列上第一个 - ( ) , ! 之前的部分为 path,之后的是 expression。还有指DOS 命令 find,Excel 函数 find等。本站专题提供linux find相关教程文章,还有相关

2023.06.30

2973

5

linux修改文件名
linux修改文件名

本专题为大家提供linux修改文件名相关的文章,这些文章可以帮助用户快速轻松地完成文件名的修改工作,大家可以免费体验。

2023.07.05

7370

7

linux系统安装教程
linux系统安装教程

linux系统是一种可以免费使用,自由传播,多用户、多任务、多线程、多CPU的操作系统。本专题提供linux系统安装教程相关的文章,大家可以免费体验。

2023.07.06

7002

7

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习