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 void
pr_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 void
sig_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