当你打开终端并输入命令时会发生什么?(上)

哈喽大家好,我是咸鱼

参加过校招面试的小伙伴们肯定对下面这道面试题很熟悉:"当你在浏览器输入一段网址后会发生什么?"。这道面试题可以说是很经典了,因为其涉及大量网络协议,可以非常直观的看出小伙伴们对计算机网络体系的整体把握程度

但如果问题换成:"当你打开终端并输入 ls 时会发生什么?",有多少小伙伴能够回答出来呢?

终端的前世今生

大多数现代终端应用程序的工作方式都来自于其历史前辈------电传打字机(teletypes,简称 tty)

在大型计算机的时代,当时数据存储在磁带上,计算机的内存以 kB 为单位,电传打字机就是为了它们而被设计出来

如上图,左边的是 IBM 2741电传打字机,右边是 IBM System/360 Mo. 40大型计算机

电传打字机是允许用户与计算机交互的基本文本客户端。teletypes 其实是 teletypewriter的缩写,因为它是从打字机(typewriters)演变过来的

如上图所示,电传打字机和大型计算机通过连接两端的物理线来进行通信。沟通过程如下:

  • 当用户从电传打字机输入时,ASCII 文本将一个字符一个字符地通过网络传输
  • 计算机的内核接收字符并对其进行解码
  • 接着字符被送到一个名为 TTY driver 的驱动程序,这里负责将输入发送到用户程序并收集输出
  • 最后,内核将输出发送回电传打字机 ,以便显示给用户

需要提到的一点是 line discipline(行规则),它会将字符缓冲到内核内存中,直到按下 Enter" 键,程序才会接收到输入

line discipline 允许这块缓冲区是可编辑的,并提供了一些与程序无关的快捷键(例如 ctrl-w)

这在当时是一项重要的性能优化,因为让程序员一个字符一个字符的处理是非常低效的

随着计算技术的进步,这些独立组件中的许多都实现了现代化。比如说电传打字机被终端所取代,终端是完全电子的机器,包括电子显示器

上图是 DEC 于 1978 年发布的 VT100 终端机(VT = video terminal),它实现并推广了至今仍在使用的 ANSI 转义码

随着电子终端的诞生,出现了越来越多的功能(例如颜色、铃声)。但本质上跟电传打字机完全相同------发送输入字符流并显示输出

现如今人人都有一台自己的电脑,这些电脑的操作系统可以监督许多应用程序,终端不再是专门的硬件,而是变成了这些应用程序中的一个

与典型的 GUI 应用程序一样,终端是操作系统监督下的一个进程,它监听来自用户的事件和输入,并告诉操作系统在窗口中显示什么(终端不直接与外设交互,而是通过驱动程序和窗口管理器)

有时候我们还会听到 "终端模拟器" 这个词,而不是简单的称之为 "终端"。这是因为 "终端" 指的是专门的硬件(终端机),而现在大多数的终端只是对该设备的模拟,是一个应用程序

但是我们这里不做区分,"终端模拟器" 和 "终端" 含义一样

那么当我们打开终端时会发生什么呢?

打开终端

上面我们提到过,终端是一个应用程序,能够让你 "使用你的电脑"(即在上面运行程序)。我们的电脑上可能已经存在了 ls、rm、mv 等程序

但是我们不满足于使用这些简单的命令,我们还希望使用脚本来实现自动化, 这些脚本将许多命令的序列组合在一起,使用分支条件逻辑,运行重复循环或并行化命令等

为了让计算机能够读懂我们的脚本并执行起来,我们需要一个完整的可交互的解释型的编程环境------shell

将其他程序作为进程运行,让操作系统内核读懂你写的脚本,这些工作都由 shell 完成。目前常见的 shell 有 Bash、Zsh 等

终端和 shell 是两个独立的程序:

  • shell 负责解释你输入的命令
  • 终端负责 UI 相关的东西,比如字体、颜色等

当我们打开终端时,终端会根据用户生成一个 shell 进程,以及用户与 shell 之间,用户与 shell 启动的进程之间通信的方法

这个 shell 进程负责解释和执行用户输入的命令,并与用户进行交互。用户在终端输入的命令将通过这个通信通道传递给 shell 进程进行解释执行,并将执行结果反馈给用户显示在终端上

创建 PTY

伪终端设备(PTY)是在计算机操作系统中创建的一个虚拟设备,用于模拟物理终端的功能

在 UNIX、Linux 和类 UNIX 系统中,PTY 用于在用户和程序之间建立一个通信通道,允许用户通过终端会话与程序进行交互

PTY通常由两个主要部分组成:主设备(leader)和从设备(follower)。leader 端连接到用户终端,follower 端连接到一个或多个程序

当用户打开终端并启动一个 shell 时,终端模拟器会创建一个 PTY,并将 leader 端连接到用户界面,同时将 follower 端连接到 shell 或其他命令行程序。用户输入的命令通过 leader 端传输到 follower端,follower端执行这些命令并将输出发送回 leader 端,最终显示在用户界面上

在 Unix 中,一切皆文件,这句话指的是 Unix 中的所有东西都有与文件相同的读/写接口。leader 的 fd(文件描述符) 指向内存中的一个缓冲区,而 follower 是一个在磁盘上具有实际路径的字符设备文件。

上图可以看到,我们打开了两个终端(/dev/pts/0、/dev/pts/1),启动了两个 shell 进程。如果我们在终端1(/dev/pts/1)中敲命令并重定向到终端0(/dev/pts/0),可以看到输出结果是在终端0中显示的

生成 shell

终端会话在启动时可能会为shell创建一个子进程,这个子进程将作为 shell 的实例来执行用户的命令

UNIX 和类 UNIX 系统中,终端会话会使用伪终端设备(PTY)来与 shell 进程进行通信,通过这种方式,终端会话可以读取和写入 shell 的输入、输出和错误输出(fd 0到2)

shell 初始化

在Linux中,用户打开终端启动 shell 进程时会进行 shell 初始化,这个过程涉及一些配置文件和脚本的执行,用来设置用户的环境和启动 shell 的行为

步骤大致如下:

  1. 读取配置文件 :在用户登录时,shell 会读取一系列的配置文件来设置用户的环境变量、别名、函数等。这些配置文件可以包括全局配置文件(例如/etc/profile)和用户特定的配置文件(例如~/.bash_profile~/.bashrc等)
  2. 执行配置命令:配置文件中可以包含各种设置和命令,例如设置环境变量、修改提示符、定义别名和函数等。这些命令会在 shell 启动时执行,以确保在用户登录后设置了所需的环境和行为
  3. 启动shell:一旦执行了配置文件中的命令,shell 就会准备就绪,等待用户的输入。这时,shell 的提示符会出现,等待用户输入命令。
相关推荐
爱瑞瑞29 分钟前
🐧深入浅出的认识 Linux 指令
linux·shell
ajassi200042 分钟前
开源 java android app 开发(十一)调试、发布
android·java·linux·开源
小李飞刀李寻欢1 小时前
使用kubeadm部署Kubernetes(k8s)集群的步骤
linux·服务器·ubuntu·kubernetes·k8s
运维成长记1 小时前
阿里云实践创建实例步骤
linux·运维·服务器·阿里云·云计算
THe CHallEnge of THe BrAve2 小时前
Linux检验库是否安装成功
linux·运维·服务器
算家计算2 小时前
告别复杂文档解析噩梦!MonkeyOCR 本地部署教程:支持公式/表格多元素结构化
linux·人工智能·开源
曹勖之3 小时前
ROS2 工作空间中, CMakeLists.txt, setup.py和 package.xml的作用分别是?
xml·linux·服务器·ros2
企鹅侠客4 小时前
ttyd:安全地通过网络共享您的 Linux 终端
linux·运维·ttyd
饭碗、碗碗香4 小时前
【开发常用命令】:服务器与本地之间的数据传输
linux·运维·服务器·笔记·学习
MonkeyBananas5 小时前
在Ubuntu中使用Apache2部署项目
linux·运维·ubuntu