On the lowest level, most Linux system interactions use a text interface. There are many mechanisms to enable the system to provide as much information as possible at the users’ fingertips. Even before the use of a complex graphical user interface (GUI) with convenient windows and controls, there were command-line interface (CLI) tools to leverage these mechanisms.
In this tutorial, we’ll clarify the Linux terms TTY and PTY. First, we go through a hierarchy of terminals. Next, we explore what a TTY is. After that, we get into PTYs. Finally, we look at terminal emulators and other PTY applications.
We tested the code in this tutorial on Debian 11 (Bullseye) with GNU Bash 5.1.4. It should work in most POSIX-compliant environments.
2. Terminals, Terminals, Terminals
What is a terminal? Indeed, we already delved deep into what a terminal is and how it came to be. In short, terminals are ways to provide input to and get output from a system.
Now, let’s go through the basic terminal abstractions from the lowest to the highest level:
- Hardware terminal, i.e., teletypewriters, hard-copy, video display unit (VDU), and others
- Software terminal, i.e., virtual TeleTYpe (TTY), which is the main interface of a Linux operating system
- Software pseudo-terminal, i.e., PseudoTeletYpe (PTY), which allows emulating a TTY
- Software terminal emulator, based on the previous ideas, but usually enhancing them via the actual or CLI-emulated GUI
Of course, we’ll skip the hardware terminals, as they don’t necessarily relate to Linux. On the other hand, terminal emulators don’t actually introduce new ideas on the lower level, instead adding features more for convenience.
Let’s start from the bottom up.
3. What is a TTY?
TTY is an acronym for teletype or teletypewriter. In essence, TTYs are devices that enable typing (type, typewriter) from a distance (tele).
In a modern operating system (OS), the concept applies directly. Linux uses a device file to represent a virtual TTY, which enables interaction with the OS by handling input (usually a keyboard) and output (usually a screen).
While Linux systems can have multiple TTYs, their number is usually limited by the configuration. Actually, we can change this by modifying /etc/init/tty*.conf, /etc/securetty, /etc/systemd/logind.conf, or similar configuration files depending on the Linux distribution.
In fact, the default number of TTYs is commonly seven. However, in more recent distributions, there are many more:
$ find /dev -regex '.*/tty[0-9]+' /dev/tty63 /dev/tty62 [...] /dev/tty1 /dev/tty0
$ find /sys/class/tty/ | sort -V /sys/class/tty/ /sys/class/tty/console /sys/class/tty/ptmx /sys/class/tty/tty /sys/class/tty/tty0 /sys/class/tty/tty1 [...] /sys/class/tty/tty63 /sys/class/tty/ttyS0 /sys/class/tty/ttyS1 /sys/class/tty/ttyS2 /sys/class/tty/ttyS3
In this case, we see several other related devices:
In fact, we have already discussed the first two. Importantly, in recent Linux distributions, systemd spawns the [email protected], which generates, provides, and monitors /dev/tty* devices. This way, we can use a command like the following to reset a problematic terminal:
$ systemctl restart [email protected]
Furthermore, device files such as /dev/ttyS#, /dev/ttyUSB#, and similar can be handled by [email protected] and are meant to be channels for communication with COM, USB, and other devices.
The last device type is /dev/ptmx, which we’ll delve into next. Pure TTYs do allow communication, but they don’t provide much flexibility because at least one end of the TTY is (a keyboard, mouse, or another input device via) the kernel. On the other hand, a PTY can be linked to any application on both ends.
4. What is a PTY?
PTY is an acronym for pseudo-TTY. The name PTY stems from the fact that it behaves like a TTY but for any two endpoints. This minor difference enables multiple PTYs to co-exist within the context of the same TTY.
In fact, both sides of a PTY have a name:
- slave, /dev/pts, represented by a file in /dev/pts/#
- master, ptm, which only exists as a file descriptor of the process, which requests a PTY
This is where /dev/ptmx, the pseudo-terminal multiplexor device, comes in. Effectively, there are several steps to establish and use a PTY:
- A process opens /dev/ptmx
- The OS returns a master ptm file descriptor
- The OS creates a corresponding /dev/pts/# slave pseudo-device
- From this point, slave input goes to the master, while master input goes to the slave
To know the correspondence between a master and slave, we can call the ptsname function.
Basically, a PTY enables bi-directional communication similar to pipes. Unlike pipes, it provides a terminal interface to any process that requires it.
What do we do with this power?
5. Terminal Emulators
In essence, a terminal emulator requests as many PTYs as it needs from the OS, often presenting them as tabs or windows in the GUI. Let’s follow how that works and how it links to the concepts of TTY and PTY.
First, Linux boots into a TTY. We can confirm this and the current terminal backend in general via the tty command:
$ tty /dev/tty1
From there, we can open any terminal emulator application and check its terminal:
$ tty /dev/pts/0
The output shows we’re in the first pseudo-TTY slave.
In fact, we can even skip the GUI step, as there are terminal emulators in the CLI.
6. PTY Applications
Naturally, we use PTYs to create more terminals inside of our existing terminals. Why do that? One reason is to avoid overloading TTYs. Another is pure convenience.
6.1. GUI in the CLI
Both of these applications are terminal multiplexors, which more or less emulate a GUI in the CLI:
$ tty $ tty /dev/pts/0 /dev/pts/1 0 bash 1 bash $ tty $ tty /dev/pts/2 /dev/pts/3 2 bash 3 bash
Of course, both screen (shown above) and tmux provide many other enhancements. For example, terminal multiplexors support long-running processes without relying on jobs in a terminal we don’t need to touch for anything else.
Often, this ability comes into play when using the system remotely.
6.2. Remote Connections
Since they are applications and not hardware, a PTY provides their terminal connection:
$ ssh ssh.example.com $ tty /dev/pts/0
Here, we see that tty returns the pseudo-terminal slave number responsible for servicing the SSH session.
In this article, we looked at TTYs, PTYs, and the differences between them. Basically, both are bi-directional channels, but a TTY is a main OS terminal, while PTYs can be allocated on request.
In conclusion, a PTY is very similar to a TTY but allows for more flexibility, enabling the development of convenient userland applications and protocols.