转载来源:吴家伟的博客
一、数据成员
各个字段的选项如下(不是所有UNIX系统都支持):
c_iflag:
- BRKINT:接到BREAK时产生SIGINT;
- ICRNL:将输入的CR转换为NL;
- IGNBRK:忽略BREAK条件;
- IGNCR:忽略CR;
- IGNPAR:忽略奇偶错字符;
- IMAXBEL:在输入队列空时振铃;
- INLCR:将输入的NL转换为CR;
- INPCK:打开输入奇偶校验;
- ISTRIP:剥除输入字符的第8位;
- IUCLC:将输入的大写字符转换成小写字符(仅SVR4);
- IXANY:使任一字符都重新起动输出;
- IXOFF:使起动/停止输入控制流起作用;
- IXON:使起动/停止输出控制流起作用;
- PARMRK:标记奇偶错;
c_oflag:
- BSDLY:退格延迟屏蔽(仅SVR4);
- CRDLY:CR延迟屏蔽(仅SVR4);
- FFDLY:换页延迟屏蔽(仅SVR4);
- NLDLY:NL延迟屏蔽(仅SVR4);
- OCRNL:将输出的CR转换为NL(仅SVR4);
- OFDEL:填充符为DEL,否则为NUL(仅SVR4);
- OFILL:对于延迟使用填充符(仅SVR4);
- OLCUC:将输出的小写字符转换为大写字符(仅SVR4);
- ONLCR:将NL转换为CR-NL;
- ONLRET:NL执行CR功能(仅SVR4);
- ONOCR:在0列不输出CR(仅SVR4);
- ONOEOT:在输出中删除EOT字符(仅4.3+BSD);
- OPOST:执行输出处理;
- OXTABS:将制表符扩充为空格(仅4.3+BSD);
- TABDLY:水平制表符延迟屏蔽(仅SVR4);
- VTDLY:垂直制表符延迟屏蔽(仅SVR4);
c_cflag:
- CCTS_OFLOW:输出的CTS流控制(仅4.3+BSD);
- CIGNORE:忽略控制标志(仅4.3+BSD);
- CLOCAL:忽略解制解调器状态行;
- CREAD:启用接收装置;
- CRTS_IFLOW:输入的RTS流控制(仅4.3+BSD);
- CSIZE:字符大小屏蔽;
- CSTOPB:送两个停止位,否则为1位;
- HUPCL:最后关闭时断开;
- MDMBUF:经载波的流控输出(仅4.3+BSD);
- PARENB:进行奇偶校;
- PARODD:奇校,否则为偶校;
c_lflag:
- ALTWERASE:使用替换WERASE算法(仅4.3+BSD);
- ECHO:进行回送;
- ECHOCTL:回送控制字符为^(char);
- ECHOE:可见擦除符;
- ECHOK:回送kill符;
- ECHOKE:kill的可见擦除;
- ECHONL:回送NL;
- ECHOPRT:硬拷贝的可见擦除方式;
- FLUSHO:刷清输出;
- ICANON:规范输入;
- IEXTEN:使扩充的输入字符处理起作用;
- ISIG:使终端产生的信号起作用;
- NOFLSH:在中断或退出键后不刷清;
- NOKERNINFO:STATUS不使内核输出(仅4.3+BSD);
- PENDIN:重新打印;
- TOSTOP:对于后台输出发送SIGTTOU;
- XCASE:规范大/小写表示(仅SVR4);
字符 | 说明 | c_cc下标 | 起作用,由: | 典型值 | POSIX.1 | SVR4 | 4.3+BSD | |
---|---|---|---|---|---|---|---|---|
字段 | 标志 | 扩充 | ||||||
CR | 回车 | 不能更改 | c_lflag | ICANON | /r | YES | | |
DISCARD | 擦除输出 | VDISCARD | c_lflag | IEXTEN | ^O | | YES | YES |
DSUSP | 延迟挂起(SIGTSTP) | VDUSP | c_lflag | ISIG | ^Y | | YES | YES |
EOF | 文件结束 | VEOF | c_lflag | ICANON | ^D | YES | | |
EOL | 行结束 | VEOL | c_lflag | ICANON | | YES | | |
EOL2 | 替换的行结束 | VEOL2 | c_lflag | ICANON | | | YES | YES |
ERASE | 擦除字符 | VERASE | c_lflag | ICANON | ^H | YES | | |
INTR | 中断信号(SIGINT) | VINTR | c_lflag | ISIG | ^?, ^C | YES | | |
KILL | 擦行 | VKILL | c_lflag | ICANON | ^U | YES | | |
LNEXT | 下一个字列字符 | VLNEXT | c_lflag | IEXTEN | ^V | | YES | YES |
NL | 新行 | 不能更改 | c_lflag | ICANON | /n | YES | | |
QUIT | 退出信号(SIGQUIT) | VQUIT | c_lflag | ISIG | ^/ | YES | | |
REPRINT | 再打印全部输入 | VREPRINT | c_lflag | ICANON | ^R | | YES | YES |
START | 恢复输出 | VSTART | c_lflag | IXON/IXOFF | ^Q | YES | | |
STATUS | 状态要求 | VSTATUS | c_lflag | ICANON | ^T | | | YES |
STOP | 停止输出 | VSTOP | c_lflag | IXON/IXOFF | ^S | YES | | |
SUSP | 挂起信号(SIGTSTP) | VSUSP | c_lflag | ISIG | ^Z | YES | | |
WERASE | 擦除字 | VWERASE | c_lflag | ICANON | ^W | | YES | YES |
4.POSIX终端I/O函数
tcgetattr | 取属性(termios结构); |
tcsetattr | 设置属性(termios结构); |
cfgetispeed | 得到输入速度; |
cfgetospeed | 得到输出速度; |
cfsetispeed | 设置输入速度; |
cfsetospeed | 设置输出速度; |
tcdrain | 等待所有输出都被传输; |
tcflow | 挂起传输或接收; |
tcflush | 刷清未决输入和/或输出; |
tcsendbreak | 送BREAK字符; |
tcgetpgrp | 得到前台进程组ID; |
tcsetpgrp | 设置前台进程组ID |
5.tcgetattr和tcsetattr
#include <termios.h> int tcgetattr(int filedes, struct termios *termptr); int tcsetattr(int filedes, int opt, const struct termios *termptr); 两个函数返回:若成功则为0,若出错则为-1
这两个函数都有一个指向termios结构的指针作为其参数,它们返回当前终端的属性,或者设置该终端的属性。因为这两个函数只对终端设备进行操作,所以若filedes并不引用一个终端设备则出错返回,errno设置为ENOTTY。
tcsetattr的参数opt使我们可以指定在什么时候新的终端属性才起作用。opt可以指定为下列常数中的一个:
- TCSANOW:更改立即发生;
- TCSADRAIN:发送了所有输出后更改才发生。若更改输出参数则应使用此选择项。
- TCSAFLUSH:发送了所有输出后更改才发生。更进一步,在更改发生时未读的所有输入数据都被删除(刷清)。
tcsetattr函数的返回值易于产生混淆。如果它执行了任意一种所要求的动作,即使未能执行所有要求的动作,它也返回0(表示成功)。如果该函数返回0,则我们有责任检查该函数是否执行了所有要求的动作。这就意味着,在调用tcsetattr设置所希望的属性后,需调用tcgetattr,然后将实际终端属性与所希望的属性相比较,以检测两者是否有区别。
6.波特率函数
波特率(baud rate)是一个历史沿用的术语,现在它指的是“位/每秒”。虽然大多数终端设备对输入和输出使用同一波特率,但是只要硬件许可,可以将它们设置为两个不同值。
#include <termios.h> speed_t cfgetispeed(const struct termios *termptr); speed_t cfgetospeed(const struct termios *termptr); 两个函数返回:波特率值 int cfsetispeed(struct termios *termptr, speed_t speed); int cfsetospeed(struct termios *termptr, speed_t speed); 两个函数返回:若成功为0,出错为-1
两个cfget函数的返回值,以及两个cfset函数的speed参数都是下列常数之一:B50、B75、B110、B134、B150、B200、B300、B600、B1200、B1800、B2400、B4800、B9600、B19200或B38400。常数B0表示“挂断”。在调用tcsetattr时将输出波特率指定为B0,则调制解调器的控制线就不再起作用。
使用这些函数时,应当理解输入、输出波特率是存放在termios结构中的。在调用任一cfget函数之前,先要用tcgetattr获得设备的termios结构。与此类似,在调用任一cfset函数后,应将波特率设置到termios结构中。为使这种更改影响到设备,应当调用tcsetattr函数。如果所设置的波特率有错,则在调用tcsetattr之前,不会发现这种错误。
7.行控制函数
#include <termios.h> int tcdrain(int filedes); int tcflow(int filedes, int action); int tcflush(int filedes, int queue); int tcsendbreak(int filedes, int duration); 四个函数返回:若成功则为0,若出错则为-1
其中,参数filedes引用一个终端设备,否则出错返回,errno设置为ENOTTY。
tcdrain函数等待所有输出都被发送。
tcflow用于对输入和输出流控制进行控制。action参数应当是下列四个值之一:
- TCOOFF:输出被挂起;
- TCOON:以前被挂起的输出被重新起动;
- TCIOFF:系统发送一个STOP字符。这将使终端设备暂停发送数据;
- TCION:系统发送一个START字符。这将使终端恢复发送数据。
tcflush函数刷清(抛弃)输入缓存(终端驱动程序已接收到,但用户程序尚未读)或输出缓存(用户程序已经写,但尚未发送)。queue参数应当是下列三个常数之一:
- TCIFLUSH:刷清输入队列;
- TCOFLUSH:刷清输出队列;
- TCIOFLUSH:刷清输入、输出队列;
tcsendbreak函数在一个指定的时间区间内发送连续的0位流。若duration参数为0,则此种发送延续0.25~ 0.5秒之间。POSIX.1说明若duration非0,则发送时间依赖于实现。
8.终端标识函数
POSIX.1提供了一个运行时函数,可被调用来决定控制终端的名字:
#include <stdio.h> char * ctermid(char *ptr);
如果ptr是非空,则它被认为是一个指针,指向长度至少为L_ctermid字节的数组,进程的控制终端名存放在该数组中。常数L_ctermid定义在<stdio.h>中。若ptr是一个空指针,则该函数为数组(通常作为静态变量)分配空间。同样,进程的控制终端名存放在该数组中。
在这两种情况中,该数组的起始地址被作为函数值返回。因为大多数UNIX系统都使用/dev/tty作为控制终端名,所以此函数的主要作用是帮助提高向其他操作系统的可移植性。
其他终端标识函数还有:
#include <unistd.h> int isatty(int filedes); 返回:若为终端设备则为1(真),否则为0(假) char *ttyname(int filedes); 返回:指向终端路径名的指针,若出错则为NULL
如果文件描述符引用一个终端设备,则isatty返回真,而ttyname则返回在该文件描述符上打开的终端设备的路径名。