Help with pipes, buffering and pseudoterminals

Nobody nobody at nowhere.invalid
Fri Apr 10 16:18:32 CEST 2015


On Mon, 06 Apr 2015 21:13:41 -0700, Daniel Ellis wrote:

> As for the question ptys and C, no, I have no experience in that area.
> I've read a bit on the master/slave stuff, but I'm still finding it
> confusing.  The manpage for pty states that it creates a "pair" of virtual
> devices, one master and one slave.  It doesn't seem like these are simple
> file descriptors for stdin, stdout, and stderr, given that there is only
> one for the master and one for the slave, so I'm really not understanding
> what it means for these devices to be created.

A pseudo-tty (pty) is a pair of devices: master and slave. Opening
either of these devices will return a file descriptor. The devices can be
(and usually are) opened read-write (O_RDWR), yielding a descriptor which
can be both read and written to (unlike a pipe).

Typical usage is that the parent process opens the master device while the
child process opens the slave device and dup2()s the descriptor to
descriptors 0,1,2 (the child process is typically the leader of a new
session, meaning that the slave will become its controlling terminal). The
child then exec()s some program.

Whatever data the parent writes to the master, the child will receive when
it reads from the slave, and vice versa. So the pair of devices
collectively behave somewhat like a socket pair or a bidirectional pipe.
Except that the slave side "looks like" a tty, i.e. isatty() will return
1, tcsetattr() etc will work on it, input characters (sent from master to
slave) will be processed (backspace, Ctrl-C, Ctrl-Z, etc), and so on.

The main use for a pseudo-tty is for emulating a terminal, where the
emulation is either a GUI program (xterm etc) or a network connection
(telnet, ssh, etc). Using it to change the default buffering of
stdin/stdout/stdout stderr is something of a hack (and a rather complex
one), but it works.

There are two distinct mechanisms for implementing pseudo-ttys.

The BSD way is to have static device nodes for both master and slave devices.
The program attempts to open the master devices /dev/pty[p-za-z][0-9a-f]
in order (i.e. /dev/ptyp0 is first) until one succeeds. The corresponding
slave device has the same name but with "tty" instead of "pty".

The SysV way is to open /dev/ptmx. The returned descriptor is for a new 
master device. The slave is dynamically created within the /dev/pts
pseudo-filesystem; its name can be obtained by using the ptsname()
function.

The Python pty module should take care of this for you.




More information about the Python-list mailing list