1
  1. The /dev/ptmx is UNIX 98 master clone device Source
  2. When a process opens /dev/ptmx, it gets a file descriptor for a pseudoterminal master (PTM), and a pseudoterminal slave (PTS) device is created in the /dev/pts directory Source. There are no nodes in the file system for master devices Source.
  3. Data written to the slave is presented on the master descriptor as input. Data written to the master is presented to the slave as input Source.
  4. In Unix and related computer operating systems, a file descriptor (FD, less frequently fildes) is an abstract indicator (handle) used to access a file or other input/output resource, such as a pipe or network socket Source.

Conclusion:

  1. /dev/ptmx is just kind of a "mold" to clone masters (file descriptor actually).
  2. A pseudoterminal is a pair of virtual devices that provide a bidirectional communication. One end of the channel is a file decriptor (Master) and the other is a /dev/pts/n device (Slave).
  3. There is no PTM device but only a file descriptor.
  4. A file descriptor is used to access a file or resource.

Questions :

  1. Where is located the PTM resource that the file descriptor handle?
  2. Why do we call PTM master "device"? Since there is no entry in /dev for it.
  3. Can a modified program like SSHD communicate with PTS directly without the PTM in the middle?
2
  • When a process opens /dev/ptmx, it gets a file descriptor for a pseudoterminal slave (PTS) device created in the /dev/pts directory. I only take away this part: "...master (PTM), and a pseudoterminal..." and it is correct.
    – user373503
    Commented Oct 15, 2019 at 6:11
  • As the code lines in my answer show, the open("/dev/ptmx", ...) line is just one step in the whole setup. This explains the subtle differences in our descriptions.
    – user373503
    Commented Oct 15, 2019 at 6:14

2 Answers 2

5

To understand how pseudoterminals work, you must consider them as an abstractization of real physical terminals. Nowadays, the most commonly seen physical terminals are the Linux virtual consoles, but back in the day real physical terminals were extremely common, and quite often the only part of a computer system a user saw in their daily work.

A real physical terminal has two very different sides (or "aspects" if you prefer):

  • An "outer" side, where the user sits. This side has a keyboard, on which the user types characters, and a screen, on which the user sees computer output. In the pseudoterminal abstraction, this is the "master" side.

  • An "inner" side, represented by a character device in the operating system. In the pseudoterminal abstraction, this is the "slave" side.

Between the "outer" side of a physical terminal and the "inner" character device used by programs to communicate with the user there is an entire series of processing; the terminal hardware itself updates the screen, the operating system may buffer user keystrokes and perform line editing etc.

A Digital Equipment Corporation VT220 terminal

A Digital Equipment Corporation VT220 terminal. You are looking at its "front" side. With a pseudoterminal, this is represented by the "master" side. Picture from Wikimedia.

  1. Where are located the PTM resource that the file descriptor handle?

    They are located in kernel memory. When a process opens /dev/ptmx the kernel creates a new pseudoterminal consisting of a master side and a slave side; the master side belongs to the process which created it, so it does not need an entry in /dev; the slave side can be opened by any process which wants to communicate with a terminal, and thus needs an entry in /dev.

  2. Why do we call PTM master "device"? Since there is no entry in /dev for it.

    We do not usually call it a device. We usually call it the master side of a pseudoterminal. But yes, it is much more like a character device than like a regular file. For example, the process which holds it cannot seek to a previous location -- it can only read new bytes or write new bytes.

  3. Can a modified program like SSHD communicate with PTS directly without the PTM in the middle?

    Sshd does not communicate with the slave side of the pseudoterminal. Sshd holds the master side of the pseudoterminal; the slave side is used by the process (e.g., a shell) spawned by Sshd.

    Sshd works like this:

    • When a login request comes over the network and the user is authenticated, Sshd creates a new pseudoterminal; it holds the master side, and then spawn a process as required by the remote user (usually a shell), giving it the slave side of the pseudoterminal as standard input, standard output and standard error.

    • Characters received from the network are written by Sshd to the master side of the pseudoterminal; this emulates a user typing on the keyboard. The kernel processes (or not) this stream of characters. The process (e.g., a shell) which has the slave side of the pseudoterminal receives them as if it was communicating with a real terminal.

    • In between the master and the slave side there is the operating system kernel, which may perform some processing or not, depending on the status of the slave side. See line discipline, and the manual pages of stty(1) and ioctl(2) (especially as applied to terminals or the slave side of pseudoterminals).

 _______             ______       ______       ______       _____       ______
(       ) bytes in  |      |     |      |     |      |     |     |     | Bash |
(Network)---------->| Sshd |---->|Master|---->|  OS  |---->|Slave|---->|  Vi  |
(       )<----------|      |<----| PTY  |<----|kernel|<----| PTY |<----| Less |
(_______) bytes out |______|     |______|     |______|     |_____|     |______|

 _______           _____      ______      ______      _____      _____      _______
<       > Events  |     |    |      |    |      |    |     |    |     |    (       )
<  GUI  >-------->|Xterm|--->|Master|--->|  OS  |--->|Slave|--->| Ssh |--->(Network)
<       ><--------|     |<---| PTY  |<---|kernel|<---| PTY |<---|     |<---(       )
<_______> Drawing |_____|    |______|    |______|    |_____|    |_____|    (_______)
10
  • They are located in kernel memory. Is there any bash command to see it?
    – etchttpd
    Commented Oct 16, 2019 at 19:49
  • It small integer returned by open(2) is an index in the file table of the process. The entire file table is part of the kernel data structures which describe the process. I'm not sure what it is what you want to see.
    – AlexP
    Commented Oct 16, 2019 at 20:03
  • Characters received from the network are written by Sshd to the master side of the pseudoterminal. How can a process (SSHD) write on file descriptor? As I know, the latter is used by the OS to access /dev/ptmx. Does it mean the SSHD writes on /dev/ptmx?
    – etchttpd
    Commented Oct 16, 2019 at 20:06
  • Sshd calls open("/dev/ptmx", O_RDWR). It gets back a file descriptor. It then uses that file descriptor in calls to read() and write(). (You do know that a file descriptor is a small integer, and that the basic I/O system calls take that number as an argument, yes?) (And no, I'm not sure that Sshd opens /dev/ptmx; there are also other ways to open the master side of a PTY. Many programs are written to use the older way, now called BSD-style PTYs.)
    – AlexP
    Commented Oct 16, 2019 at 20:10
  • You do know that a file descriptor is a small integer, and that the basic I/O system calls take that number as an argument, yes? Yes, but this small integer is used like "an alias" to access the real resource for reading and writing and not used to access the file descriptor itself. The latter is not the final resource.
    – etchttpd
    Commented Oct 16, 2019 at 20:26
0

When I go to the top of this oracle link I find "preface":

The STREAMS Programming Guide describes how to use STREAMS in designing and implementing applications and STREAMS modules and drivers, for architectures that conform to the SolarisTM 7 DDI/DDK.

Solaris7 was from 1998-2010. And still this oracle/solaris link explains the setup in well commented C code:

fdm = open("/dev/ptmx", O_RDWR);  /* open master */
grantpt(fdm);                     /* change permission of slave */
unlockpt(fdm);                    /* unlock slave */
slavename = ptsname(fdm);         /* get name of slave */
fds = open(slavename, O_RDWR);    /* open slave */

Isolating these two lines, where a char dev is opened:

fdm = open("/dev/ptmx", O_RDWR);    /* open master */
fds = open( slavename,  O_RDWR);    /* open slave */

you see the symmetry...only difference is:

  • fdm uses string "/dev/ptmx"
  • fds uses variable slavename (containing a string like...?(bonus Q))

Of course the link is done here: slavename = ptsname(fdm). In plain english: return name of slave belonging to fd returned by opening master device. Nobody said it is trivial.

Or is this a typo? No! It's ptsname() you need to find out which number/name (/dev/pts/8, /dev/pts/17, ...) the master side has assigned to the "ticket" you are holding (that fdm "handlle").

And man ptsname:

The ptsname() function returns the name of the slave pseudoterminal device corresponding to the master referred to by fd.

Twice you open a pseudo device to get a filedescriptor "fd_", but first fdm is "only" to get a fds. And then fds is used to r/w to that new slave side device.

Reminds of a hotel guest getting the key to his private room from a public room first.


But I would never have realized all this without that clarifying picture of a real physical VT of the original inventor of colored terminals supporting even sound.

You must log in to answer this question.

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