3

I have been trying to understand how the TTY device driver works on a Linux machine for a few days now and still can't wrap my head around the idea.

When we open a terminal to ssh to a server, I understand most likely it will use pseudo-tty; that acts like a TTY in the terminal and processes the commands typed.

Since it uses a pseudo type tty, under the hood does it still use the tty technology to send out commands to the console?

In layman's terms, is the TTY always used in sending out commands to the console regardless of the terminal used? Is it the main driver for all things terminal?

I understand the tty character device that handles input and output and bunch of things that sends out signals to master/slave. I also know that a tty was used in the olden days. Is it still used today when opening our terminal regarding of OS/program used?

My knowledge is all over the place. I have very limited Linux knowledge. Would love to have a layman's explanation on how TTY works in today's Linux distributions.

1
  • I will check it out. Hopefully I understand it enough. Thank you
    – Chopnut
    Commented Jun 9, 2018 at 7:16

2 Answers 2

4

Which tty am I using?

tty - print the file name of the terminal connected to standard input

-- man tty

For example:

$ tty
/dev/pts/0

What type of tty is that? Which device driver is it implemented by?

The concept of device drivers is OS-specific. You asked for Linux specifically, but I still found a bunch of special cases when I tried to answer this question. So we can get a quicker answer if we look up specific examples.

/dev/pts/0

pts/0 is the first pseudo-terminal device, or "pty". pts means pseudo-terminal slave.

The slave pseudo-terminal behaves as an emulated tty device. Terminal emulators like gnome-terminal work by controlling the master end of the pseudo-terminal. For example, when you press the Enter key inside the gnome-terminal window, it writes a "new line" character to the master device. The "new line" character is then received on the slave device.

The two ends of a pty are not exactly symmetric. Writing the character for Control-C to the master device, may send the signal SIGINT to interrupt the processes using the slave device. The reverse is not true. No matter what character the program inside the terminal writes, it will not send an interrupt signal to gnome-terminal. The master device does not behave the same as a real tty.

/dev/ttyS0

ttyS0 is the first serial port device on your computer. If anyone has an old physical terminal, this is the type of port they can plug it in to. No slippery metaphors here! It all still works the same as a TTY device on historical Unixes. You can still buy PCs with serial ports if you look carefully :).[1]

The example with Control-C above applies equally to a serial terminal. If you press Control-C on the terminal, that character is received by the serial port, and the processes using the serial device may receive SIGINT and be interrupted. This is one common factor to any device which is used as a tty.

There is quite a large set of common TTY behaviours, which needed to apply equally to multiple types of TTY device that Linux would implement. If the two terminal devices duplicated a substantial amount of code, it would have been horrible to maintain and wasted valuable RAM.

In some Unixes / Unix-likes including Linux, behaviours like this are said to be implemented in a "line discipline". The same "line discipline" is used to implement this behaviour on serial ports, as it is on the pseudo terminal slave. Linux calls the line discipline which implements this behaviour, TTY... But let's not get too hung up on exact terms. The point is that it's a big chunk of shared code.

/*
 *  Copyright (C) 1991, 1992  Linus Torvalds
 */

/*
 * 'tty_io.c' gives an orthogonal feeling to tty's, be they consoles
 * or rs-channels. It also implements echoing, cooked mode etc.

-- https://elixir.bootlin.com/linux/v4.17/source/drivers/tty/tty_io.c [3000 lines]

 * n_tty.c --- implements the N_TTY line discipline.
 *
 * This code used to be in tty_io.c, but things are getting hairy
 * enough that it made sense to split things off.  (The N_TTY
 * processing has changed so much that it's hardly recognizable,
 * anyway...)
 *
 * Note that the open routine for N_TTY is guaranteed never to return
 * an error.  This is because Linux will fall back to setting a line
 * to N_TTY if it can not switch to any other line discipline.
 *
 * Written by Theodore Ts'o, Copyright 1994.

-- https://elixir.bootlin.com/linux/v4.17/source/drivers/tty/n_tty.c [2500 lines]

[1] That said, real-world uses of serial ports tend not to involve physical terminals any more. One example use is to access a console on a simple device with no graphics hardware. We can connect the device to a PC which has a serial port, and a terminal emulator program. Instructions for doing so are available here.

Notice that the program on the PC which opens the serial port, will not want to be affected by tty device behaviour, such as Control-C -> interrupt signal. The program wants it to behave like a pty master, not like a pty slave. Such programs will effectively disable the common tty behaviour, using the equivalent of the command stty raw -echo.

If you look for ttyS0, it's possible you will find your PC has fully functioning serial hardware... despite having no serial port on the outside. Some desktop motherboards include pins for a serial port, which you can buy separately and connect with a ribbon cable. Some business laptops support docking stations with a serial port.

Some drivers may provide a serial port which behaves the same, but has a different name. ttyUSB0 on Linux is normally used for a USB device, which provides a serial port for PCs which do not have one built in.

/dev/tty1

tty1 is the first Virtual Terminal on a PC. This first tty, is the text console which shows messages at boot time. If you have a graphical boot with plymouth, pressing the Escape key will switch the VT back to text mode, allowing you to see the boot messages.

On most Linux PCs you can switch between at least 6 or 7 ttys. If you use a graphical interface, it will be running on a specific tty. Switching to a different tty may show you a text-based login prompt.

You might have noticed this numbering is inconsistent with the other types of tty :-). tty0 is reserved to refer to the currently active VT, leaving tty1 as the first VT.

To switch between VTs on a purely text-based install, use e.g. alt+f2 to switch to VT2. Graphical interfaces override these key combinations completely, and e.g. alt+f4 is usually reserved to close a window. Instead, graphical interfaces have developed a convention that ctrl+alt+f2 will switch to VT2, etc. This key combination is also works when switching from a text console.

How to check which device driver is used

$ ls -l /dev/ttyS0
crw-rw----. 1 root dialout 4, 64 Jun  9 13:17 /dev/ttyS0

^ c = character device     ^ 4, 64 is the major, minor
                             number of the device

$ ls -l /sys/dev/char/4:64
lrwxrwxrwx. 1 root root 0 Jun  9 14:17 /sys/dev/char/4:64 ->
 ../../devices/platform/serial8250/tty/ttyS0

This is a symbolic link file. It shows us that the canonical /sys path for this device, is /sys/devices/platform/serial8250/tty/ttyS0. It is a device of the tty class, and it is a child of /sys/devices/platform/serial8250/. We can find the name of the driver for the parent device:

$ ls -l /sys/devices/platform/serial8250/driver
lrwxrwxrwx. 1 root root 0 Jun  9 13:17 /sys/devices/platform/serial8250/driver ->
 ../../../bus/platform/drivers/serial8250

This serial driver doesn't seem to report itself as belonging to a loadable kernel module... because the driver is built in to my main kernel instead.

$ ls -l /sys/bus/platform/drivers/serial8250/module
ls: cannot access '/sys/bus/platform/drivers/serial8250/module': No such file or directory

$ grep 8250 /boot/config-`uname -r`
CONFIG_SERIAL_8250=y
...

$ ls -l /dev/tty1
crw--w----. 1 gdm tty 4, 1 Jun  9 13:18 /dev/tty1

$ ls -l /sys/dev/char/4:1
lrwxrwxrwx. 1 root root 0 Jun  9 15:57 /sys/dev/char/4:1 ->
 ../../devices/virtual/tty/tty1

Virtual Terminal devices are virtual: they are not registered as a child of a hardware device. We cannot ask what driver is bound to the hardware device, because there isn't one :-).


$ ls -l /dev/pts/0
crw--w----. 1 alan tty 136, 0 Jun  9 15:52 /dev/pts/0

$ ls -l /sys/dev/char/136:0
ls: cannot access '/sys/dev/char/136:0': No such file or directory

Linux devices are usually expected to be listed inside /sys. For non-virtual devices, this makes it possible to look up their device driver. However, ptys would be virtual: not a child of any hardware device. This means it is not possible to ask what driver is bound to their hardware device.

But I can't confirm this to you in the normal way, because pty slave devices are not listed inside /sys in the first place. This is a very special case in Linux. There is a filesystem type devpts, mounted at /dev/pts/, which provides pty device nodes on a modern Linux system. More recently, it is possible to have multiple independent devpts mounts, e.g. to run other Linux OS's in a containers with systemd-nspawn. Usually devices are identified by number, broken down into a major & minor number. However, I can see the same device number representing a completely independent pty device, depending on which devpts filesystem it was opened on. This special case caused some problems in 2016.

2

ssh does not allocate a TTY in every case. There is none if it is called with a command:

ssh user@host tty
    not a tty

This is OK because usually a command needs only stdin, stdout, and stderr.

The allocation of a tty can be enforced with -t or -tt.

3
  • Thank you. This helps with me understanding it bit by bit. Can you correct me if Im wrong of my understanding. I will comment here. As comment characters here are limited.
    – Chopnut
    Commented Jun 9, 2018 at 15:37
  • So all in all my understanding is when you SSH to a server, you are using a pseudo-tty to the server giving you a virtual terminal to manage the machine. This also gives you a interactive shell. When you spawn a connection to sshd, it mounts a /dev/pts/* dynamically. Making it look like a real terminal is connected or physical device. And you can use this to refer to your connection, by using tty command on your terminal. Pseudo because you are emulating tty functionality, instead of actually connected to the server physically.
    – Chopnut
    Commented Jun 9, 2018 at 15:38
  • @Chopnut That is correct. Commented Jun 9, 2018 at 16:47

Not the answer you're looking for? Browse other questions tagged .