TERMIOS - Linux手册页
Linux程序员手册 第3部分
更新日期: 2020-08-13
名称
termios,tcgetattr,tcsetattr,tcsendbreak,tcdrain,tcflush,tcflow,cfmakeraw,cfgetospeed,cfgetispeed,cfsetispeed,cfsetospeed,cfsetspeed-获取和设置终端属性,线路控制,获取和设置波特率
语法
#include <termios.h> #include <unistd.h> int tcgetattr(int fd, struct termios *termios_p); int tcsetattr(int fd, int optional_actions, const struct termios *termios_p); int tcsendbreak(int fd, int duration); int tcdrain(int fd); int tcflush(int fd, int queue_selector); int tcflow(int fd, int action); void cfmakeraw(struct termios *termios_p); speed_t cfgetispeed(const struct termios *termios_p); speed_t cfgetospeed(const struct termios *termios_p); int cfsetispeed(struct termios *termios_p, speed_t speed); int cfsetospeed(struct termios *termios_p, speed_t speed); int cfsetspeed(struct termios *termios_p, speed_t speed);
glibc的功能测试宏要求(请参阅feature_test_macros(7)):
cfsetspeed(),cfmakeraw():
从glibc 2.19开始:
_DEFAULT_SOURCE
Glibc 2.19及更早版本:
_BSD_SOURCE
说明
termios功能描述了提供的通用终端接口,用于控制异步通信端口。
The termios structure
这里描述的许多功能都有一个termios_p参数,该参数是指向termios结构的指针。此结构至少包含以下成员:
tcflag_t c_iflag; /* input modes */ tcflag_t c_oflag; /* output modes */ tcflag_t c_cflag; /* control modes */ tcflag_t c_lflag; /* local modes */ cc_t c_cc[NCCS]; /* special characters */
下面介绍可以分配给这些字段的值。对于前四个位掩码字段,仅当定义了特定的功能测试宏(请参见feature_test_macros(7))时才公开可能设置的某些相关标志的定义,如方括号(" [ ]")。
在下面的描述中,"不在POSIX中"表示未在POSIX.1-2001中指定该值,而" XSI"意味着在POSIX.1-2001中指定了该值作为XSI扩展的一部分。
c_iflag标志常量:
- IGNBRK
- 忽略输入的BREAK条件。
- BRKINT
- 如果设置了IGNBRK,则会忽略BREAK。如果未设置,但设置了BRKINT,则BREAK会导致刷新输入和输出队列,并且如果该终端是前台进程组的控制终端,它将导致SIGINT发送到该前台进程组。如果既未设置IGNBRK也未设置BRKINT,则BREAK读取为空字节(aq \ 0aq),除非设置了PARMRK,在这种情况下,其读取为序列\ 377 \ 0 \ 0。
- IGNPAR
- 忽略成帧错误和奇偶校验错误。
- PARMRK
- 如果设置了此位,则在传递给程序时会标记具有奇偶校验或成帧错误的输入字节。仅当设置了INPCK且未设置IGNPAR时,该位才有意义。标记错误字节的方式是使用前面的两个字节\ 377和\ 0。因此,程序实际上从终端接收到一个错误字节的三个字节。如果有效字节的值为\ 377,并且未设置ISTRIP(请参见下文),则程序可能会将其与标记奇偶校验错误的前缀混淆。因此,在这种情况下,有效字节\ 377作为两个字节\ 377 \ 377传递给程序。
- 如果既未设置IGNPAR也未设置PARMRK,则读取具有奇偶校验错误或成帧错误的字符\ 0。
- INPCK
- 启用输入奇偶校验。
- ISTRIP
- 剥掉第八位。
- INLCR
- 在输入上将NL转换为CR。
- IGNCR
- 忽略输入的回车。
- ICRNL
- 在输入中将回车转换为换行符(除非设置了IGNCR)。
- IUCLC
- (不适用于POSIX)在输入时将大写字符映射为小写。
- IXON
- 在输出上启用XON / XOFF流控制。
- IXANY
- (XSI)键入任何字符将重新启动停止的输出。 (默认是仅允许使用START字符来重新开始输出。)
- IXOFF
- 在输入上启用XON / XOFF流控制。
- IMAXBEL
- (不在POSIX中)当输入队列已满时响铃。 Linux不会实现此位,并且就像始终将其设置一样。
- IUTF8(since Linux 2.6.4)
- (不在POSIX中)输入为UTF8;这样可以在烹饪模式下正确执行字符擦除。
c_oflag标志常量:
- OPOST
- 启用实现定义的输出处理。
- OLCUC
- (不适用于POSIX)在输出时将小写字符映射为大写。
- ONLCR
- (XSI)在输出上将NL映射到CR-NL。
- OCRNL
- 在输出上将CR映射到NL。
- ONOCR
- 不要在第0列输出CR。
- ONLRET
- 不输出CR。
- OFILL
- 发送填充字符有一个延迟,而不是使用定时延迟。
- OFDEL
- 填充字符为ASCII DEL(0177)。如果未设置,则填充字符为ASCII NUL(aq \ 0aq)。 (未在Linux上实现。)
- NLDLY
- 换行延迟掩码。值是NL0和NL1。 [需要_BSD_SOURCE或_SVID_SOURCE或_XOPEN_SOURCE]
- CRDLY
- 回车延误掩码。值为CR0,CR1,CR2或CR3。 [需要_BSD_SOURCE或_SVID_SOURCE或_XOPEN_SOURCE]
- TABDLY
- 水平制表符延迟掩码。值是TAB0,TAB1,TAB2,TAB3(或XTABS,但请参见" BUGS"部分)。 TAB3的值(即XTABS)将制表符扩展为空格(制表符每八列停止一次)。 [需要_BSD_SOURCE或_SVID_SOURCE或_XOPEN_SOURCE]
- BSDLY
- 退格延迟掩码。值为BS0或BS1。 (从未实现。)[需要_BSD_SOURCE或_SVID_SOURCE或_XOPEN_SOURCE]
- VTDLY
- 垂直制表符延迟掩码。值为VT0或VT1。
- FFDLY
- 进纸延迟掩码。值为FF0或FF1。 [需要_BSD_SOURCE或_SVID_SOURCE或_XOPEN_SOURCE]
c_cflag标志常量:
- CBAUD
- (不在POSIX中)波特率速度掩码(4 + 1位)。 [需要_BSD_SOURCE或_SVID_SOURCE]
- CBAUDEX
- (不适用于POSIX)CBAUD中包含额外的波特率掩码(1位)。 [需要_BSD_SOURCE或_SVID_SOURCE]
- (POSIX表示,波特率速度存储在termios结构中,而没有指定精确的位置,并提供cfgetispeed()和cfsetispeed()进行获取。某些系统使用cBc在C_cflag中选择的位,其他系统使用单独的字段,例如,sg_ispeed和sg_ospeed。)
- CSIZE
- 字符大小掩码。值为CS5,CS6,CS7或CS8。
- CSTOPB
- 设置两个停止位,而不是一个。
- CREAD
- 启用接收器。
- PARENB
- 对输出启用奇偶校验生成,对输入启用奇偶校验。
- PARODD
- 如果设置,则输入和输出的奇偶校验为奇数;否则为0。否则,将使用奇偶校验。
- HUPCL
- 最后一个过程关闭设备(挂断)后,降低调制解调器控制线。
- CLOCAL
- 忽略调制解调器控制线。
- LOBLK
- (不适用于POSIX)阻止非当前Shell层的输出。供shl(外壳层)使用。 (未在Linux上实现。)
- CIBAUD
- (不适用于POSIX)输入速度的掩码。 CIBAUD位的值与CBAUD位的值相同,向左移IBSHIFT位。 [需要_BSD_SOURCE或_SVID_SOURCE](在Linux上未实现。)
- CMSPAR
- (不适用于POSIX)使用" stick"(标记/空格)奇偶校验(在某些串行设备上受支持):如果设置了PARODD,则奇偶校验位始终为1;否则为0。如果未设置PARODD,则奇偶校验位始终为0。[需要_BSD_SOURCE或_SVID_SOURCE]
- CRTSCTS
- (不在POSIX中)启用RTS / CTS(硬件)流控制。 [需要_BSD_SOURCE或_SVID_SOURCE]
c_lflag标志常量:
- ISIG
- 收到任何字符INTR,QUIT,SUSP或DSUSP时,都会产生相应的信号。
- ICANON
- 启用规范模式(如下所述)。
- XCASE
- (在POSIX中不是;在Linux下不受支持)如果还设置了ICANON,则terminal只能是大写字母。输入将转换为小写字母,但\之前的字符除外。在输出时,大写字符以\开头,小写字符转换为大写。 [需要_BSD_SOURCE或_SVID_SOURCE或_XOPEN_SOURCE]
- ECHO
- 回声输入字符。
- ECHOE
- 如果还设置了ICANON,则ERASE字符将擦除前面的输入字符,而WERASE将擦除前面的单词。
- ECHOK
- 如果还设置了ICANON,则KILL字符将擦除当前行。
- ECHONL
- 如果还设置了ICANON,即使未设置ECHO,也应回显NL字符。
- ECHOCTL
- (不适用于POSIX)如果还设置了ECHO,则将TAB,NL,START和STOP以外的终端特殊字符回显为haX,其中X是ASCII码比特殊字符大0x40的字符。例如,字符0x08(BS)回显为haH。 [需要_BSD_SOURCE或_SVID_SOURCE]
- ECHOPRT
- (不在POSIX中)如果还设置了ICANON和ECHO,则在擦除字符时将其打印出来。 [需要_BSD_SOURCE或_SVID_SOURCE]
- ECHOKE
- (不在POSIX中)如果还设置了ICANON,则按照ECHOE和ECHOPRT的指定,通过擦除行上的每个字符来回显KILL。 [需要_BSD_SOURCE或_SVID_SOURCE]
- DEFECHO
- (不适用于POSIX)仅在读取进程时回显。 (未在Linux上实现。)
- FLUSHO
- (不在POSIX中;在Linux下不受支持)正在刷新输出。通过输入DISCARD字符可切换此标志。 [需要_BSD_SOURCE或_SVID_SOURCE]
- NOFLSH
- 生成INT,QUIT和SUSP字符的信号时,请禁用刷新输入和输出队列。
- TOSTOP
- 将SIGTTOU信号发送到尝试写入其控制终端的后台进程的进程组。
- PENDIN
- (在POSIX中不是;在Linux下不受支持)在读取下一个字符时,将重新打印输入队列中的所有字符。 (bash(1)以这种方式处理提前输入。)[需要_BSD_SOURCE或_SVID_SOURCE]
- IEXTEN
- 启用实现定义的输入处理。必须启用此标志以及ICANON,才能解析特殊字符EOL2,LNEXT,REPRINT,WERASE,并使IUCLC标志有效。
c_cc数组定义终端特殊字符。符号索引(初始值)和含义是:
- VDISCARD
- (不适用于POSIX; Linux不支持; 017,SI,Ctrl-O)切换:开始/停止丢弃待处理的输出。设置IEXTEN后识别,然后不作为输入传递。
- VDSUSP
- (不在POSIX中;在Linux下不受支持; 031,EM,Ctrl-Y)延迟的挂起字符(DSUSP):在用户程序读取该字符时发送SIGTSTP信号。在设置IEXTEN和ISIG且系统支持作业控制,然后不作为输入传递时识别。
- VEOF
- (004,EOT,Ctrl-D)文件结尾字符(EOF)。更准确地说:此字符使待处理的tty缓冲区被发送到等待的用户程序,而无需等待行尾。如果它是该行的第一个字符,则用户程序中的read(2)返回0,表示文件结束。在设置ICANON时识别,然后不作为输入传递。
- VEOL
- (0,NUL)附加的行尾字符(EOL)。设置ICANON时可识别。
- VEOL2
- (不在POSIX中; 0,NUL)另一个行尾字符(EOL2)。设置ICANON时可识别。
- VERASE
- (0177,DEL,外表或010,BS,Ctrl-H或#)擦除字符(ERASE)。这会擦除以前尚未擦除的字符,但不会擦除过去的EOF或行首。在设置ICANON时识别,然后不作为输入传递。
- VINTR
- (003,ETX,Ctrl-C或0177,DEL,rubout)中断字符(INTR)。发送SIGINT信号。设置ISIG后识别,然后不作为输入传递。
- VKILL
- (025,NAK,Ctrl-U或Ctrl-X或@),杀死角色(KILL)。自上次EOF或行首以来,这将擦除输入。在设置ICANON时识别,然后不作为输入传递。
- VLNEXT
- (不适用于POSIX; 026,SYN,Ctrl-V)立即数下一个(LNEXT)。引用下一个输入字符,使它失去可能的特殊含义。设置IEXTEN后识别,然后不作为输入传递。
- VMIN
- 非规范读取的最小字符数(MIN)。
- VQUIT
- (034,FS,Ctrl- \)退出字符(QUIT)。发送SIGQUIT信号。设置ISIG后识别,然后不作为输入传递。
- VREPRINT
- (不在POSIX中; 022,DC2,Ctrl-R)重新打印未读字符(REPRINT)。设置ICANON和IEXTEN,然后不作为输入传递时识别。
- VSTART
- (021,DC1,Ctrl-Q)起始字符(START)。重新启动由Stop字符停止的输出。设置IXON后识别,然后不作为输入传递。
- VSTATUS
- (不适用于POSIX; Linux不支持;状态请求:024,DC4,Ctrl-T)。状态字符(STATUS)。在终端上显示状态信息,包括前台进程的状态及其已消耗的CPU时间。还将SIGINFO信号(Linux不支持)发送到前台进程组。
- VSTOP
- (023,DC3,Ctrl-S)停止字符(STOP)。停止输出,直到键入开始字符。设置IXON后识别,然后不作为输入传递。
- VSUSP
- (032,SUB,Ctrl-Z)挂起字符(SUSP)。发送SIGTSTP信号。设置ISIG后识别,然后不作为输入传递。
- VSWTCH
- (在POSIX中不;在Linux下不受支持; 0,NUL)切换字符(SWTCH)。在System V中用于在Shell层中切换Shell,这是Shell作业控制的前身。
- VTIME
- 非规范读取(TIME)的超时时间(以分秒为单位)。
- VWERASE
- (不适用于POSIX; 027,ETB,Ctrl-W)字清除(清除)。设置ICANON和IEXTEN,然后不作为输入传递时识别。
通过将相应的c_cc元素的值设置为_POSIX_VDISABLE,可以禁用单个终端特殊字符。
除了VTIME,VMIN分别具有与VEOL,VEOF相同的值外,以上符号下标值均不同。在非规范模式下,特殊字符含义由超时含义代替。有关VMIN和VTIME的说明,请参见下面的非规范模式说明。
Retrieving and changing terminal settings
tcgetattr()获取与fd引用的对象关联的参数,并将其存储在termios_p引用的termios结构中。该功能可以从后台进程中调用;但是,终端属性可能随后会被前台进程更改。
tcsetattr()从termios_p引用的termios结构中设置与终端关联的参数(除非需要不可用的基础硬件的支持)。 optional_actions指定更改何时生效:
- TCSANOW
- 更改立即发生。
- TCSADRAIN
- 在传输完所有写入fd的输出之后,将发生更改。更改影响输出的参数时,应使用此选项。
- TCSAFLUSH
- 更改发生在写入fd引用的对象的所有输出都已传输之后,并且在进行更改之前,已接收但未读取的所有输入将被丢弃。
Canonical and noncanonical mode
c_lflag中ICANON佳能标志的设置确定终端是在规范模式下(ICANON设置)还是在非规范模式下(ICANON未设置)运行。默认情况下,设置ICANON。
在规范模式下:
- *
- 逐行提供输入。输入一个行定界符(NL,EOL,EOL2或行首的EOF)时,输入行可用。除EOF以外,行定界符包含在read(2)返回的缓冲区中。
- *
- 启用了行编辑(ERASE,KILL;如果设置了IEXTEN标志:WERASE,REPRINT,LNEXT)。 read(2)最多返回一行输入;如果read(2)请求的字节少于当前输入行中可用的字节,则仅读取请求的字节数,其余字符可用于将来的read(2)。
- *
- 最大行长为4096个字符(包括终止的换行符);长度超过4096个字符的行将被截断。在4095个字符之后,将继续进行输入处理(例如ISIG和ECHO *处理),但在4095个字符之后(直至(但不包括)任何终止换行符)的所有输入数据都将被丢弃。这样可以确保终端可以始终接收更多输入,直到可以读取至少一行。
在非规范模式下,输入立即可用(无需用户输入行定界符),不执行任何输入处理,并且禁用行编辑。读缓冲区仅接受4095个字符;如果将输入模式切换为规范,则为换行符提供了必要的空间。 MIN(c_cc [VMIN])和TIME(c_cc [VTIME])的设置确定read(2)完成的情况;有四种不同的情况:
- MIN == 0, TIME == 0 (polling read)
- 如果有可用数据,read(2)将立即返回,而可用字节数或请求的字节数较少。如果没有可用数据,则read(2)返回0。
- MIN > 0, TIME == 0 (blocking read)
- read(2)阻塞,直到MIN个字节可用为止,并返回最多所请求的字节数。
- MIN == 0, TIME > 0 (read with timeout)
- TIME以十分之一秒为单位指定计时器的限制。调用read(2)时启动计时器。当至少一个字节的数据可用或计时器到期时,read(2)返回。如果计时器到期而没有任何可用输入,则read(2)返回0。如果在调用read(2)时数据已经可用,则该调用的行为就好像在调用之后立即接收到数据一样。
- MIN > 0, TIME > 0 (read with interbyte timeout)
- TIME specifies the limit for a timer in tenths of a second.
Once an initial byte of input becomes available,
the timer is restarted after each further byte is received.
read(2)
returns when any of the following conditions is met:
- 由于仅在初始字节可用后才启动计时器,因此将至少读取一个字节。如果在调用read(2)时数据已经可用,则该调用的行为就像在调用之后立即接收到数据一样。
POSIX不指定O_NONBLOCK文件状态标志的设置是否优先于MIN和TIME设置。如果设置了O_NONBLOCK,则无论MIN或TIME的设置如何,非规范模式下的read(2)都可能立即返回。此外,如果没有可用数据,则POSIX允许在非规范模式下的read(2)返回0或-1,并将errno设置为EAGAIN。
Raw mode
cfmakeraw()将终端设置为类似于旧版本7终端驱动程序的"原始"模式:逐字符可用输入,禁用回显,并且禁用终端输入和输出字符的所有特殊处理。终端属性设置如下:
termios_p->c_iflag &= ti(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); termios_p->c_oflag &= tiOPOST; termios_p->c_lflag &= ti(ECHO | ECHONL | ICANON | ISIG | IEXTEN); termios_p->c_cflag &= ti(CSIZE | PARENB); termios_p->c_cflag |= CS8;
Line control
如果终端使用异步串行数据传输,则tcsendbreak()会在特定持续时间内传输连续的零值比特流。如果持续时间为零,则它将零值位传输至少0.25秒且不超过0.5秒。如果持续时间不为零,则它将在某些实现定义的时间长度内发送零值位。
如果终端未使用异步串行数据传输,则tcsendbreak()将返回而不采取任何措施。
tcdrain()等待,直到写入fd引用的对象的所有输出都已传输。
根据queue_selector的值,tcflush()丢弃写入fd所引用但未发送的对象的数据或已接收但未读取的数据:
- TCIFLUSH
- 刷新已接收但未读取的数据。
- TCOFLUSH
- 刷新已写入但未传输的数据。
- TCIOFLUSH
- 刷新已接收但未读取的数据,以及已写入但未传输的数据。
tcflow()挂起fd引用的对象上的数据传输或接收,具体取决于action的值:
- TCOOFF
- 暂停输出。
- TCOON
- 重新启动暂停的输出。
- TCIOFF
- 发送一个STOP字符,该字符将阻止终端设备向系统发送数据。
- TCION
- 发送一个START字符,这将启动终端设备向系统发送数据。
终端文件打开时的默认设置是既不暂停其输入也不暂停其输出。
Line speed
提供了波特率功能,用于在termios结构中获取和设置输入和输出波特率的值。在成功调用tcsetattr()之前,新值不会生效。
将速度设置为B0指示调制解调器"挂断"。对应于B38400的实际比特率可以使用setserial(8)进行更改。
输入和输出波特率存储在termios结构中。
cfgetospeed()返回存储在termios_p指向的termios结构中的输出波特率。
cfsetospeed()将存储在termios_p所指向的termios结构中的输出波特率设置为speed,该波特率必须是以下常量之一:
B0 B50 B75 B110 B134 B150 B200 B300 B600 B1200 B1800 B2400 B4800 B9600 B19200 B38400 B57600 B115200 B230400
零波特率B0用于终止连接。如果指定了B0,则调制解调器控制线将不再有效。通常,这将断开线路。 CBAUDEX是POSIX.1(57600及更高版本)中定义的速度以外的速度的掩盖。因此,B57600和CBAUDEX不为零。
cfgetispeed()返回存储在termios结构中的输入波特率。
cfsetispeed()将存储在termios结构中的输入波特率设置为speed,必须将其指定为cfsetospeed()上面列出的Bnnn常数之一。如果输入波特率设置为零,则输入波特率将等于输出波特率。
cfsetspeed()是4.4BSD扩展。它采用与cfsetispeed()相同的参数,并设置输入和输出速度。
返回值
cfgetispeed()返回存储在termios结构中的输入波特率。
cfgetospeed()返回存储在termios结构中的输出波特率。
所有其他函数返回:
- 0
- 成功。
- -1
- 如果失败,则设置errno来指示错误。
请注意,如果可以成功执行任何请求的更改,则tcsetattr()返回成功。因此,在进行多项更改时,可能有必要在此调用之后再调用tcgetattr()以检查是否已成功执行所有更改。
属性
有关本节中使用的术语的说明,请参见attribute(7)。
Interface | Attribute | Value |
tcgetattr(),tcsetattr(),tcdrain(),tcflush(),tcflow(),tcsendbreak(),cfmakeraw(),cfgetispeed(),cfgetospeed(),cfsetispeed(),cfsetospeed(),cfsetspeed() | Thread safety | MT-Safe |
遵循规范
在POSIX.1-2001中指定了tcgetattr(),tcsetattr(),tcsendbreak(),tcdrain(),tcflush(),tcflow(),cfgetispeed(),cfgetospeed(),cfsetispeed()和cfsetospeed()。
cfmakeraw()和cfsetspeed()是非标准的,但在BSD上可用。
备注
UNIX V7和更高版本的系统都有一个波特率列表,其中B14,...,B9600这十四个值之后是两个常量EXTA,EXTB(" External A"和" External B")。许多系统以更高的波特率扩展了列表。
tcsendbreak()的非零持续时间的影响会有所不同。 SunOS指定了一个持续时间* N秒的间隔,其中N至少为0.25,并且不大于0.5。 Linux,AIX,DU,Tru64发送间隔时间为毫秒的中断。 FreeBSD和NetBSD以及HP-UX和MacOS忽略持续时间的值。在Solaris和UnixWare下,持续时间为非零的tcsendbreak()的行为类似于tcdrain()。
BUGS
在Linux 4.16之前的Alpha架构(和2.28之前的glibc)上,XTABS值不同于TAB3,因此它被终端驱动程序的N_TTY行规程代码忽略(因为它不是TABDLY掩码的一部分) )。
出版信息
这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/。