一、 名字来源:Teletype / Teletypewriter(电传打字机)

1. 词源拆解

tty = TeleTYpewriter 的缩写,直译:电传打字机。

历史背景

  1. 60年代大型机时代,没有键盘显示器一体设备;人机交互靠 Teletype 33 这种硬件:
    • 自带打字键盘(输入)、卷纸打印头(输出);
    • 通过串口长线连机房大型主机;
    • 人敲按键 → 电信号传给电脑;电脑输出字符 → 当场打印在纸带上。
  2. 当年Unix诞生在PDP小型机(Programmed Data Processor,可编程数据处理器,数字设备公司 DEC 的经典小型机系列,16 位迷你通用小型计算机,PDP-8、PDP-11 最为知名)上,系统对接的唯一交互设备就是这种电传机,内核直接把这类硬件设备命名为tty设备。
  3. 后来屏幕终端、桌面终端、ssh远程终端全部普及,但历史命名保留至今,所有字符交互设备统一叫 tty

二、现代 Linux 里「tty 终端」到底是什么

核心定义

tty 是内核一套终端子系统,是一种字符型设备文件(在 /dev 下),专门处理交互式人机字符IO,自带一套特殊终端规则(行缓冲、退格、Ctrl+C中断、密码不回显等)。

三类常见 tty 设备

1. 物理虚拟控制台 /dev/tty1~tty6(本机黑屏文字终端)

Ctrl+Alt+F3 切到纯文字界面,对应 /dev/tty3,直接绑定本机键盘+显示器硬件。 图形桌面一般占用 tty7

2. 伪终端 PTY /dev/pts/X(你日常用的终端窗口)

桌面打开的 GNOME Terminal、XTerm、SSH远程登录,底层都是 pty(pseudo-tty,虚拟tty)

  • 分为主端master(终端窗口程序持有)、从端slave(/dev/pts/0,shell/bash绑定);
  • 键盘输入 → 终端模拟器 → master → slave(tty) → bash;
  • bash打印输出反向走同一条通道到窗口显示;
  • 本质是软件模拟老式电传机硬件行为,所以依然归类为tty。

3. 串口硬件终端 /dev/ttyS0

老式RS232串口、USB转串口设备,外接工业控制台、交换机Console口,是原汁原味当年的硬件tty延伸。

特殊文件 /dev/tty

代表当前进程所属的控制终端,程序不管跑在 /dev/pts/2 还是 /dev/tty4,打开 /dev/tty 都会自动指向自己对应的终端设备。 用途:脚本强制弹窗输入密码,不受stdin管道重定向影响。

三、关键:tty 和普通管道 pipe 的本质区别(结合你之前FFmpeg场景)

很多人混淆两者,这里一次性分清:

特性tty(终端设备)pipe(匿名管道)
设计初衷人机交互式字符交互,带终端规则进程间单向批量流式数据传输
双向性双向读写(人输入、程序输出)单向半双工,一端读一端写
内置行处理(Line discipline)✅ 内置:退格删除、Tab补全、Ctrl+C发SIGINT、密码隐藏、回车换行转换❌ 纯原始字节流,无任何特殊处理
随机seek不支持不支持
绑定关系一个进程组独占前台tty,后台进程读写会被拦截仅父子进程临时共享缓冲区
典型场景bash、ssh、图形终端窗口shell `cmd1

举个直观例子

  1. 直接在终端运行 ffmpeg: stdin/stdout/stderr 绑定 tty
    • 你敲 Ctrl+C,tty子系统捕获信号杀死ffmpeg;
    • 输入密码类内容会自动隐藏不回显;
  2. cat video.mp4 | ffmpeg -i pipe:0 out.mp4 ffmpeg stdin绑定 pipe管道
    • 管道没有终端信号机制,Ctrl+C 要传给整个管道进程组;
    • 纯裸字节流,不会处理回车、退格这类交互字符;
    • 无法实现交互式输入。

四、为什么程序默认 stdin/stdout 会连 tty

进程启动规则:

  1. 登录/打开终端窗口时,内核分配一个tty设备;
  2. 启动shell(bash/zsh)时,自动把 fd0(stdin)、fd1(stdout)、fd2(stderr) 挂载到这个tty;
  3. shell执行任何命令(ls/ffmpeg/python),子进程会继承这三个fd,所以默认读写终端屏幕/键盘。

一旦用 | 管道、> file 重定向,fd就会脱离tty,切换成管道/普通文件。

五、补充几个实用命令验证 tty

# 查看当前终端设备名(返回 /dev/pts/0 这类)
tty
 
# 查看终端参数(tty独有配置,管道无)
stty -a
 
# 判断当前stdin是不是终端(返回1=是tty,0=管道/文件)
test -t 0 && echo "当前是终端窗口" || echo "当前是管道/文件"

极简总结

  1. 名字由来:tty = Teletypewriter(老式电传打字机),Unix沿用历史命名;
  2. 本质:Linux内核一套专门处理交互式字符人机IO的设备子系统;
  3. 和管道最大差异:tty带交互信号、行编辑、双向交互能力,管道只是单纯单向字节缓冲通道;
  4. 日常桌面终端、ssh远程都是虚拟tty(pty/pts),纯文字黑屏是硬件虚拟tty(tty1~6)。