termios中CSIZE的设置机制及相关位操作疑问解答
我在阅读termios手册页时,对CSIZE感到困惑。手册里的解释很晦涩:
CSIZE: 字符大小掩码。取值为CS5、CS6、CS7或CS8。
在rawmode示例中,先执行termios_p->c_cflag &= ~(CSIZE | PARENB);清除CSIZE位,再执行termios_p->c_cflag |= CS8;设置CS8。由于CS5-CS8没有进一步的解释或取值说明,我搞不懂它的工作逻辑。
核心概念与操作解释
1. 字符大小掩码(CSIZE)的定义
CSIZE是c_cflag(控制标志位)中专门用来标记字符数据位长度的一组二进制位集合。它不是单个位,而是连续的几位(通常为2位),这几位的组合值用来表示当前终端/串口使用的字符数据位数(5/6/7/8位)。
2. ~CSIZE操作的作用
~CSIZE是对CSIZE对应的二进制位取反,配合&=操作的目的是彻底清除c_cflag中所有属于CSIZE的位。因为要设置新的字符长度前,必须先把原来的长度位清零,避免新旧值冲突导致设置错误。
比如假设CSIZE对应二进制0b11000000(仅为示例,实际值依系统而定),~CSIZE就是0b00111111,和c_cflag做按位与后,原CSIZE对应的那几位会被置为0,其他位保持不变。
3. |CS5/CS8操作的作用
|= CS8是将CS8对应的二进制位设置到c_cflag中。CS5/CS6/CS7/CS8是系统预定义的宏,每个宏对应CSIZE位域的一种合法组合:
- CS5:对应5位数据位的二进制取值
- CS6:对应6位数据位的二进制取值
- CS7:对应7位数据位的二进制取值
- CS8:对应8位数据位的二进制取值
由于之前已经把CSIZE的位清零,直接按位或就能准确设置新的字符长度,不会有旧值残留干扰。
4. CS5-CS8的数字含义
它们的本质是CSIZE位域的合法取值,和ISTRIP的逻辑不同——ISTRIP是单个控制位,用来剥离字符的最高位;而CS5-CS8是一组位的组合值。
举个实际系统的例子(不同系统细节可能有差异,但逻辑一致):
假设CSIZE占用c_cflag的第5、6位(从0开始计数),那么:
- CS5 =
0x00(二进制00000000),对应5位数据位 - CS6 =
0x20(二进制00100000),对应6位数据位 - CS7 =
0x40(二进制01000000),对应7位数据位 - CS8 =
0x60(二进制01100000),对应8位数据位
这些宏的存在是为了让开发者不用直接写底层的二进制/十六进制数值,而是用语义化的名称设置字符长度,代码更易读、更具可移植性。
内容的提问来源于stack exchange,提问作者iloveclang

