大多数UNIX系统都提供了一种功能,可以对当前终端窗口的大小进行跟踪,在窗口大小发生变化时,使内核通知前台进程组。内核为每个终端和伪终端保存一个winsize结构:
Struct winsize {
unsigned short ws_row; /* rows, in character */
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信号。
- 除了存放此结构的当前值以及在此值改变时产生一个信号以外,内核对该结构不进行任何其他操作。对结构中的值进行解释完全是应用程序的工作。
- 提供这种功能的目的是,当窗口大小发生变化时通知应用程序(例如,vi编辑器)。应用程序接到此信号后,它可以取窗口大小的新值,然后重绘屏幕。
实例:打印当前窗口大小,然后休眠。每次窗口大小改变时,就捕捉到SIGWINCH信号,然后打印新的窗口大小。必须用一个信号终止此程序。
程序清单18-12 打印窗口大小
#include "apue.h"
#include <termios.h>
#ifndef TIOCGWINSZ
#include <sys/ioctl.h>
#endif
static void
pr_winsize(int fd)
{
struct winsize size;
if(ioctl(fd, TIOCGWINSZ, (char *)&size) < 0)
err_sys("TIOCGWINSZ error");
printf("%d rows, %d columns ", size.ws_row, size.ws_col);
}
static void
sig_winch(int signo)
{
printf("SIGWINCH received ");
pr_winsize(STDIN_FILENO);
}
int
main(void)
{
if(isatty(STDIN_FILENO) == 0)
exit(1);
if(signal(SIGWINCH, sig_winch) == SIG_ERR)
err_sys("signal error");
pr_winsize(STDIN_FILENO); /* print initial size */
for(;;) /* and sleep forever */
pause();
}