Originally, "tty" had two definitions: the hardware (now the emulator) and the driver (interfaced through /dev/pty* or /dev/tty*).
The hardware/emulator was/is responsible for:
- Taking a stream of data and presenting it; this included interpreting control sequences like "move cursor left", "blinking cursor", "clear-screen" although these control sequences were often different among manufacturers.
- Sending keycodes for keys typed by the user; most of these were standard ASCII characters, but some terminals sent propriety keycodes for even standard keys.
The 'tty' driver was responsible for:
- Managing the buffering, in raw or canonical mode; for example, buffering a line of characters until Enter is pressed.
- Managing the control flow; e.g. being able to stop/continue with Cntl-s/Cntl-q.
- Translating propriety keycodes to standard ASCII, where applicable.
- Intercepting certain control characters (like Cntl-c and Backspace) and processing them appropriately (send SIGINT on a Cntl-c or signal an EOF on Cntl-d.
- Canonical display of characters, for example, if
echo
is turned off, then do not send feedback (character typed) back to the terminal.
The terminfo and termcap databases managed what terminal control characters should be sent for an operation (like 'clear-screen'). These control sequences were/are not interpreted by the driver, but by the hardware/emulator.
When a GUI terminal emulator prints out a string, it has to convert the string to font codepoints, send the codepoints to a font renderer, get back a bitmap and blit that bitmap to the display via the X server.
The font renderer has to retrieve the glyphs and run them (did you know that Truetype/Opentype fonts are programs running inside a virtual machine in the font renderer?). During the process of running each glyph, an insane number of decisions are made with respect to font metrics, kerning (though monospace fonts and kerning don't mix well), Unicode compliance, and that's before we even reach the rasteriser which probably uses sub-pixel addressing. The terminal then has to take the buffer produced by the font rasteriser and blit it to the right place, taking care of pixel format conversions, alpha channels (for sub-pixel addressing), scrolling (which involves more blitting), et cetera.
In comparison, writing a string to a Virtual Terminal running in text mode (note: not a graphical console) involves writing that string to video memory. ‘Hello, World!’ involves writing 13 bytes (13 16-bit words if you want colours, too). The X font rasteriser hasn't even started its stretching exercises and knuckle cracking yet, and we're done. This is why text mode was so incredibly important in decades past. It's very fast to implement. Even scrolling is easier than you think: even on the venerable Motorola 6845-based MDA and CGA, you could scroll the screen vertically by writing a single 8-bit value to a register (could be 16... it's been too long). The screen refresh circuitry did the rest. You were essentially changing the start address of the frame buffer.
There's nothing you can do to make a graphical terminal as fast as a text mode terminal on the same computer. But take heart: there have been computers with slower text modes than the slowest graphical terminal you're ever likely to see on a modern computer. The original IBM PC was pretty bad (DOS did software scrolling, sigh). When I saw my first Minix console on an 80286, I was amazed at the speed of the (jump) scrolling. Progress is good.
Update: how to accelerate the terminal
@poige has already mentioned three in his answer, but here's my own take on them:
- Decrease the size of the terminal. My own terminals tend to grow till they fill screens, and they get slow as they do that. I get exasperated, annoyed at graphical terminals, then I resize them and everything's better. :)
- (@poige) Use a different terminal emulator. You can get a huge speed boost at the cost of some modern features.
xterm
and rxvt
work really well, it has a fantastic terminal emulator. I suspect your tests may have showed they perform better than the ‘modern’ ones.
- (@poige) Don't use scalable fonts. 1986 may call and ask for its terminals back, but you can't deny they're faster. ;)
- (@poige) Dumb down the font rasteriser by turning off anti-aliasing/sub-pixel addressing and hinting. Most of them allow overrides in environment variables, so you don't have to do this globally. Note: pointless if you choose a bitmap font.
- This will hurt the most: don't use (multiple panes in)
tmux
— run two separate terminals side by side. When tmux
displays two panes, it has to use terminal directives to move the cursor around a lot. Even though modern terminal libraries are very fast and good at optimising, they're still stealing bytes from your raw terminal bandwidth. To move the cursor to an arbitrary row on a DEC VT-compatible terminal, you send ESC [ row ; col H
. That's 6–10 bytes. With multiple terminals, you're segregating the work, doing away with the need for positioning, optimisation, buffering and all the other stuff curses
does, and making better use of multiple CPU cores.
Best Answer
May give you good results. It gives the name of the process that is the parent of the session leader. For processes started within a terminal emulator, that would generally be the process running that terminal emulator (unless things like
screen
,expect
,tmux
... are being used (though note thatscreen
andtmux
are terminal emulators), or new sessions are started explicitly withsetsid
,start-stop-daemon
...)If you find nested parenthesis hard to read, you could write it on several lines:
Or use variables (which can also help make the script more self explanatory):
You could also try parsing
wtmp
where terminal emulators usually log an entry with their pid associated with the pseudo-terminal device. This works for me on a Debian system provided expect/screen/tmux... are not involved:(using
dump-utmp
from GNUacct
).