56星座屋
当前位置: 首页 星座百科

终端中有一个进程在运行(当你在终端上按下一个键时会发生什么)

时间:2023-05-23 作者: 小编 阅读量: 2 栏目名: 星座百科

我复刻了它,使它能与最新的xterm.js一起工作,因为它最后一次更新是在6年前。它必须由服务器进程明确地告诉它来显示它。2004h是告诉终端显示什么或其他东西。我相信当我们按CtrlC时,cat被中断的原因是服务器端的Linux内核收到这个\x03字符,识别出它意味着“中断”,然后发送一个SIGINT到拥有伪终端的进程组。\x04对应于ASCII“传输结束”。

我对终端Terminal是怎么回事困惑了很久。

但在上个星期,我使用 xterm.js在浏览器中显示了一个交互式终端,我终于想到要问一个相当基本的问题:当你在终端中按下键盘上的一个键(比如Delete,或Escape,或a),发送了哪些字节?

像往常一样,我们将通过做一些实验来回答这个问题,看看会发生什么 : )

远程终端是非常古老的技术

首先,我想说的是,用 xterm.js在浏览器中显示一个终端可能看起来像一个新事物,但它真的不是。在 70 年代,计算机很昂贵。因此,一个机构的许多员工会共用一台电脑,每个人都可以有自己的 “终端” 来连接该电脑。

例如,这里有一张 70 年代或 80 年代的 VT100 终端的照片。这看起来像是一台计算机(它有点大!),但它不是 —— 它只是显示实际计算机发送的任何信息。

EC_VT100_terminal.jpg">

当然,在 70 年代,他们并没有使用 Websocket 来做这个,但来回发送的信息的方式和当时差不多。

(照片中的终端是来自西雅图的 活电脑博物馆Living Computer Museum,我曾经去过那里,并在一个非常老的 Unix 系统上用ed编写了 FizzBuzz,所以我有可能真的用过那台机器或它的一个兄弟姐妹!我真的希望活电脑博物馆能再次开放,能玩到老式电脑是非常酷的。)

发送了什么信息?

很明显,如果你想连接到一个远程计算机(用 ssh或使用xterm.js和 Websocket,或其他任何方式),那么需要在客户端和服务器之间发送一些信息。

具体来说:

客户端需要发送用户输入的键盘信息(如ls -l)。服务器需要告诉客户端在屏幕上显示什么。

让我们看看一个真正的程序,它在浏览器中运行一个远程终端,看看有哪些信息会被来回发送!

我们将使用 goterm 来进行实验

我在 GitHub 上发现了这个叫做 goterm的小程序,它运行一个 Go 服务器,可以让你在浏览器中使用xterm.js与终端进行交互。这个程序非常不安全,但它很简单,很适合学习。

我 复刻了它,使它能与最新的xterm.js一起工作,因为它最后一次更新是在 6 年前。然后,我添加了一些日志语句,以打印出每次通过 WebSocket 发送/接收的字节数。

让我们来看看在几个不同的终端交互过程中的发送和接收情况吧!

示例:ls

首先,让我们运行 ls。下面是我在xterm.js终端上看到的情况:

~:/play$ lsfile~:/play$

以下是发送和接收的内容:(在我的代码中,我记录了每次客户端发送的字节:sent: [bytes],每次它从服务器接收的字节:recv: [bytes]

sent: "l"recv: "l"sent: "s"recv: "s"sent: "\r"recv: "\r\n\x1b[?2004l\r"recv: "file\r\n"recv: "\x1b[~:/play$ "

我在这个输出中注意到 3 件事:

  1. 回显:客户端发送 l,然后立即收到一个l发送回来。我想这里的意思是,客户端真的很笨 —— 它不知道当我输入l时,我想让l被回显到屏幕上。它必须由服务器进程明确地告诉它来显示它。
  2. 换行:当我按下回车键时,它发送了一个 \r'(回车)符号,而不是\n'(换行)。
  3. 转义序列:\x1b是 ASCII 转义字符,所以\x1b[?2004h是告诉终端显示什么或其他东西。我想这是一个颜色序列,但我不确定。我们稍后会详细讨论转义序列。

好了,现在我们来做一些稍微复杂的事情。

示例:Ctrl C

接下来,让我们看看当我们用 Ctrl C中断一个进程时会发生什么。下面是我在终端中看到的情况:

~:/play$ cat^C~:/play$

而这里是客户端发送和接收的内容。

sent: "c"recv: "c"sent: "a"recv: "a"sent: "t"recv: "t"sent: "\r"recv: "\r\n\x1b[?2004l\r"sent: "\x03"recv: "^C"recv: "\r\n"recv: "\x1b[?2004h"recv: "~:/play$ "

当我按下 Ctrl C时,客户端发送了\x03。如果我查 ASCII 表,\x03是 “文本结束”,这似乎很合理。我认为这真的很酷,因为我一直对Ctrl C的工作原理有点困惑 —— 很高兴知道它只是在发送一个\x03字符。

我相信当我们按 Ctrl C时,cat被中断的原因是服务器端的 Linux 内核收到这个\x03字符,识别出它意味着 “中断”,然后发送一个SIGINT到拥有伪终端的进程组。所以它是在内核而不是在用户空间处理的。

示例:Ctrl D

让我们试试完全相同的事情,只是用 Ctrl D。下面是我在终端看到的情况:

~:/play$ cat~:/play$

而这里是发送和接收的内容:

sent: "c"recv: "c"sent: "a"recv: "a"sent: "t"recv: "t"sent: "\r"recv: "\r\n\x1b[?2004l\r"sent: "\x04"recv: "\x1b[?2004h"recv: "~:/play$ "

它与 Ctrl C非常相似,只是发送\x04而不是\x03。很好!\x04对应于 ASCII “传输结束”。

Ctrl其它字母呢?

接下来我开始好奇 —— 如果我发送 Ctrl e,会发送什么字节?

事实证明,这只是该字母在字母表中的编号,像这样。

  • Ctrl a=> 1
  • Ctrl b=> 2
  • Ctrl c=> 3
  • Ctrl d=> 4
  • ...
  • Ctrl z=> 26

另外,Ctrl Shift b的作用与Ctrl b完全相同(它写的是0x2)。

键盘上的其他键呢?下面是它们的映射情况:

  • Tab-> 0x9(与Ctrl I相同,因为 I 是第 9 个字母)
  • Escape->\x1b
  • Backspace->\x7f
  • Home->\x1b[H
  • End->\x1b[F
  • Print Screen->\x1b\x5b\x31\x3b\x35\x41
  • Insert->\x1b\x5b\x32\x7e
  • Delete->\x1b\x5b\x33\x7e
  • 我的 Meta键完全没有作用

Alt呢?根据我的实验(和一些搜索),似乎AltEscape在字面上是一样的,只是按Alt本身不会向终端发送任何字符,而按Escape本身会。所以:

  • altd=>\x1bd(其他每个字母都一样)
  • altshiftd=>\x1bD(其他每个字母都一样)
  • 诸如此类

让我们再看一个例子!

示例:nano

下面是我运行文本编辑器 nano时发送和接收的内容:

recv: "\r\x1b[~:/play$ "sent: "n" [[]byte{0x6e}]recv: "n"sent: "a" [[]byte{0x61}]recv: "a"sent: "n" [[]byte{0x6e}]recv: "n"sent: "o" [[]byte{0x6f}]recv: "o"sent: "\r" [[]byte{0xd}]recv: "\r\n\x1b[?2004l\r"recv: "\x1b[?2004h"recv: "\x1b[?1049h\x1b[22;0;0t\x1b[1;16r\x1b(B\x1b[m\x1b[4l\x1b[?7h\x1b[39;49m\x1b[?1h\x1b=\x1b[?1h\x1b=\x1b[?25l"recv: "\x1b[39;49m\x1b(B\x1b[m\x1b[H\x1b[2J"recv: "\x1b(B\x1b[0;7mGNU nano 6.2 \x1b[44bNew Buffer \x1b[53b \x1b[1;123H\x1b(B\x1b[m\x1b[14;38H\x1b(B\x1b[0;7m[ Welcome to nano.For basic help, type Ctrl G. ]\x1b(B\x1b[m\r\x1b[15d\x1b(B\x1b[0;7m^G\x1b(B\x1b[m Help\x1b[15;16H\x1b(B\x1b[0;7m^O\x1b(B\x1b[m Write Out\x1b(B\x1b[0;7m^W\x1b(B\x1b[m Where Is\x1b(B\x1b[0;7m^K\x1b(B\x1b[m Cut\x1b[15;61H"

你可以看到一些来自用户界面的文字,如 “GNU nano 6.2”,而这些 \x1b[27m的东西是转义序列。让我们来谈谈转义序列吧!

ANSI 转义序列

上面这些 nano发给客户端的\x1b[东西被称为“转义序列”或 “转义代码”。这是因为它们都是以 “转义”字符\x1b开头。它们可以改变光标的位置,使文本变成粗体或下划线,改变颜色,等等。维基百科介绍了一些历史,如果你有兴趣的话可以去看看。

举个简单的例子:如果你在终端运行

echo -e '\e[0;31mhi\e[0m there'

它将打印出 “hi there”,其中 “hi” 是红色的,“there” 是黑色的。本页有一些关于颜色和格式化的转义代码的例子。

我认为有几个不同的转义代码标准,但我的理解是,人们在 Unix 上使用的最常见的转义代码集来自 VT100(博客文章顶部图片中的那个老终端),在过去的 40 年里没有真正改变。

转义代码是为什么你的终端会被搞乱的原因,如果你 cat一些二进制数据到你的屏幕上 —— 通常你会不小心打印出一堆随机的转义代码,这将搞乱你的终端 —— 如果你cat足够多的二进制数据到你的终端,那里一定会有一个0x1b的字节。

可以手动输入转义序列吗?

在前面几节中,我们谈到了 Home键是如何映射到\x1b[H的。这 3 个字节是Escape[H(因为Escape\x1b)。

如果我在 xterm.js终端手动键入Escape,然后是[,然后是H,我就会出现在行的开头,与我按下Home完全一样。

我注意到这在我的电脑上的 Fish shell 中不起作用 —— 如果我键入 Escape,然后输入[,它只是打印出[,而不是让我继续转义序列。我问了我的朋友 Jesse,他写过一堆 Rust 终端代码,Jesse 告诉我,很多程序为转义代码实现了一个超时—— 如果你在某个最小的时间内没有按下另一个键,它就会决定它实际上不再是一个转义代码了。

显然,这在 Fish shell 中可以用 fish_escape_delay_ms来配置,所以我运行了set fish_escape_delay_ms 1000,然后我就能用手输入转义代码了。工作的很好!

终端编码有点奇怪

我想在这里暂停一下,我觉得你按下的键被映射到字节的方式是非常奇怪的。比如,如果我们今天从头开始设计按键的编码方式,我们可能不会把它设置成这样:

  • CtrlaCtrlShifta做的事情完全一样。
  • AltEscape是一样的
  • 控制序列(如颜色/移动光标)使用与 Escape键相同的字节,因此你需要依靠时间来确定它是一个控制序列还是用户只是想按Escape

但所有这些都是在 70 年代或 80 年代或什么时候设计的,然后需要永远保持不变,以便向后兼容,所以这就是我们得到的东西 :smiley:

改变窗口大小

在终端中,并不是所有你能做的事情都是通过来回发送字节发生的。例如,当终端被调整大小时,我们必须以不同的方式告诉 Linux 窗口大小已经改变。

下面是 goterm中用来做这件事的 Go 代码的样子:

syscall.Syscall(syscall.SYS_IOCTL,tty.Fd,syscall.TIOCSWINSZ,uintptr(unsafe.Pointer(&resizeMessage)),)

这是在使用 ioctl系统调用。我对ioctl的理解是,它是一个系统调用,用于处理其他系统调用没有涉及到的一些随机的东西,通常与 IO 有关,我猜。

syscall.TIOCSWINSZ是一个整数常数,它告诉ioctl我们希望它在本例中做哪件事(改变终端的窗口大小)。

这也是 xterm 的工作方式。

在这篇文章中,我们一直在讨论远程终端,即客户端和服务器在不同的计算机上。但实际上,如果你使用像 xterm 这样的终端模拟器,所有这些工作方式都是完全一样的,只是很难注意到,因为这些字节并不是通过网络连接发送的。

文章到此结束啦

关于终端,肯定还有很多东西要了解(我们可以讨论更多关于颜色,或者原始与熟化模式,或者 Unicode 支持,或者 Linux 伪终端界面),但我将在这里停止,因为现在是晚上 10 点,这篇文章有点长,而且我认为我的大脑今天无法处理更多关于终端的新信息。

感谢 Jesse Luehrs回答了我关于终端的十亿个问题,所有的错误都是我的 :smiley:

via: https://jvns.ca/blog/2022/07/20/pseudoterminals/

作者:Julia Evans选题:lujun9972译者:wxy校对:wxy

本文由 LCTT原创编译,Linux中国荣誉推出

    推荐阅读
  • 欢乐颂蒋欣穿绿色的衣服哪一集(细数欢乐颂里给我们种的草)

    中国上海,欢乐颂小区19号楼22层住着五个女人。灵感来源于纪梵希高级定制,将高级手工蕾丝融入护肤领域,与独家专利配方具有非凡生命力的"墨藻生命精萃"融合,带来出乎意料的抗老功效。第七集里,樊胜美手上拿的这款纪梵希小羊皮唇膏,也让本公举盯上了!↓兰芝气垫BB霜SPF30PARMB305特殊科技舒缓降温使用后即刻令肌肤温度下降3度,双重容器隔离炎热,维持海绵的温度。《欢乐颂》才播出了13集,就给我们安利了这么多好东西!

  • 梅雨季节衣服不干有味怎么办(梅雨季节衣服不干有味解决方法)

    梅雨季节衣服不干有味怎么办?以下内容希望对你有帮助!黑色能吸收热量及紫外线,并有杀菌功能,并不会出现捂坏的情况,比自然晾晒干得快,特别适合在阴雨天晾衣服用。如果是袜子这样的小件,可以放在正在使用的显示器上烘干。把铁丝衣架两端1/3处用力向前弯曲,衣架变成立体的,晾晒衣服时,前、后身就不会贴在一起,衣物内侧通风可以大大缩短晾晒的时间,阴雨天晾衣服可以快速晾干。

  • 沙漠鹰有哪些(盘点那些生不逢时的战鹰们)

    但是军方却不买账。美国空军于1991年4月23日宣布YF-22获选优胜。YF-23一共只有生产两架原型机,目前都已经不再飞行。1991年4月8日,美国陆军宣布波音、西科斯基公司小组获胜,LHX随之进入原型机研制阶段。运-10由于各种原因最终没有投产。,2000年2月29日首飞,只有1架技术验证机。1969年1月,在完成了最后一次试验飞行之后,被送进俄亥俄州的怀特,帕特森空军基地博物馆。

  • 海贼王热血航线怎么参加狙击王的试炼(海贼王热血航线如何参加狙击王的试炼)

    下面更多详细答案一起来看看吧!海贼王热血航线怎么参加狙击王的试炼工具/原料:华为P40,MIUI12.0.0.1,海贼王热血航线1.0.7。第一步玩家们登录自己的大区,在游戏的主页面找到玩法选项。这里我们需要选择的是第一个游戏狙击王点击进入。

  • 阿胶糕速冻一年还能不能食用(阿胶糕速冻一年还能食用吗)

    阿胶糕放这种食物在冰箱中冷藏了一年,这个时候是不可以食用的冷藏通常至少可以保质一个星期左右,即便是冷冻,也只只可以保质2个月到3个月之间,接下来我们就来聊聊关于阿胶糕速冻一年还能不能食用?阿胶糕速冻一年还能不能食用阿胶糕放这种食物在冰箱中冷藏了一年,这个时候是不可以食用的。而到了七八月的炎热天,高温也有可能导致阿胶融化。因此,不建议食用保存超过两个月的阿胶。

  • 2021广州国际汽车展览会门票多少钱(广州国际汽车展览会2020门票)

    第十九届广州国际汽车展览会将于2021年11月19日至28日在中国进出口商品交易会展馆举办,11月19日为媒体日。欢迎全球观众、媒体及业内人士前来参观。2021广州国际汽车展览会门票多少钱?11月19日为媒体日,仅对国内外媒体及特邀嘉宾开放。

  • 孩子咳嗽感冒流鼻涕小妙招(小孩感冒咳嗽流鼻涕)

    闺女感冒了,咳嗽,流鼻涕。按照医嘱按时吃药会很快好起来。于是改用第二方案,拿个吸管,放在奶瓶盖中,让小家伙吸,无效,屁孩知道是药仍抗拒。改用第三方案,拿小勺子喂,无效,甚至打翻药。于是又软下来苦口婆心地劝说,让她乖点,喝药,妈妈就不离开了,可这小家伙仍拒药,比革命烈士更坚决立场。改用第六方案,滴管滴,可小家伙很快发现是药,只让滴一次,决不上第二次当了。终于搞定这小家伙了。

  • WE战队的成员都是谁啊?(WE战队的成员简述)

    WE战队的成员都是谁啊WE.IGE的队员包括有:WE.IGE.Suho:中国第一精灵,左手会跳舞的男人。在第二届中韩对抗赛上勇夺冠军,并在Acon4上取得了季军的成绩。WE.IGE.Sky:Sky流创始人,WCG2005全球总决赛魔兽冠军。我们毫不怀疑其世界顶尖选手的实力。WE.IGE.WyW:中国星际Zerg第一高手。WE.IGE.DuCui:原Lion战队主力,国内顶尖orc玩家。WE.IGE.TeD:国内亡灵新秀,第一届“SoulWar激战台”擂主。

  • 新工科专业有哪些(有这五种)

    新工科专业有哪些?大数据类大数据是众多学科与统计学交叉产生的一门新兴学科,涉及数据挖掘、云计算等数学,我来为大家科普一下关于新工科专业有哪些?云计算,是指“超级计算集群”经过网络输送各种计算机服务及数据。智能科学与技术类。智能科学与技术专业面向前沿高新技术的基础性本科专业,覆盖面很广。光电信息科学与工程类。该专业主要学习光学、机械学、电子学及计算机科学基础理论及专业知识。

  • 人和自然的关系(关系有哪些)

    不论是以屈从于“神”的方式,还是以屈从于“道”的方式,敬畏都是人存在的统一姿势。在这个时期,西方艺术以描绘“神”为主题,东方艺术则以领悟“道”为宗旨。科学革命打破了人类的一切禁忌。神不再是世界的主体,而承载“道”的宇宙则被解释成不过是一群根据万有引力漂浮在太空的平凡球体。于是,无论是西方的神还是东方的道都变得不值一提。战争与环境问题挑战了人类理性的绝对地位。