You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux非规范模式串口通信如何忽略收到的POLLHUP事件?

Linux串口非规范模式随机POLLHUP问题解决方法

问题根因

  • 未开启CLOCAL标志:termios默认会检测调制解调器载波信号(DCD),直连UART设备时无稳定载波信号,会随机触发挂断检测
  • 禁用了IGNBRK:收到串口BREAK条件(对端发送超过1字节长度的低电平)时,内核默认触发挂断事件上报
  • open返回值判断错误:原代码判断fd == 0作为打开失败条件,而0是标准输入的合法fd,会导致意外初始化失败
  • 错误的错误检测逻辑:串口不是套接字设备,调用getsockopt读取SO_ERROR返回的结果无意义

修复方案

1. 修正初始化配置

修改setup()方法中的termios配置:

bool UartSocket::setup()
{
    int fd = ::open("/dev/serial0", O_RDWR | O_NOCTTY | O_NONBLOCK);
    // 修正open返回值判断:open失败返回-1,不是0
    if (fd < 0)
    {
        return false;
    }

    struct termios portSettings;
    ::memset(&portSettings, 0, sizeof(portSettings));
    if (m_rSyscalls.tcgetattr(fd, &portSettings) != 0)
    {
        m_logger.error("tcgetattr() failed, errno = %d.", errno);
        return false;
    }
    m_rSyscalls.cfsetispeed(&portSettings, 115200);
    m_rSyscalls.cfsetospeed(&portSettings, 115200);
    cfmakeraw(&portSettings);

    // 核心修改1:忽略BREAK条件,避免触发挂断事件
    portSettings.c_iflag |= IGNBRK;
    // 核心修改2:忽略载波检测,启用接收器,关闭挂断自动复位
    portSettings.c_cflag |= CLOCAL | CREAD;
    portSettings.c_cflag &= ~HUPCL;
    // 非规范模式参数配置:至少1字节返回,无超时
    portSettings.c_cc[VMIN] = 1;
    portSettings.c_cc[VTIME] = 0;

    if (m_rSyscalls.tcsetattr(fd, TCSANOW, &portSettings) != 0)
    {
        m_logger.error("tcsetattr() failed, errno = %d.", errno);
        return false;
    }

    m_pollfd.fd = fd;
    m_pollfd.events = POLLIN;

    return true;
}

2. 优化POLLHUP处理逻辑

串口的POLLHUP仅表示输入侧的临时挂断事件,不会导致fd失效,无需重新打开设备,修改recv()中的处理逻辑:

// 缓冲区清空后再处理挂起事件
if ((m_pollfd.revents & POLLHUP) && (readResult == 0))
{
    m_logger.warn("Hangup event on uart %s, ignored.", m_rConfig.getPath().c_str());
    // 清除事件标记即可,无需reopen
    m_pollfd.revents &= ~POLLHUP;
}

验证说明

修改后内核会自动忽略BREAK条件和载波电平变化,不会再随机触发POLLHUP事件,即便出现偶发事件也无需重启设备,所有原始字节都会正常上报到应用层,不会被内核解析为控制字符。


内容的提问来源于stack exchange,提问作者Fadeway

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 17:57:05