Yabage

Yet Another Blog About Geek Experiments

Jul 8, 2016 - 8 minute read - Comments - Linux

TTY: under the hood

It all started with the simple instruction: -t flag assigns a pseudo-tty or terminal inside the new container… and a moment of puzzlement… What is exactly a pseudo TTY? What does it mean to attach or detach a process from it?

gnome-terminal

Beware my friend, for this article will lead you into the depths of forgotten history, guiding you through arcane kernel mechanisms. But persevere and the pure light of knowledge will shine upon you by the end of this journey.

The origin of the myth: the Teletype

When you go all Neo from Matrix by popping up a fancy green terminal to impress your friends around (what do you mean, “nobody does that”?), you are actually playing with the legacy of a very old device that few have ever seen in their lives: the Teletype.

A legendary object

teletype-model-28

Do you see this beauty in the picture? That’s a Teletype. A model 28 by Teletype Corporation to be precise. However there are countless models built by many different forgotten companies. The history of teletypes finds its roots in initial experimentation during the late 1800s, but truly began in the 1920s approaching an end in the 70s when fax technology began to be good enough to replace them.

A teletype is basically a machine that sends letters you typed on the keyboard through electric signals to another machine or network, and prints (literally prints, on paper!) letters received through the reception cable. Obviously, the different models evolved with time to offer more features and performance possibilites:

  • Use of Multiplex signal, in order to allow the usage of one physical cable to send and receive messages
  • Support of punched card to send prepared messages at full speed without the need of typing them
  • Use of video screen (you’re welcome, trees!)
  • Increase of speed (from 50 baud to 150000 baud)

At the time this type of machine was the best way to transmit data in fast and reliable way.

Stop your boring old gibberish… Why the heck are you telling me about this?

Because instead of building new devices to interact with computers, pragmatic people at the time decided to reuse existing teletypes to connect to them. Listen very carefully, I’m not talking here about the Personal Computer (PC) you are familiar with. I’m talking about a big, massive machine located in its own dedicated room to which you had no access if you were not cool enough, and where you had to send commands from the teletype and read the output printed back on the device.

mainframe2

Actually, one terminal was directly connected to the machine within the same room : the console. Man, I can’t tell you about the kudos and props at being the lucky one behind the console. Well, I can’t because I’m not that old, but I’m sure that it should have been a big deal back then.

Anyway, by now we’ve realized a few things: for instance when using a terminal it’s nice to see what you are typing. So what about asking the computer to echo back to us what it received, so that it is printed from our teletype? And what about erasing with backspace what has been typed? Yep, the computer at the end of the cable should take care of that for us, we’re only using a dummy Teletype after all.

Under the hood

Here is a diagram of how a teletype interacted with a computer:

teletype-mainframe-workflow

  1. Each machine is -conceptually or physically- connected via two cables: one to send instructions to the computer and one to receive output from the computer.
  2. These cables are connected to the computer through a serial cable plugged into an Universal Asynchronous Receiver and Transmitter (UART) that transforms the asynchronous flow of data into bytes words.
  3. The computer has an UART driver to read for the hardware device.
  4. The sequence of characters is passed to the line discipline. The line discipline will be in charge of converting special characters (like end of line, backspaces), and echoing (reprinting) what has been received back to the teletype, so that the user can visualize what he/she types.
  5. The flow of instruction is passed to the TTY driver, that then passes them to the foreground processes for the session associated with this TTY. Indeed, as a user, you can execute several processes in parallel, but only interact with one at a time, letting the others working (or waiting) in the background.

The whole stack as defined above is called a TTY device, and several ones can exist at the same time for a computer. So different line disciplines can be set for different devices, each TTY having its own foreground job, etc.

From the Teletype to the Terminal

Besides unpredictable haircuts and memorable rythms, the 80s have also brought us what they called intelligent terminals. Slowly, terminals evolved to become badass devices, with screen, memory, and even small processors to manage specific features on their side.

terminal_vt100

They started to look like your current PC desktop. But Beware they are in no way comparable! They are still dummy objects, despite their name. They do not compute things on their own: managing fancy colors and having a fast refresh frequency is far from being even close to a computer. It’s the 80s after all, it’s hard to call anything from that period of time smart…

These devices worked in the same way as teletypes, but also introduced some new features that needed supported from the software to be managed correctly (colors, special movements, etc).

Wake up Neo, it is all virtual

The massive set of wardrobes that used to constitute a computer gradually shrunk in size to a nice little box that you could fit under your desk. And there were no more endless terminals connected to it, only one monitor and one keyboard. Nevertheless, your current Linux machine keeps emulating several (usually 7 by default) terminals connected to your hardware. But to protect you from the effort of getting up and physically going to another chair, the OS allows you to switch from one terminal to another by a simple press of keys (Ctrl+Alt+F1 to Ctrl+Alt+F7). This feature is called virtual terminals, and is represented by the files /dev/tty1 to /dev/tty7. You can see any of these files as a duplex cable connected to a terminal. If you write to it, you send the information to be printed to the terminal. If you read from it, you receive what is typed from the terminal (try it, it works).

virtual-terminal-workflow

When you switch from one virtual terminal to another, the OS detaches your seat (a set of input and output devices like monitor, keyboard, mouse, etc. representing the hardware interface with the user) from the first virtual terminal and attaches it to the one requested by your shortcut. The processes from the first virtual terminals keep running, writing and reading from their virtual tty file (dev/tty1 for instance), but this file won’t receive any event from the seat and won’t be able to send output to the seat. The information will be buffered instead (until you reattach your seat to this terminal), making the switch between sessions transparent for running jobs.

I know no master

matrix-operator

Yet I imagine only a few of you are actually using the virtual tty just mentioned. You are usually using a terminal console application launched from a graphic environment that is itself launched from a virtual terminal (yep, take a deep breath and read that again).

So when you launch your favorite terminal emulator like xterm or gnome-terminal, how do the processes know where to write the output, and where to get the input from?

ptmx-pts-workflow

Basically, when you launch a terminal within a graphic environment like this, it will spawn its own equivalent of /dev/ttyX: the terminal emulator will open a special file located in /dev/ptmx, called the master side of the pts, will work some magic with ioctl function, which will create a slave side of the pts in /dev/pts/X.

The processes running in the session will be attached to this file, that will behave like any file from the virtual terminal, except that there is no attachment to a seat: you can open several terminal emulator windows at the same time and display them side by side, having different sessions running in parallel.

Going further

We could dig into the topic endlessly, discussing the function ioctl, detailing how the kernel handles the session, expressing our endless admiration for the great 70s look of the DEC VT05 terminal… But we should keep some for further articles, and there are anyway plenty of great resources already available if you are interested. To share a few:

I realize I took a lot of shortcuts in this article and it would be natural that some part suggest greater depths to be explored. So if you have any question or need further details, please leave a comment, I will try my best to provide a clear answer!