串口文件描述符调用close()出现30秒延迟,如何配置取消该关闭延迟?
问题根因
Linux 系统下串口文件描述符默认关闭时,会等待内核发送缓冲区的所有数据全部完成硬件传输才会返回。如果串口链路异常(如硬件断连、对端流控未放开导致数据无法发送),发送队列数据长期无法排空,close 调用就会阻塞,最长可达30秒,这是串口驱动的默认行为。
解决方法
- 首先修正现有关闭代码的语法错误
你当前代码中的tcflush调用缺少参数分隔符,未正常生效,正确写法如下:
tcflush(com_port->port_handle_, TCIOFLUSH);
TCIOFLUSH 会直接丢弃串口收发两端的所有内核缓冲区数据,无需等待未发送的数据传输完成,修复后大部分场景下 close 就不会再阻塞。
- 临时配置文件描述符为非阻塞模式
如果修复后仍有阻塞,可以在调用close前临时将文件描述符设为非阻塞模式,非阻塞模式下的close不会等待缓冲区排空,会直接返回:
int CloseSerialPort(SerComPort* com_port) { if(com_port->port_handle_ > 0) { // 临时设置非阻塞 int flags = fcntl(com_port->port_handle_, F_GETFL, 0); fcntl(com_port->port_handle_, F_SETFL, flags | O_NONBLOCK); // 清空缓冲区 tcflush(com_port->port_handle_, TCIOFLUSH); } return close(com_port->port_handle_); }
如果你的业务不影响正常收发逻辑,也可以在 open 串口时直接加上 O_NONBLOCK 标志:fd = open(addr, O_RDWR | O_NONBLOCK);
注意这种情况下正常读写串口时需要处理 EAGAIN 错误码。
内容的提问来源于stack exchange,提问作者FooAnon
相关产品推荐
相关产品推荐

