Linux/C/C++:串口/USB读写为何选择阻塞或非阻塞模式?
串口读写模式选择建议
单线程场景:优先用规范模式的阻塞read()
如果你的程序必须拿到完整的带终止符的文本串才能继续执行,直接用规范模式的阻塞read()是最优选择:
- 内核会自动缓存数据,直到检测到终止符(比如
\n)才返回完整的串,不用自己写循环拼接数据、判断终止符,代码更简洁可靠。 - 自己用非阻塞模式加
usleep()循环的方式有明显缺点:usleep的时长很难精准设置——设短了会频繁唤醒线程,白白占用CPU;设长了会拖慢响应速度,还要自己处理数据分多次到达的情况,容易出现漏接、拼接错误的bug。
多线程场景:收数据线程用阻塞模式更高效
如果是专门负责收数据的线程,阻塞模式依然是更好的选择:
- 线程会阻塞在
read()调用上,没有数据时不会占用CPU资源,有数据到达时内核会自动唤醒线程处理,资源利用率更高。 - 非阻塞加
usleep()循环的方式会让线程周期性空转,浪费CPU,除非你需要在等待间隙处理其他逻辑,但如果只是单纯等待完整串,完全没必要这么做。
非阻塞模式的适用场景
非阻塞模式(配合select()/poll()等I/O多路复用,而非单纯的usleep()循环)确实有它的用武之地:
- 分块处理数据流:不需要等完整串,拿到部分数据就可以提前处理(比如实时监控数据流中的特定关键字)。
- 单线程多任务:程序需要在等待串口数据的同时处理其他任务(比如UI交互、其他设备读写),这时候不能一直阻塞在
read()上,用非阻塞模式加I/O多路复用,可以同时监听多个文件描述符,在空闲时处理其他逻辑,比usleep()循环高效得多。 - 灵活的超时控制:如果需要设置等待数据的超时时间,用非阻塞模式配合
select()(带超时参数)比阻塞read()加信号(比如alarm())的实现方式更灵活、更易维护。
内容的提问来源于stack exchange,提问作者AxAn
相关产品推荐
相关产品推荐

