 Throughout the 1960s and 1970s, most human interaction with computers was done through what are called terminals. A terminal device is a piece of hardware that combines a keyboard with some kind of character display, which in the early days in the 1960s was usually some kind of printer that would print out characters line by line. Or later in the 1970s it was usually a video console, but the video console was not capable of displaying arbitrary graphics, it could only display text characters. And these text characters could only be displayed in a fixed grid. So you wouldn't have arbitrarily positioned characters anywhere on screen. And also these devices usually only had one display font and one display color. So the idea of a terminal is that when we hook it up to a computer, the computer can then send text characters in sequence to the terminal, which get displayed character by character on the screen. And when the user sitting at the keyboard types anything, a character is sent from the terminal to the computer. So there's a neat symmetry there. A strict sequence of characters flows from the computer to the terminal and vice versa. As you can probably guess, the text going in both directions was almost always ASCII text. In Unix systems, a process may communicate with the terminal through a file representing that terminal, a terminal character device file. When a process writes to a terminal character device file, that's putting data in the output buffer of the device file, which then is going to get sent out by the operating system to the terminal device associated with that character device file. Conversely, when the user at the keyboard types something, that data gets sent from the terminal to the computer, and then the operating system will take that data and put it in the input buffer of the associated character device file. And then the process then may read from the character device file to get that data. So again, be clear that the terminal is a totally dumb device. When you see text displayed on the terminal, that's something that's coming from processes running on the attached computer. The only exception to this is that with a terminal character device file, we can turn on a mode called echoing. When a terminal character device operates in the echoing mode, then any input it receives from the terminal, it will then immediately echo back out to the terminal so that it gets displayed on screen. In practice, what this means is that when echoing is on and the user types something on the keyboard, then whatever key they type, they will then immediately see appear on their screen. Just be clear that the terminal doesn't have an echoing mode. It's the terminal character device file that has an echoing mode. So the data is actually being sent from the terminal and then immediately back to the terminal. As the years went on, some terminals began to add more features, like for example some terminals featured the ability to change text color. The way this would work is that you would set the terminal's mode, like say what color it's printing, by sending it an escape sequence, that is a sequence of characters beginning with the ASCII escape character, which is ASCII code 27. By sending escape sequences to the terminal, we can set its modes and thereby change its behavior, like say what color of text gets displayed, or maybe say how many lines of text get displayed on the screen. Things like that. Now the trouble with this arrangement is that early on the escape sequences weren't really standardized. Every manufacturer did their own thing, so what you would need to do to control one terminal differed from what you would do to control another. In time though, eventually a standard did more or less emerge. Unfortunately, the end result of this process ended up quite messy. So if you look into the details of terminals and want to know exactly what you can do with escape codes, it's all surprisingly complicated, so that's a whole area we're going to alight over. We'll just think of terminals as simply displaying a sequence of text and sending back to the computer whatever gets typed at the keyboard. End of story. However, I do mention these capabilities because you will likely interact with some programs that when they do use a terminal they seem to do things that otherwise aren't possible, like say changing the color of the text. In Unix, we have this convention whereby processes, when they are started, expect to inherit from their parent two open file descriptors, 0 and 1. File descriptor 0 we call standard in, abbreviated as STDIN, and file descriptor 1 we call standard out, abbreviated as STDOUT. In the usual case, processes expect standard in to be a file descriptor open for reading a terminal character device file, and standard out is expected to be open for writing that same terminal character device file. In practice what this means is that when a program wishes to read input from a terminal, it reads from standard in, its file descriptor 0, and when a program wishes to display text on that same terminal, it writes data to its standard out. Now be clear, this is what processes expect to inherit from their parent. Recall that when a process forks in Unix, the file descriptors from the parent get copied to the child, so it has all the same open file descriptors. So the convention in Unix is that when programs wish to interact with a terminal, they usually don't locate an appropriate terminal themselves, they just expect to inherit these file descriptors already open to an appropriate terminal. Now you may be wondering why do we have two separate file descriptors, one for reading, one for writing? Well first off, something I didn't explicitly mention in the coverage of Unix system calls is that when you open a file, you can open it in a mode such that only reading is allowed or only writing is allowed, that is possible. Still, that doesn't explain why we have two separate file descriptors when we could just get away with one for both reading and writing. This is something that we'll be explained a bit later when we talk about what's called redirection. Something else you may be wondering about at this point is, hey, my computer doesn't have a terminal, I have a proper monitor that's a full graphical display, and on that display I have a graphical user interface, which I interact with through a mouse and keyboard, but those are totally separate devices. I don't have a keyboard bundled together with a monitor as a single unit called a terminal. So what the hell is going on here? We don't seem to have any terminal in a modern system. The answer is that while hardware terminals are a thing of the past, what we do today is we imitate them, we emulate them in software. We have what are called terminal emulators. This window here, for example, is a terminal emulator program. To explain what's going on here, we actually first have to talk about the graphical user interface in Linux in general. In Microsoft Windows, the graphical user interface is a part of the operating system itself. It's tangled up with all the other operating system code. In Unix systems, in contrast, including in today's Linux, the graphical user interface runs basically as an ordinary program. It's not a component of the Linux kernel at all, in fact. When running a graphical environment in Linux, the program which controls your screen and which gets the input directly from the mouse and the keyboard is called an X-Windows system server. When you then run a program which has a graphical interface, like, say, the Firefox web browser or the GIMP image editing program, these programs send the content of their windows to the X-Windows server, and then the X-Windows server is responsible for actually displaying those windows on the screen. When a user then, say, clicks on one of these windows, that mouse data is read by the X-Windows server, which then sends it on to the appropriate program. Usually in this setup, we also have programs running responsible for, say, drawing all of the interface elements of the desktop, like, say, the desktop wallpaper and all the icons on the desktop, and also whatever interface elements you have for task switching and starting new programs. One program commonly used for that purpose is a program called Genome Panel, which is part of the whole Genome desktop, which is a whole collection of programs in libraries for creating a graphical user environment on Linux. And then additionally with an X-Windows server, you need what's called a Window Manager, which is a program which is responsible for drawing the borders around windows and also keeping track of the positions of the windows on screen and moving them around and resizing them and such. The Window Manager included with the Genome desktop is called Metacity. So, notice that Genome Panel and the Metacity Window Manager are both otherwise ordinary processes that talk to the X-Windows server. So, they actually talk to the X-Windows server using the same X protocol that all other programs like Firefox and Gimp use. Be clear that the X-Windows system is defined really by a protocol, the X protocol, and there are a few different X-Windows servers available. The most widely one used though is called Xorg. If you have a Linux system today, most likely it's using Xorg. Also be clear that though we call it a server, the X-Windows server is usually talking to programs running on the very same machine. So, when I run Firefox on my system and I see it displayed on my screen, then it's connected to the X-Windows server running on my same system. Part of the reason though for this client server architecture is that it is possible to run a program like Firefox and have it talk to an X-Windows server running on a different system. So, if we run say Firefox on your system, but have it connect to the X-Windows server running on my system, then I will be seeing that Firefox window displayed on my screen and I can interact with it just like it were a program running locally on my system, but in fact it's actually running on your system. This is an example of a feature called network transparency. And the idea going back say 30 years ago when the system was first devised is that we would have a bunch of what are called thin clients computers which don't have to be very powerful yet simply just display programs that are actually being run on other systems. It's an arrangement actually very much like the idea with having a bunch of terminals all connected to one system where all the code is really running on that computer system and the terminals themselves can be very thin clients. They don't have to have much smarts in them. So now getting back to terminals, a terminal emulator is a program which sends window content to an X-Windows server to display on screen as a graphical window and it also receives textual input from the keyboard and also perhaps mouse clicks from the X-Windows server. The question now is how do we get other programs to read and write from the terminal emulator as if it were just like a regular terminal, an actual terminal character device file. Well the way this is achieved is with another mechanism introduced in Unix systems called pseudo-terminal device files. These pseudo-terminal files actually called in pairs, one the slave, one the master and the program which is imitating a terminal, it reads and writes from the master and the program which actually wishes to use this fake terminal reads and writes from the slave. So for example I open up my terminal emulator in X-Windows and then I click in the window and say start to type something. That text data I type is sent from the X-Windows server to the terminal emulator which then writes it to the master pseudo-terminal character device file. The operating system then copies that data over into the associated slave to be read by a process. So be clear that pseudo-terminals are in a sense a fiction. They represent terminal devices which don't actually exist. In fact it is the responsibility of the terminal emulator when it starts to ask the operating system to allocate a new pseudo-terminal just for its own purposes. You generally want each terminal emulator to have its own unique pseudo-terminal master slave pair. In the context of Linux you'll hear talk about a feature called virtual consoles. On a Linux system if you hold down control and alt and hit F1 or F2 or F3 or F4 up through F8 it'll switch you to another virtual console. So the X-Windows system by default actually runs as usually the 6th, 7th or 8th virtual console and so you switch to your X-Windows server by holding down control alt and hitting F7 or sometimes F8. If you hold down control alt and hit F1 that switches you to a different virtual console one without an X-Windows server but rather just a terminal. So a virtual console sort of acts like a terminal emulator. It's just that it's implemented inside the Linux kernel itself. And though these virtual consoles by default simply run with a terminal command line you can in a virtual console launch an X-Windows server and thereby turning that virtual console into a proper GUI desktop. So what typically happens in most Linux systems is upon boot up it launches an X-Windows server in one of the virtual consoles and then switches to that virtual console. So the purpose of the system is it's the way Linux gives us a terminal even if we don't have an X-Windows server and also it allows us to in case something goes wrong with our X-Windows server we can just switch over to another virtual console and use the command line there. Assuming you have an X-Windows server in which nothing ever goes wrong you probably don't ever need to use virtual consoles but it's there as a nice fallback feature basically. Just remember though if you accidentally for whatever reason switch away from your X-Windows server because you hit CTRL ALT and say like F3 just remember you can get back by hitting CTRL ALT and F7 or sometimes F8 or F6 it depends on your Linux distribution. The last thing to say about terminals here is where you will find the character device files. This is something that may vary depending upon which which Unix you're using and if you're using Linux which distribution but on my Ubuntu system for example if I look in slash dev I will see a directory called pts which stands for pseudo terminal slaves and in this directory I find all of the pseudo terminal slaves that are currently being used and then in the dev directory itself you'll find a file called tty this is a special kind of special file it doesn't represent a character device when a program opens the slash dev slash tty file what they get back is a file descriptor for the so-called controlling terminal that is the terminal that is associated with their process which is a concept we'll talk more about later on but the point here is that when you open this file there's some special magic going on where what you get back for a file descriptor depends upon which process is opening the file and finally also in slash dev you will see a number of files starting with tty and then a number these are character device files representing the virtual consoles and again remember that virtual consoles are a Linux specific feature but in any case if say you open and write to slash dev slash tty1 what you're doing is you are writing to the terminal of the first virtual console I believe actually these virtual consoles are numbered starting from 1 rather than 0 if you're wondering what tty stands for well that's a historical mechanism back in the 50s 60s and 70s we had these devices called teletype machines that is over a communication line you'd have two devices on either end you type on one end and the character is printed out on the other end so these were actually predecessors to hardware terminals and for whatever reason that's the name that the creators of Unix went with even though it didn't really even make sense at the time and certainly doesn't make sense as a given name 40 years later but that's what we're stuck with when people talk about tty's they're talking about terminals