分类: LINUX
2007-12-21 17:27:51
终端IO
终端IO有两种模式:
1. 规范模式。在这种模式下,输入以行为单位进行处理。每次读请求终端驱动都返回一行。
2. 非规范模式。输入字符不编成一行。
默认情况下系统采用规范模式。
POSIX。1定义了 11种特殊输入字符,它们中的9种可以改变。
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
};
输入标志:控制从终端设置驱动程序输入的字符。
输出标志:控制输出字符
控制标志:控制标志影响RS-232串行线
本地标志:本地标志影响驱动与用户之间的接口。如开关回显,显示擦除字符,使终端产生信号,为后台输出的工作控制停止信号
Tcflag_t对于标志位值已经足够大了,可以定义它为 unsigned int 或 unsigned long类型。
C_cc数组包含所有我们能改变的特别字符。Cc_t 通常定义为unsigned char
控制字符:
CLOCAL: 忽略modem状态线
CREAD: 使 接收器中 开启
CRTSCTS: 使硬件流控制开启
CSIZE: 字符大小的掩码
CSTOPB: 发送两个stop位,其它情况发送一个
CUPCL: 最后关闭时停止
PARENB: 部分开启
PARODD: 奇数,其它为偶数
输入标志:
BRKINT: 当BREAK时产生SIGINT信号
ICRNL: 在输入时将CR 转成 NL
IGNBRK : 忽略BREAK
IGNCR: 忽略CR
IGNPAR: 忽略字符
IMAXBEL 当队列满时振玲
INLCR 将NL换成CR
INPCK
IUCLC 大写字符转成小写字符
IXANY
IXOFF 开始或关闭输入流控制
IXON
PARMRK
本地标志:
ECHO 开启 echo
ECHOCTL 回显控制字符
ECHOE 显示擦除字符
ECHOK 显示KILL
ECHOKE 为KILL显示擦除字符
ECHONL 显示NL
ECHOPRT 为硬拷贝显示擦除字符
EXTPROC 扩展字符
FLUSHO
ICANON 规范输入
IEXTEN
ISIG 使终端产生信号开启
NOFLSH
……
终端IO总结:
Tcgetattr 得到属性(termios结构)
Tcsetattr
Cfgetispeed get input speed
Cfgetospeed 得到输出速度
Cfsetispeed
Cfsetospeed
Tcdrain 等待所有输出传出
Tcflow 挂起传输或接收
Tcflush
Tcsendbreak 发送BREAK字符
Tcgetpgrp 得到前台进程组ID
Tcsetpgrp 设置前台组ID
Tcgetsid 得到控制session头,进程组ID
每个终端设备有一个输入队列和一个输出队列
得到或调置终端属性
有两个函数很重要:tcgetattr 和 tcsetattr,它们都包含在
opt 的值可以有以下几个:
TCSANOW (terminal control set attribute now),改变立即发生
TCSADRIN ,在所有输出已经传出后,发生改变。
TCSAFLUSH , 所有输出已经传出后,且当改变发生时,所有没有输入被读的数据丢弃。
终端标识
历史上大多数版本的UNIX控制终端使用 /dev/tty. POSIX.1提供了我们能调用决定控
制终端名子的运行时函数。
#include
char *ctermid(char *ptr);
如果ptr非空,它指向 L_ctermid 数组的字节,且控制终端的名子存放在该数组中。如果ptr是空指针,函数为数组分配空间,进程控制终端的名子存放在该数组中。
isatty函数,当文件描述符指向的是终端设备,则返回真值。
ttyname函数,它返回终端设备的路径名。
规范模式
规范终端IO很简单,我们发出一个读请求后,终端驱动程序读取一行信息后返回,有几个条件引起读返回:
1. 当读到请求的字节数时读请求返回。
2. 当读请求遇到定界符时,读请求返回。如NL,EOL,EOL2, EOF
3. 如果捕获到一个信号且函数不自动重启,则读请求探返回。
非规范模式
非规范模式是指关闭termios结构中的c_lflag域的ICANON标志位。在非规范模式下,输入数据不编进一行,下面的一些特殊字符也不进行处理:ERASSE, KILL, EOF,NL, EOL, EOL2, CR, REPRINT ,STATUS 和 WERASE。
规范模式是容易的,系统每次返回一行。但在非规范模式下,系统知道什么时候返回数据给我们呢?
解决办法是系统或是在指定数量已经读够或是给定的时间超时时返回。该技术使用了两个变量:MIN和TIME。
MIN : 指明了在读返回之前应读的最小字节数。
TIME : 指明了等待数据的时间
它们一共有四种组合,每种情况描述如下:
1. MIN >0, TIME>0
TIMER指明从第一个接收到的字节开始计数。如果在超时前,接收到MIN个字节,那么返回字节数。如果发生了时间超时,至少有一个字节返回,因为计时器是从接收到第一个字节开始计数的。
2. MIN >0, TIME == 0
在这种情况下,直到读到的字节数达到MIN个时才返回。
3. MIN==0, TIME >0
TIME的值从读用read开始计算,如果收到一个字节或时间超时时返回。
4. MIN==0, TIME==0
如果一些数据是有效的,则 read返回这些数据。如果没有数据有效,则立即返回。
终端窗口大小
内核为每个终端和伪终端维护着一个winsize结构:
struct winsize{
unsigned short ws_row;
unsigned short ws_col;
unsigned short ws_xpixel;
unsigned short ws_ypixel;
};
规则如下:
1. 我们可以使用 ioctl 的 TIOCGWINSZ 得到该结构的当前值。
2. 我们可以使用 ioctl 的 TIOCSWINSZ 将新值保存到内核维护的结构中。如果这个新值与当前内核中存放的值不一样,则SIGWINCH信号发送给当前进程组。
3. 当值发生变化时,除了保存结构的当前值和产生一个信号之外,内核不做其它事情。
terncap, terminfo, curses
termcap 代表 terminal capability, 它表示 /etc/termcap文件和读该文件的一列列程。termcap文件中包含各种终端的描述。如终端支持那种特性和使终端执行某些操作。
总结: