《UNIX环境高级编程》笔记--行控制函数、终端标识、终端窗口大小

来源:互联网 发布:北大网络教育好考吗 编辑:程序博客网 时间:2024/04/30 10:49

1.行控制函数

下列4个函数提供了终端设备的行控制能力,其中,参数filedes引用一个终端设备,否则出错返回,errno设置为ENOTTY。
#include<termios.h>int tcdrain(int filedes);int tcflow(int filedes, int action);int tcflush(int filedes, int queue);int tcsendbreak(int fledes, int duration);//四个函数返回值:若成功则返回0,出错则返回-1.
tcdrain函数等待所有输出都被发送。tcflow用于对输入和输出流控制进行控制。action参数应当是下列四个值之一。
TCOOFF 输出被挂起。
TCOON  重新启动以前被挂起的输出。
TCIOFF  系统发送一个STOP字符。这将使终端设备暂停发送数据。
TCION  系统发送一个START字符。这将使终端恢复发送数据。
tcflush函数刷清输入缓冲区或输出缓冲区。输入缓冲区中的数据时终端驱动程序已接收到,但是用户尚未读的;输出缓冲区中
的数据时用于程序已经写,但尚未发送的。
queue参数应当是下列三个常量之一:
TCIFLUSH  刷清输入队列。
TCOFLUSH 刷清输出队列。
TCIOFLUSH  刷清输入输出队列。
tcsendbreak函数在一个指定的时间区间内发送连续的0位流。若duration参数为0,则此种发送延续0.25至0.5秒之间。

2.终端标识

在大多数UNIX系统中,控制终端的名字是/dev/tty。POSIX.1提供了一个运行时函数,可被用来确定控制终端的名字。
#include <stdio.h>char *ctermid(char *ptr); //若成功则返回指向控制终端名的指针,若出错则返回指向空字符串的指针。
如果ptr非null,则它被认为是一个指针,指向长度至少为L_ctermid字节的数组,进程控制终端名存放在该数组中。常量
L_ctermid定义在<stdio.h>中。若ptr是一个空指针,则该函数为数组分配空间(通常为静态变量)。同样,进程的
控制终端名存放在该数组中。

另外两个与终端标识有关的函数是isatty和ttyname。isatty在文件描述符引用一个终端设备时返回真,后者则返回在该文件
描述符上打开的终端设备的路径名。
#include<unistd.h>int isatty(int filedes); //若为终端设备则返回1,否则返回0.char *ttyname(int filedes); //返回值:指向终端路径名的指针,出错则返回NULL。

3.终端窗口大小

大多数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)
};
此结构的作用如下:
用ioctl的TIOCGWINSZ命令可以取此结构的当前值。
用ioctl的TIOCSWINSZ命令可以将此结构的新值存放到内核中,如果此新值与存放在内核中的当前值不同,则向前台进程组
发送SIGWINCH信号。
除了存放此结构的当前值以及在此值改变时产生一个信号以外,内核对该结构不进行任何操作。
提供这种功能的目的是,当窗口大小发生变化时通知应用程序,应用程序接到此信号后,它可以取窗口大小的新值,然后重绘
屏幕。

实践:
#include <stdio.h>#include <termios.h>#include <sys/ioctl.h>#include <signal.h>#include <unistd.h>static voidpr_winsize(int fd){        struct winsize size;        if(ioctl(fd,TIOCGWINSZ,(char*)&size) < 0){                perror("ioctl");                return;        }        printf("%d rows, %d columns\n",size.ws_row, size.ws_col);}static voidsig_winch(int signo){        printf("SIGWINCH received.\n");        pr_winsize(STDIN_FILENO);}int main(void){        if(isatty(STDIN_FILENO) == 0){                perror("isatty");                return -1;        }        if(signal(SIGWINCH,sig_winch) == SIG_ERR){                perror("signal");                return -1;        }        pr_winsize(STDIN_FILENO);        for(;;){                pause();        }}
运行结果:
root@gmdz-virtual-machine:~# ./a.out
22 rows, 76 columns 
SIGWINCH received.  //改变终端窗口大小
22 rows, 77 columns
SIGWINCH received. //改变终端窗口大小
23 rows, 77 columns
0 0