Linux的TTY子系统(TTY框架)的重要结构体termios的`c_iflag`字段的BRKINT选项和IGNBRK选项的含义【详解串口的BREAK信号】

引言

要搞清楚结构体termios的c_iflag字段的BRKINT选项和IGNBRK选项的含义,首先要搞清楚BREAK信号的含义。其实当你搞清楚BREAK信号后,结构体termios的c_iflag字段的BRKINT选项和IGNBRK选项的含义你也就自然知道了。

1. 什么是 BREAK 信号?

在串口通信(UART)中,BREAK 信号 指的是 发送端保持 TXD 低电平超过一帧完整字符的时间(一帧完整字符通常为8位数据位+1位校验位+1位停止位,共10位),BREAK 信号通常用于:

  • 通信错误检测
  • 终端控制
  • 复位设备
  • 同步设备状态

示意图(不含校验位):

正常传输:
Start  | Data bits  | Stop
------|------------|------
   0  |  10101010  |  1    (1帧字符)

BREAK 信号:
Start  |    低电平持续时间      | 
------|----------------|------
   0  |    低电平       |  低电平

2. BREAK 信号的特性

  • BREAK 信号 = TX 线一直保持低电平
  • 持续时间至少要大于 1 帧字符传输的时间
  • 不会被解释为正常数据
  • 可用于特殊控制用途,如复位、唤醒、错误通知等

3. BREAK 信号的用途

① 终端控制(TTY 设备)

  • Linux TTY 设备收到 BREAK 时,可触发 SIGINT(中断信号) 终止前台进程。
  • 相关 termios 选项:
    • BRKINT(如果启用,则 BREAK 会触发 SIGINT)。
    • IGNBRK(如果启用,则忽略 BREAK 信号)。

② 设备复位

某些设备(如 Modbus 从机、某些 GPS 设备)会在收到 BREAK 后执行复位。

③ 调制解调器通信

  • 传统调制解调器(Modem)使用 BREAK 作为特殊指令,如退出数据模式、进入命令模式。

④ 通信错误检测

  • 串口通信通常有校验(如奇偶校验),但如果线路出现严重干扰,设备可能发送 BREAK 作为错误指示。

4. BREAK 信号的处理方式

单独介绍选项值IGNBRKBRKINT

不同操作系统和硬件会有不同的 BREAK 处理方式,通常可以通过 termios 结构体的 c_iflag 选项来配置。

c_iflag 选项含义
IGNBRK忽略 BREAK 信号,不传递给应用程序
BRKINT启用 BREAK,BREAK 触发 SIGINT 终止进程
PARMRK奇偶校验启用 时,将 BREAK 作为 \377\0\0 发送给用户

示例:

struct termios options;
tcgetattr(fd, &options);

// 让 BREAK 触发 SIGINT
options.c_iflag |= BRKINT;

// 设置新属性
tcsetattr(fd, TCSANOW, &options);

选项值IGNBRKBRKINT组合使用的效果

IGNBRKBRKINT处理方式
1(启用)0(禁用)直接忽略 BREAK 信号,不通知用户空间
1(启用)1(启用)直接忽略 BREAK 信号,不触发 SIGINT
0(禁用)0(禁用)BREAK 被视为 空字符 (0x00) 传递给用户
0(禁用)1(启用)BREAK 触发 SIGINT(终止进程)

5. 发送 BREAK 信号

在 Linux 上,tcsendbreak(fd, duration) 用于 主动发送 BREAK 信号。

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>

int main() {
    int fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY);
    if (fd == -1) {
        perror("open");
        return -1;
    }

    // 发送 BREAK 信号,持续时间为 0(默认 250~500ms)
    tcsendbreak(fd, 0);

    close(fd);
    return 0;
}
  • duration = 0:发送 默认长度(250~500ms)的 BREAK
  • duration > 0:发送 特定长度 的 BREAK(非 POSIX 标准,仅部分系统支持)。

6. 检测 BREAK 信号

在应用程序中,可以通过 read() 检测是否接收到 BREAK,但大多数情况下,内核会转换 BREAK 为 SIGINT,因此不需要手动读取。

如果要检测 BREAK 而不让它触发 SIGINT,可以:

struct termios options;
tcgetattr(fd, &options);
options.c_iflag &= ~BRKINT; // 禁止 BREAK 触发 SIGINT
tcsetattr(fd, TCSANOW, &options);

然后在 read() 中读取数据,如果 PARMRK 使能,BREAK 会作为 \377\0\0 传输。


7. 物理层行为

波特率1 帧字符时间(按10位字符来算)BREAK 最小持续时间
11520086.8 µs≥ 87 µs
96001.04 ms≥ 1.04 ms
24004.17 ms≥ 4.17 ms

例如,在 9600 bps 下,BREAK 必须至少 保持低电平 1.04 ms 才会被识别。


8. 相关 Linux 命令

  • stty 命令查看和设置 BREAK 处理方式
stty -F /dev/ttyS0 -a   # 查看当前串口设置
stty -F /dev/ttyS0 brkint  # 使能 BREAK 触发 SIGINT
stty -F /dev/ttyS0 -brkint # 禁止 BREAK 触发 SIGINT
  • 手动发送 BREAK
echo -e "\x00" > /dev/ttyS0   # 可能不会产生 BREAK
stty -F /dev/ttyS0 sendbreak   # 发送 BREAK 信号

总结

  • BREAK 信号 = TX 线保持低电平超过 1 个字符时间
  • 用途:设备复位、终端控制(SIGINT)、调制解调器控制、错误检测等。
  • Linux 处理方式
    • IGNBRK:忽略 BREAK
    • BRKINT:BREAK 触发 SIGINT
    • tcsendbreak(fd, duration) 主动发送 BREAK
  • 应用场景
    • 串口调试时可用 BREAK 触发设备复位
    • TTY 终端可用 BREAK 中断进程
    • 工业设备可能使用 BREAK 作为特殊信号

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值