According to my knowledge,
/dev/pts files are created for ssh or telnet sessions.
Nothing is stored in
/dev/pts. This filesystem lives purely in memory.
/dev/pts are pseudo-terminals (pty for short). Unix kernels have a generic notion of terminals. A terminal provides a way for applications to display output and to receive input through a terminal device. A process may have a controlling terminal — for a text mode application, this is how it interacts with the user.
Terminals can be either hardware terminals (“tty”, short for “teletype”) or pseudo-terminals (“pty”). Hardware terminals are connected over some interface such as a serial port (
ttyS0, …) or USB (
ttyUSB0, …) or over a PC screen and keyboard (
tty1, …). Pseudo-terminals are provided by a terminal emulator, which is an application. Some types of pseudo-terminals are:
- GUI applications such as xterm, gnome-terminal, konsole, … transform keyboard and mouse events into text input and display output graphically in some font.
- Multiplexer applications such as screen and tmux relay input and output from and to another terminal, to decouple text mode applications from the actual terminal.
- Remote shell applications such as sshd, telnetd, rlogind, … relay input and output between a remote terminal on the client and a pty on the server.
If a program opens a terminal for writing, the output from that program appears on the terminal. It is common to have several programs outputting to a terminal at the same time, though this can be confusing at times as there is no way to tell which part of the output came from which program. Background processes that try to write to their controlling terminal may be automatically suspended by a SIGTTOU signal.
If a program opens a terminal for reading, the input from the user is passed to that program. If multiple programs are reading from the same terminal, each character is routed independently to one of the programs; this is not recommended. Normally there is only a single program actively reading from the terminal at a given time; programs that try to read from their controlling terminal while they are not in the foreground are automatically suspended by a SIGTTIN signal.
To experiment, run
tty in a terminal to see what the terminal device is. Let's say it's
/dev/pts/42. In a shell in another terminal, run
echo hello >/dev/pts/42: the string
hello will be displayed on the other terminal. Now run
cat /dev/pts/42 and type in the other terminal. To kill that
cat command (which will make the other terminal hard to use), press Ctrl+C.
Writing to another terminal is occasionally useful to display a notification; for example the
write command does that. Reading from another terminal is not normally done.
The files in
/dev/pts are "pseudo-ttys". They're like named pipes to an extent, but they also imitate old serial-connection terminals, like VT-100s. Pseudo-ttys do the work of transferring bytes from keyboard to program, and from program to output device, which sounds simple. But that answers your explicity question: the kernel stores nothing in
/dev/pts/0 for example. Only streams of bytes from stdout of a program connected to the pseudo-tty goes in, and programs whose stdin is connected to the same pseudo-tty read those bytes.
Pseudo-ttys also put a layer of indirection into those streams of bytes. The kernel can inspect bytes for special values like "Control-C" or "Control-D" or "Control-U" (which are all configurable, see
man stty) and send a SIGINT, set end-of-file on stdin, or erase a line on the input. There's also a buffering function in there somewhere, so my "stores nothing" is somewhat wrong, but only by a few kilobytes.
The kernel can inspect byte values on output and do things like turn a newline (ASCII linefeed, LF or
"\n") into two bytes, carriage-return and linefeed (CRLF or
"\r\n"), or whatever bytes a serial terminal hardware requires. The indirection of a pseudo-tty allows independence from hardware.
Pseudo-ttys also allow all the "set baud rate", "set parity" and so forth
ioctl() system calls, and probably do nothing with them. This lets programs that were written back in the day of VT-100s, ADM-3 and Wyse whatevers keep working without erroring out. Software, the pseudo-ttys device driver, acts like hardware.
Pseudo-ttys may be used by
telnet, but they're also used between
a terminal emulator (like
rxvt) and the shell that typically runs inside the xterm.
Linux and a lot of Unixes have pseudo-ttys. Plan 9 does not. Pseudo-ttys are a little bit of a relic, left over from the days of serial-cable connected hardware terminals.
/dev/ is a special directory for device files. These are abstractions, they are not real files on disk. The directory is populated at boot and subject to change to reflect existing device interfaces, which are created and destroyed by the kernel and a userspace daemon,
Many of the devices so represented are virtual. This includes the entries in
/dev/pts, which are console devices. This is why one is created for remote sessions; they are also created when you open a local GUI terminal.
You can open them as files, although it's not of much use value. To get the
/dev/pts node your shell is connected, use
> tty /dev/pts/4
Now switch to some other console and try:
> echo "duck!" > /dev/pts/4
Clever. Now try:
> cat /dev/pts/4
Then try and use the shell at /dev/pts/4. You're stuck until you exit the
cat on the other side, but most of what you type on pts/4 will pass through (e.g. trying "hello world" I ended up with
hl on pts/4 and
ello word on the
My guess here is that the device is taking input from the shell, and outputting it via the system, which is how stuff ends up on the screen -- the shell isn't dealing with hardware, the system is. Try
strace bash (and have a look at
man strace if you don't know what it is); you get a preliminary flurry of calls as bash starts up. Now start hitting keys:
read(0, "h", 1) = 1 rt_sigprocmask(SIG_BLOCK, [INT], , 8) = 0 write(2, "h", 1h) = 1 rt_sigprocmask(SIG_SETMASK, , NULL, 8) = 0 rt_sigprocmask(SIG_BLOCK, NULL, , 8) = 0 read(0, "e", 1) = 1 rt_sigprocmask(SIG_BLOCK, [INT], , 8) = 0 write(2, "e", 1e) = 1 rt_sigprocmask(SIG_SETMASK, , NULL, 8) = 0 rt_sigprocmask(SIG_BLOCK, NULL, , 8) = 0 read(0, "y", 1) = 1 rt_sigprocmask(SIG_BLOCK, [INT], , 8) = 0 write(2, "y", 1y) = 1 rt_sigprocmask(SIG_SETMASK, , NULL, 8) = 0 rt_sigprocmask(SIG_BLOCK, NULL, , 8) = 0
For every letter typed there's a read from standard input and a write to standard out. But what's the shell's standard out connected to? Now try
strace on your GUI terminal -- you'll have to figure out the name if you don't know it, e.g. on KDE it's
konsole, and GNOME has the
gnome-terminal, I believe. The output from that
strace is probably more cryptic -- mine has a lot of
recvfrom(). I don't see any writes, but if you now pull the
cat trick from another terminal, you'll notice when you type, the key strokes that get read by cat cause no response at all in the strace output -- the terminal isn't recieving them. So the GUI terminal app and cat are competing to read from the same device, which the shell is outputing into.