Linux 终端(TTY)

2023-05-16

原文:Linux 终端(TTY) - sparkdev - 博客园

Linux 终端(TTY) 

TTY 是 Teletype 或 Teletypewriter 的缩写,原来是指电传打字机,后来这种设备逐渐键盘和显示器取代。不管是电传打字机还是键盘显示器,都是作为计算机的终端设备存在的,所以 TTY 也泛指计算机的终端(terminal)设备。为了支持这些 TTY 设备,Linux 实现了一个叫做 TTY 的子系统。所以 TTY 既指终端,也指 Linux 的 TTY 子系统,当然 TTY 还有更丰富(混乱)的含义,本文试图把它们解释清楚。本文中演示部分使用的环境为 ubuntu 18.04。

硬件终端 terminal(TTY)

早期的终端(terminal) 是一台独立于计算机的机器(teletype 即, TTY),大概像下面的样子:

它终端通过线缆与计算机连接,并完成计算机的输入输出功能:

现在物理终端实际上已经灭绝了,我们看到的所有 TTY 都是模拟视频终端,即软件仿真出来的终端。可以通过 toe -a 命令查看系统支持的终端类型,不要奇怪,这是一个挺长的列表。

控制台 console

提到终端就不能不提控制台 console。控制台的概念与终端含义非常相近,其实现在我们经常用它们表示相同的东西,但是在计算机的早期时代,它们确实是不同的东西。
一些数控设备(比如数控机床)的控制箱,通常会被称为控制台,顾名思义,控制台就是一个直接控制设备的面板,上面有很多控制按钮。 在计算机里,把那套直接连接在电脑上的键盘和显示器就叫做控制台。而终端是通过串口连接上的,不是计算机自身的设备,而控制台是计算机本身就有的设备,一个计算机只有一个控制台。计算机启动的时候,所有的信息都会显示到控制台上,而不会显示到终端上。这同样说明,控制台是计算机的基本设备,而终端是附加设备。计算机操作系统中,与终端不相关的信息,比如内核消息,后台服务消息,都可以显示到控制台上,但不会显示到终端上。比如在启动和关闭 Linux 系统时,我们可以在控制台上看到很多的内核信息(下图来自 vSphere Client 中的 "Virtual Machine Console"):

现在终端和控制台都由硬件概念,逐渐演化成了软件的概念。简单的说,能直接显示系统消息的那个终端称为控制台,其他的则称为终端(控制台也是一个终端)。或者我们在平时的使用中压根就不区分 Linux 中的终端与控制台。

下面的例子是通过 /dev/console 文件向控制台发送消息,这个这个例子我们可以看到控制台与终端的一点点不同之处。
打开 vSphere Client 中的 "Virtual Machine Console"(即控制台),默认显示的是 tty1:

通过其他的终端向 /dev/console 中写入字符串 "hello world":
root@esearch:~# echo "hello world" > /dev/console

字符串显示在了控制台中。然后通过 Ctrl + Alt + F2 把控制台中的终端切换到 tty2,再次向 /dev/console 写入字符串:
root@esearch:~# echo "hello world" > /dev/console

这次字符串写到了 tty2 中,这说明 Linux 总是把写入 /dev/console 的内容会显示在控制台中当前的虚拟终端(tty1-tty6)里。

TTY 设备

从历史上看,终端刚开始就是终端机,配有打印机,键盘,带有一个串口,通过串口传送数据到主机端,然后主机处理完交给终端打印出来。电传打字机(teletype)可以被看作是这类设备的统称,因此终端也被简称为 TTY(teletype 的缩写)。
如下图所示(下图来自互联网):

UART 驱动
如上图所示,物理终端通过电缆连接到计算机上的 UART(通用异步接收器和发射器)。操作系统中有一个 UART 驱动程序用于管理字节的物理传输。

行规范
上图中内核中的 Line discipline(行规范)用来提供一个编辑缓冲区和一些基本的编辑命令(退格,清除单个单词,清除行,重新打印),主要用来支持用户在输入时的行为(比如输错了,需要退格)。

TTY 驱动
TTY 驱动用来进行会话管理,并且处理各种终端设备。

UART 驱动、行规范和 TTY 驱动都位于内核中,它们的一端是终端设备,另一端是用户进程。因为在 Linux 下所有的设备都是文件,所以它们三个加在一起被称为 "TTY 设备",即我们常说的 TTY。

从软件仿真终端到伪终端

后来的终端慢慢演变成了键盘 + 显示器。如果我们要把内容输出到显示器,只要把这些内容写入到显示器对应的 TTY 设备就可以了,然后由 TTY 层负责匹配合适的驱动完成输出,这也是 Linux 控制台的工作原理(下图来自互联网):

上图中,TTY 驱动和行规范的行为与前面的示例类似,但不再有 UART 或物理终端。相反,软件仿真出视频终端,并最终被渲染到 VGA 显示器。注意,这里出现了软件仿真终端,它们是运行在内核态的。显示器和 vSphere Client "Virtual Machine Console" 中的 tty1-tty6 都是软件仿真终端

/dev/tty1-/dev/tty6 是这些仿真终端在文件系统中的表示,程序通过对这些文件的读写实现对仿真终端的读写。

如果我们在用户空间也进行终端仿真,情况会变得更加灵活,下图是 xterm 及其克隆的工作方式(下图来自互联网):

为了便于将终端仿真移入用户空间,同时仍保持 TTY 子系统(TTY 子系统指 TTY 驱动和行规范)的完整,伪终端被发明了出来(pseudo terminal 或 pty)。伪终端在内核中分为两部分,分别是 master side 和 在 TTY 驱动中实现的 slave side。注意上图中的 xterm,这是一个运行在用户态的终端仿真程序,比如 Ubuntu Desktop 中的 GNOME Terminal:

当创建一个伪终端时,会在 /dev/pts 目录下创建一个设备文件:

如果是通过 PuTTY 等终端仿真程序通过 SSH 的方式远程连接 Linux,那么终端仿真程序通过 SSH 与 PTY master side 交换数据。

终端与伪终端的区别

至此我们可以得出这样的结论:现在所说的终端已经不是硬件终端了,而是软件仿真终端(终端模拟软件)。
关于终端和伪终端,可以简单的理解如下:

  • 真正的硬件终端基本上已经看不到了,现在所说的终端、伪终端都是软件仿真终端(即终端模拟软件)
  • 一些连接了键盘和显示器的系统中,我们可以接触到运行在内核态的软件仿真终端(tty1-tty6)
  • 通过 SSH 等方式建立的连接中使用的都是伪终端
  • 伪终端是运行在用户态的软件仿真终端

总结

通过本文我们可以了解到,真正的硬件终端基本上已经看不到了。在一些连接了键盘和显示器的系统中(当然也包括一些 vsphere 等虚拟环境),我们可以接触到运行在内核态的软件仿真终端。而我们使用最多的则是伪终端。

参考:
解密TTY
Linux TTY/PTS概述
The TTY demystified
What is stored in /dev/pts files and can we open them?
终端、虚拟终端、shell、控制台、tty的区别

作者:sparkdev

出处:sparkdev - 博客园

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux 终端(TTY) 的相关文章

  • 页面错误陷阱的成本

    我有一个应用程序 它定期 每 1 或 2 秒后 通过分叉自身来获取检查点 因此 检查点是原始进程的一个分支 它一直保持空闲状态 直到原始进程发生某些错误时被要求启动 现在我的问题是fork的写时复制机制的成本有多大 每当原始进程写入内存页面
  • 类似 wget 的 BitTorrent 客户端或库? [关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 是否有任何
  • 在 Linux 2.6.21 (glibc 2.3.5) 上进行 ARP 和反向 ARP

    我需要在任意 IP 网络上存储对第三方设备的持久引用 其中设备的 IP 地址可能是静态的或由 DHCP 随机分配 我不控制网络上的设备 也不能依赖 DNS 和其他现有的或与设备一起使用的临时网络协议 所以我被指示使用硬件地址和 ARP 进行
  • 从 gitlab docker runner 启动声纳扫描仪

    我有一个 CI 工作流程 集成了 linting 作业和代码质量作业 我的 Linting 工作是一个 docker runner 从应用程序代码启动我的 eslint 脚本 然后我的代码质量工作应该启动声纳扫描仪泊坞窗实例 检查我的代码并
  • Linux:通过网络进行屏幕桌面视频捕获和 VNC 帧速率

    抱歉 文字墙很长 TL DR VNC 连接的帧速率是多少 以帧 秒为单位 或者更确切地说 由谁决定 客户端还是服务器 对于桌面屏幕捕获的任何其他建议 但 正确的时间编码 具有不抖动的帧速率 具有稳定的周期 并有可能将其作为未压缩 或无损 图
  • Linux shell 命令逐块读取/打印文件

    是否有一个标准的 Linux 命令可以用来逐块读取文件 例如 我有一个大小为 6kB 的文件 我想读取 打印第一个 1kB 然后是第二个 1kB 看来猫 头 尾在这种情况下不起作用 非常感谢 你可以这样做read n在循环中 while r
  • 操作系统崩溃的常见原因[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有兴趣了解 操作系统崩溃 不限于Windows崩溃 最常见的技术原因 从操作系统编程的角度 有哪些 我正在寻找一个不像 打开太多应用
  • 如何真正释放 Linux 中的大页面以供新进程使用?

    真的找不到太多关于此的信息 希望有人可以提供帮助 我正在假脱机使用 100GB java 堆作为大数据缓存 为了避免与文件系统缓存等内容发生冲突 并且因为它通常性能更好 我将其分配在大页面中 我保留了 51 200 x 2MB 大页面 一切
  • 即使 makefile 和源代码存在,为什么“Build Project”在 Eclipse Helios CDT 中显示为灰色?

    我无法构建我的项目 我在 Eclipse Helios 中创建了一个新的 CDT 项目 并告诉它使用现有的源代码和 makefile 这两者都正确显示在 Package 和 Project 视图中 然而 项目 菜单中的 构建全部 和 构建项
  • 在键盘热插拔上加载模块

    我正在尝试学习如何为 Linux 系统编写模块和驱动程序 类似于this https unix stackexchange com questions 120839 usb kernel module does not load on de
  • Mono 和 WebRequest 速度 - 测试

    在 mono 4 6 2 linux 中 我注意到 wget 下载文件的速度与webclient DownloadString 所以我做了一个小测试来调查 为什么 wget 明显比 C 快 根据我自己的实验 使用 wget 下载 手动读取文
  • 原生 Linux 应用程序可像 ResHacker 一样编辑 Win32 PE

    我想运行自动修改 dll服务 用户提交特定的 dll 我在服务器上修改它 然后用户可以下载 dll的修改版本 是否有任何本机 Linux 应用程序提供常见的 Win32 PE 修改功能 例如图标 字符串 加速器 对话等 至少提供命令行或脚本
  • ARM 系统调用的接口是什么?它在 Linux 内核中的何处定义?

    我读过有关 Linux 中的系统调用的内容 并且到处都给出了有关 x86 架构的描述 0x80中断和SYSENTER 但我无法追踪 ARM 架构中系统调用的文件和进程 任何人都可以帮忙吗 我知道的几个相关文件是 arch arm kerne
  • Docker DNS 设置

    我尝试使用自定义网络和 dos 设置创建 docker 容器 docker网络创建 driver bridge opt com docker network bridge enable ip masquerade true opt com
  • python中打印字符串的长度

    有没有什么方法可以找到 即使是最好的猜测 Python中字符串的 打印 长度 例如 potaa bto 是 8 个字符len但 tty 上只打印 6 个字符宽 预期用途 s potato x1b 01 32mpotato x1b 0 0mp
  • gnome-terminal 新选项卡,使用别名作为要执行的命令

    我已经创建了一个别名 bashrc文件如下 alias myproject cd Desktop myproject 当我重新启动终端时保存文件后 输入myproject带我到项目目录 但是当我尝试使用别名作为新的命令参数时gnome te
  • 在中断时获取 current->pid

    我正在Linux调度程序上写一些东西 我需要知道在我的中断到来之前哪个进程正在运行 当前的结构可用吗 如果我在中断处理程序中执行 current gt pid 我是否可以获得我中断的进程的 pid 你可以 current gt pid存在并
  • 通过 SSH 将变量传递给远程脚本

    我正在通过 SSH 从本地服务器在远程服务器上运行脚本 首先使用 SCP 复制该脚本 然后在传递一些参数时调用该脚本 如下所示 scp path to script server example org another path ssh s
  • grails 上的同步块在 Windows 上有效,但在 Linux 上无效

    我有一个 grails 应用程序 它依赖于服务中的同步块 当我在 Windows 上运行它时 同步按预期工作 但当我在 ams linux 上运行时 会出现 StaleObjectStateException 该问题在以下示例中重现 cla
  • 使用命令行将 MediaWiki 维基文本格式转换为 HTML

    我倾向于编写大量文档 因此 MediaWiki 格式对我来说很容易理解 而且比编写传统 HTML 节省了我很多时间 然而 我也写了一篇博客 发现一直从键盘切换到鼠标来输入正确的 HTML 标签会增加很多时间 我希望能够使用 Mediawik

随机推荐

  • mybatis源码之集成mybatis-plus源码

    本文将结合源码介绍mybatis plus的原理 xff0c 包括 xff1a BaseMapper APIMybatisSqlSessionFactoryBean类BaseMapper API Statement解析Wrapper查询构建
  • Jpa 插入更新如何过滤null值

    使用Jpa时 xff0c 默认的save方法会将entity中null的值也更新到数据库 xff0c 这对与存在默认值或者更新接口将直接导致错误的记录产生 xff0c 那么如何解决这个问题 xff1f Hibernate提供了两个注解 64
  • 一个奇怪的java.lang.IncompatibleClassChangeError异常

    解决方法就是替换jdk版本 xff0c 下面都是废话 最近项目进行了一次小更新 xff0c 添加了一个很小很小的功能 xff0c 结果运行一段时间后莫名出现java lang IncompatibleClassChangeError xff
  • nginx的proxy_pass最后反斜杠/的问题

    如果只是host xff0c 如http host 带 xff1a 用代理的内容替换掉匹配的路径 不带 xff1a 拼接上匹配的路径 2 xff1a 如果是子路径 xff0c 如http host func 带和不带 xff1a 用代理的内
  • gitlab修改克隆地址

    1 修改gitlab yml文件 xff0c 修改gitlab下的host和port vi opt gitlab embedded service gitlab rails config gitlab yml 修改完成后执行gitlab c
  • 结构体成员——数组或指针

    结构体成员是C类型的字符数组 表示字符串时 c语言中没有字符串类型 xff0c 只能使用字符数组表示字符串 当定义结构体时 xff0c 成员是字符数组时 xff0c 在外部给该成员赋值 xff0c 不能使用 结构体把变量名 成员名 61 3
  • C++遍历输出enum枚举类型

    enum DAY MON TUE WED THU FRI SAT SUN 问题 如果使用如下方式来遍历 xff0c 则编译器会报类型转换失败错误 xff0c 因为enum类型没有 43 43 运算符 xff0c 也不支持 43 运算 for
  • Kali Linux

    为什么我输入git clone 43 网址显示无法访问啊
  • Android自定义标题栏异常You cannot combine custom titles with other title features

    我们在使用自定义标题栏时 xff0c 一般的写法基本上是下面几步 requestWindowFeature Window FEATURE CUSTOM TITLE setContentView R layout activity test
  • Kotlin中使用Dagger2 可能导致错误"Dagger does not support injection into private fields"

    Kotlin 生成 java文件时属性默认为 private xff0c 给属性添加 64 JvmField 声明可以转成 public class User var name String 61 null val age Int 61 2
  • [linux]ubuntu22安装mysql5.7.40

    导语 xff1a ubuntu22 04 强制安装mysql5 7 40 安装完安装其他apt依赖的时候 可能会造成mysql出问题 最好还是离线环境用 apt update apt get install zip y cd var rm
  • winxp 远程rdp 连接 Ubuntu10.10-再次远程登陆失败 (二)

    在文章winxp 远程rdp 连接 Ubuntu10 10 一 操作完成 xff0c 并且进行第一成功登陆之后 xff0c 退出 xff08 注销 直接关闭mstsc退出按钮 xff09 远程连接之后 xff0c 重新登录出现 xff0c
  • PostGIS教程七:几何图形(Geometry)

    目录 一 介绍 二 元数据表 三 表示真实世界的对象 3 1 点 xff08 Points xff09 3 2 线串 xff08 Linestring xff09 3 3 多边形 xff08 Polygon xff09 3 4 集合 xff
  • FreeBSD下修改安装源的方法

    FreeBSD默认是从官方的源下载软件包的 xff0c 速度比较慢 xff0c 可以修改配置文件指定国内的镜像源来快速安装软件 说明 xff1a FreeBSD中安装软件一般有两种方式 xff1a xff08 一 xff09 使用pk ad
  • sqlite3_bind

    sqlite3 bind text 中绑定的指针 xff0c 在sqlite3 step 时必须存在 xff0c 不能释放 xff0c 否则会是乱码 sqlite3 bind blob中绑定的指针 xff0c 在sqlite3 step 时
  • Windows10 Clion 无法打开文件cudart.lib

    真是巨坑 xff0c 遇到这个问题 xff0c 且耗费两个小时百度 google xff0c 差点放弃换用Visual Studio xff0c 但真实原因竟然这么简单 在你的CmakeList txt中 xff0c 是不是这样添加cuda
  • cf规则介绍

    codeforces的正确打开方式 1 背景 可能很多人都久闻codeforces网站的大名 xff0c 却苦于各种各样的区域性问题或玄学问题 xff0c 没能真正地体验到cf所带来的极致魅力 而网络上关于这方面的博文太少了 xff08 至
  • 使用Buildroot + QEMU构建和运行Linux

    使用Buildroot 43 QEMU构建和运行Linux xunknown 64 2022 04 06 概述 Buildroot是一个用于为嵌入式系统构建完整的Linux系统 xff08 包括Bootloader xff0c Linux
  • openwrt 无线中继设置–固定IP+打印服务器和文件共享

    openwrt 无线中继设置 固定IP 43 打印服务器和文件共享 因为给TPLINK703N xff0c 编译16MROM成功 xff0c 固件里加入了打印服务器和SAMBA VSFTPD USB挂载等功能 xff0c 可使用有线连接上级
  • Linux 终端(TTY)

    原文 xff1a Linux 终端 TTY sparkdev 博客园 Linux 终端 TTY TTY 是 Teletype 或 Teletypewriter 的缩写 xff0c 原来是指电传打字机 xff0c 后来这种设备逐渐键盘和显示器