All I know is that a process has file descriptor 0/1 set to stdin/stdout by default. But how does programs such as vi know about window size, especially when I can resize the window freely in desktop environment? I can't think of how this could be sent via signals, so I guess there are some other mechanisms?.
I do not know anything about terminal emulator, which I guess might be related to the question. Any pointers will be helpful and appreciated.
ACCEPTED]
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
[1] for details.
SIGWINCH has been added to POSIX and the functions tcgetsize() and tcsetsize() have been added to POSIX. They are part of the upcomming Issue 8 standard version that is expected to be ready to the end of this year. - schily
tcgetattr() instead of the preexisting ioctls. - schily
tty command merely check the file /proc/self/fd/0, does that mean fd 0 is the controlling tty? - QnA
tty command does not show the name of the controlling tty, but the "file name of the terminal connected to standard input". If a process wants to read, write or performs ioctls like TIOCGWINSZ on its controlling tty, it can do it by opening the /dev/tty pseudo-device, which will relay all those operations to the real device which is the controlling tty. - user313992
/proc/<pid>/stat file (that's where ps -o tty get its info from) but that can't be reliably matched with a path, because multiple tty can have the same device number. - user313992
/dev/tty* (or /dev/pts/*) to open? Is there a special fd or some other variable to remember this information? - QnA
/dev/tty (not /dev/tty1 or /dev/pts/1 or any path returned by tty(1)) if it wants to access its controlling tty. - user313992
tcgetwinsize and tcsetwinsize are going to be added to POSIX. The ioctl calls won't as POSIX does not standardise any ioctl calls besides the STREAMS interface. That's why I devised the tcgetwinsize and tcsetwinsize functions. - FUZxxl