像 top 这样的命令如何在不附加到控制台的情况下更新输出?

Pav*_*van 8 linux unix console putty terminal-emulator

我通过 PuTTY 终端模拟器使用 SSH 连接到远程 Linux 服务器。我注意到我运行的命令和控制台上的输出不断附加在终端窗口中。我的意思是,当我使用滚动条并向上/向下滚动时,我可以看到我之前运行的命令及其输出,就像在打印纸上一样。但是,某些命令如top不断更新输出而不显示为附加在控制台上。它是如何工作的?

Aus*_*arn 17

这里可能有两种机制在起作用。

一种是使用 ANSI 转义码(在某些情况下还有其他非 ANSI 代码),正如 Martin Prikryl 在他们的回答中提到的,来实现基于文本的伪图形接口。最起码的就是两个特定的 ANSI 转义码^[[2J,它会擦除​​屏幕上的所有内容,以及^[[;H,将光标移动到屏幕的左上角。通过组合这些,您可以一个一个地写出每个“帧”的内容,而无需添加到回滚缓冲区中。大多数应用程序实际上使用的不仅仅是那些(例如,有一组代码可以在任意方向上移动光标,使用这些代码跳过应该是“空”的屏幕部分是很正常的)。在实践中,大多数(但绝不是全部)较大的应用程序使用 libcurses(或更常见的是 ncurses)或直接等效物来为它们处理所有这些。

另一种可能性,通常结合使用 ANSI 转义码来操作屏幕内容,是最初由 xterm 提供的特殊功能,但现在被大多数像样的终端模拟器广泛实现,称为备用屏幕缓冲区。有一对转义码(^[[?1049h^[[1049l) 用于在此缓冲区和常规回滚缓冲区之间切换。通过在呈现文本 UI 之前切换到备用屏幕缓冲区,程序可以完全避免更改回滚缓冲区,这不仅可以防止您在滚动时不必拦截通常会滚动的按键,还可以让程序执行以下操作:让您在程序运行之前检查现有的终端内容(并在您打开全屏应用程序之前更容易查看您在做什么)。


Pet*_*ica 10

你所观察到的是历史发展的产物。

最早的交互终端是真神电传打字机;本质上是连接到电话线的电动打字机。(有没有想过为什么 /dev/ tty的命名方式如此命名?)您可以输入文本命令(使用 iirc,甚至是一些基本的、笨拙的行编辑)并获得文本输出。

当然,那些只能从左到右和自上而下移动。哦等等,这不是真的!他们可以使用 Ctrl-H 返回一个字符并再次输入,使其加粗。看哪,这就是某些程序仍然为打印机执行格式化文本的操作。电传打字机也有一些基本的控制代码,如换行、换页或铃声。

迈向基于 CRT 的终端的步骤是合乎逻辑的,即使只是为了保存树木。但从那以后,每一个终端(模拟器)都提供了电传打字机的基本功能:除非另有说明(使用著名的转义序列),接收到的 7 位 ASCII 代码,包括基本控制代码,被解释为相应的字符或命令并从左到右、从上到下显示,从终端维护的当前光标位置开始。

但是由于智能终端实际上​​能够在屏幕上的任意行/列位置显示字符,因此它们都有一些方法可以通过控制代码序列以编程方式做到这一点,并且操作系统以一种或另一种方式配置为使用正确的序列. 一些程序,特别是编辑器、shell 和其他交互式的、面向用户的程序(如 top)使用此功能来控制整个屏幕。

这种“视觉模式”并不常见的原因是,简单地输出没有“装饰”的线性字符序列是非常通用的——同时对于广泛的输出来说已经足够了:您可以打印表格数据,这些数据本质上仍然是带有空格(空格、制表符、换行符)的一系列字符序列。带有管道和设备的整个 Unix/Linux 生态系统都是围绕这个范例构建的。它允许您将 find、grep、cut 等“积木”插入在一起并自动处理文本信息。如果输出与定位和格式化命令混合在一起,那将是完全不可能的。


Mar*_*ryl 7

大多数命令只是将行打印到终端。终端客户端只是像古代行式打印机那样打印这些行。回滚是从打印机出来的无尽纸张的表示。

但是终端客户端(又名终端模拟器)可以做更多的事情,包括像在屏幕上移动光标这样的事情,从而允许服务器(远程应用程序)在“终端屏幕”的任意点上打印。这就是像topvi、 Midnight Commander 等应用程序让我们实现全屏“GUI”界面(实际上是TUI 界面)。这些高级功能是使用ANSI 转义码实现的