ITPub博客

首页 > 数据库 > 数据库开发技术 > 当你打开终端并输入命令时会发生什么?(下)

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

原创 数据库开发技术 作者:咸鱼运维杂谈 时间:2023-12-15 17:28:00 0 删除 编辑

哈喽大家好,我是咸鱼


我们先来大致回顾一下文章《当你打开终端并输入命令时会发生什么?(上)》的内容


终端设备是由电传打字机演变过来的,电传打字机通过物理线与大型计算机连接在一块来实现输入输出

如上图,分别是二战时期的电传打字机和西门子 “Fernscheiber 100” 电传打字机


随着技术的不断发展(尤其是显示技术),带显示屏的终端设备随之诞生

而现在随着个人电脑的普及,出现了基于屏幕显示的图形用户界面(GUI),演变成了现在的计算机终端


现在的终端大多都是计算机上的一个应用程序,它们通常被称为终端模拟器,充当用户与操作系统交互的界面(比如说 Linux 中的 Xterm、Xshell,Windows 中的控制台),而不必使用专门的终端。输出系统是屏幕,输入系统是键盘


以 Linux 为例,当我们打开终端时,通常会启动一个 shell 进程,用于与用户交互。用户在终端中输入的命令将传递给 shell 进程,然后由 shell 解释和执行这些命令


这个过程包括将用户输入的命令解析为操作系统可以理解的指令,执行这些指令,并将执行结果返回给终端显示给用户

输入命令


当我们在终端中输入命令时,键盘输入的字符会被转换成相应的字符编码(比如说 backspace 键被转译成 ASCII 字符 0x08)


这些字符通过终端写入到 PTY leader,接着 TTY driver 从 PTY leader 中读取字符并存储到 line discipline 中(line discipline 为 PTY 两端之间的中间缓冲区)


不但如此,line discipline 还负责解释来自 PTY leader 的字符然后根据自己的规则去处理它们(比如进行回退、删除字符等,或者处理特殊字符)


举个例子,line discipline 收到 backspace 时,它会根据自己的规则解释成 ERASE 字符,然后进行编辑,方法是删除最后一个字符


接着将删除操作返回给 PTY leader,这样终端就可以从 PTY leader 那里读取到更改并将其反映在终端显示中


需要注意的是,上面这段过程里字符还没有被写入到 PTY follower 中,只是处在【编辑】部分


当我们在键盘敲下 CTRL+C 时,line discipline 会解释成 INTR (INTERRUPT 的缩写),这时候就会向 PTY follower 发送一个 SIGINT 信号去中断在前台运行的任何进程


如果不是特殊字符(比如输入 ls),line discipline 会将字符返回给 PTY leader,终端程序读取并显示在屏幕上,这就是为什么你在键盘敲一个字符,显示器就会显示一个字符(echo 功能)


现在 shell 进程也会缓冲用户的输入,以实现一些高级的功能:比如命令历史记录或 tab 键自动补全

执行并解析命令


当我们输入完命令之后,就要按下回车键(Enter)来执行命令了


一旦按下回车键,line discipline 解释为换行字符(newline),通常表示为 NL


然后一并将用户的命令转发到 PTY follower ,而 shell 进程跟 follower 相连,shell 拿到命令之后就会去解析并执行


当 shell 进程接收到用户的输入和换行符时,它会开始解析并执行命令。这个过程包括命令解析、查找可执行文件或内置命令,以及执行相应的操作


首先对命令解析成一个一个 token 并进行语法/语义分析,以  ls 命令为例:

  • ls > foo.txt :正确
  • ls > :语法不正确, > 后面缺少内容
  • ls | foo.txt :语义不正确,管道的两端都需要是可运行的进程

然后接着解析那些不是 shell 关键字或者路径的 token,shell 需要知道这些 token 的含义,所以 shell 会去根据下面几个部分去递归查找 token 引用的内容:

  • aliases:命令别名,通常用于缩写复杂的命令(例如 alias ll="ls -lh" )
  • function:函数
  • environment variables:环境变量
  • builtins:shell 内嵌命令(例如 cd pwd exit kill)
  • PATH executables:shell 可以找到(通过 $PATH 变量)并运行的外部命令

我们可以通过 type 命令知道对应的类型

[root@minion1 ~]# type ll
ll 是 'ls -l --color=auto' 的别名

[root@minion1 ~]# type cd
cd 是 shell 内嵌

[root@minion1 ~]# type python
python 是 /usr/bin/python


与 shell 内嵌命令不同的是,可执行命令是单独的程序或脚本文件,具有执行权限,可以作为单独的进程执行


当用户在 shell 中输入一个命令时,shell 会查找可执行文件的位置,并在找到后创建一个新的子进程来运行该可执行文件,并将相应的命令参数传递给这个新的子进程


我们可以通过 pstree 命令来查看进程之间的关系

返回输出


当 shell 执行完命令之后,把生成的输出写入到 PTY follower ,接着传到 line discipline 中,line discipline 不会处理这些输出,而是转发给 PTY leader,然后终端就会读取并显示到屏幕上


参考文章:https://www.warp.dev/blog/what-happens-when-you-open-a-terminal-and-enter-ls

- END -

原文作者:咸鱼运维杂谈;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论
最新的技术文章首先发布在微信公众号:咸鱼运维杂谈 擅长Linux系统维护、开源软件维护、自动化运维等领域,博客主要偏向于学习笔记及经历分享

注册时间:2021-05-29

  • 博文量
    193
  • 访问量
    84228