APUE - 终端 I/O

综述

终端 I/O 有两种不同的工作模式:

  1. 规范模式输入处理。在这种模式中,终端输入以行为单位进行处理。对于每个读要求,终端驱动程序最多返回一行。
  2. 非规范模式输入处理。输入字符并不组成行。

如果不作特殊处理,则默认模式是规范模式。

所有我们可以检测和更改的终端设备特性都包含在 termios 结构中。该结构定义在头文件 中。

struct termios {
    tcflag_t    c_iflag;    /* input flags */
    tcflag_t    c_oflag;    /* output flags */
    tcflag_t    c_cflag;    /* control flags */
    tcflag_t    c_lflag;    /* local flags */
    cc_t        c_cc[NCCS]; /* control characters */
};

获得和设置终端属性

使用函数 tcgetattr 和 tcsetattr 可以获得或设置 termios 结构。这样也就可以检测和修改各种终端选择标志和特殊字符,以使终端按我们所希望的方式进行操作。

#include <termios.h>
int tcgetattr(int filedes, struct termios *termptr);
int tcsetattr(int filedes, int opt, const struct termios *termptr);

波特率函数

波特率是一个以往采用的术语,现在它指的是“位/秒”。虽然大多数终端设备对输入和输出使用同一波特率,但是只要硬件许可,可以将它们设置为两个不同值。

#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);

行控制函数

下列 4 个函数提供了终端设备的行控制能力。

#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);

终端标识

在大多数 UNIX 系统中,控制终端的名字是 /dev/tty。POSIX.1 提供了一个运行时函数,可被用来确定控制终端的名字。

#include <stdio.h>
char *ctermid(char *ptr);

另外两个与终端标识有关的函数是 isatty 和 ttyname。前者在文件描述符引用一个终端设备时返回真,而后者返回在文件描述符上打开的终端设备的路径名。

#include <unistd.h>
int isatty(int filedes);
char *ttyname(int filedes);

终端的窗口大小

大多数 UNIX 系统都提供了一种功能,可以对当前终端窗口的大小进行跟踪,在窗口大小发生变化时,使内核通知前台进程组。内核为每个终端和伪终端保存一个 winsize 结构:

struct winsize {
    unsigned short  ws_row;     /* rows, in characters */
    unsigned short  ws_col;     /* columns, in characters */
    unsigned short  ws_xpixel;  /* horizontal size, pixels (unused) */
    unsigned short  ws_ypixel;  /* vertical size, pixels (unused) */
};