The size of a terminal is kept in kernel-internal structure, and can be queried by the TIOCGWINSZ
and set by TIOCSWINSZ
ioctls. See the ioctl_tty(2)
manpage for details.
Each time the window size is set via TIOCSWINSZ
(eg. by xterm
when its GUI window was resized) the kernel will send a SIGWINCH
signal to the foreground process group of that terminal.
A program like vi
catches that signal and updates its idea of the window size via TIOCGWINSZ
.
The window size is usually set by the program driving the master end of a pseudo-tty (like xterm
or sshd
) but any process able to open the tty (whether in read-only or write-only mode) can do it.
A command line interface to those ioctls is via the stty
program.
(eg. stty cols 80 rows 40
). This is useful with real serial terminals, which have no inherent size, and no standard way to pass that info through.
Though not yet standardized [1], all of this is not Linux-specific, and works similarly on other systems like BSD or Solaris. A notable difference is that a background process trying to change the size of its controlling tty with TIOCSWINSZ
will get a SIGTTOU
signal on BSD and Solaris, but not on Linux.
On any of those systems, a background process will NOT get a SIGWINCH
signal, neither when its controlling tty is resized, nor when it becomes a foreground process. Full screen programs assume that they're either running in the foreground or stopped, and also query the terminal size upon a SIGCONT
signal (together with other tty operations like switching to the alternate screen or turning the canonical mode off).
Notice that a process doesn't need to have an open handle to a tty for it to be its controlling tty, and it can have an open handle to a tty without it being its controlling tty.
There's no other way for a process to be notified of terminal size changes other than being in the tty's foreground process group. Also, there's no general way to be notified of other changes to the terminal parameters: tcsetattr(3)
will not generate any signal or event that can be select(2)
ed on.
[1] A standard interface is slated to be included in an upcoming version of POSIX, with the tcgetwinsize
and tcsetwinsize
functions, easily implementable as wrappers to ioctl(TIOC[SG]WINSZ)
. See here for details.