回滚和回滚缓冲区究竟是什么?

Ole*_*leg 29 shell terminal buffer tty scrolling

什么是“回滚”,并在节目像“滚动缓冲区”bashscreen,以及它们如何涉及到TTY,正在运行的程序,标准输入/输出/标准错误?

这是迄今为止我发现的“回滚”的唯一定义(在archlinux wiki 中):

回滚是在文本控制台中实现的一项功能,它允许用户返回查看已滚出屏幕的文本行。这是通过在视频适配器和显示设备之间为此目的创建的缓冲区实现的;回滚缓冲区。

但是,这给我带来了更多的问题:

  • 它的意思是“子程序”中的“功能”还是“功能”中的“功能”?
  • 此回滚缓冲区是否有 Unix 标准或 API?
  • 在程序的“堆栈”中,例如在终端模拟器vimscreen启动的bash启动中ssh启动,这些程序中的哪些正在控制回滚缓冲区?

我也用screen,以转储回溯到一个文件中。这个文件的顶部有很多空白,我的终端模拟器显示的“视图”似乎只是缓冲区底部的几行。

  • 这就是为什么像这样的程序vim可以“清除”我的整个终端窗口,因为它可以临时访问父 shell 的回滚缓冲区?
  • 还是vim使用它自己的回滚缓冲区,该缓冲区以某种方式覆盖在父回滚缓冲区之上?

Mic*_*mer 37

这是一个有点复杂的问题。我将尝试依次回答您的问题,但首先是一般描述:

回滚缓冲区由您的终端模拟器(xterm、Konsole、GNOME 终端)实现。它包含屏幕上显示的所有文本,包括您在终端中运行的每个程序的标准输出和标准错误。它完全是终端功能,可让您查看可能已经滚动过您的过去输出或检查之前所说的内容。

您可以将回滚缓冲区视为一长页记录输出,而您的终端窗口则是一个在任何时候只查看其中一部分的窗口。如果您还没有向上滚动,那么您看到的是缓冲区的尾端。通常会在终端中配置一个限制,限制它在开始忘记之前跟踪多少行。

假设限制是 1000 行。对于会话中的前一千行输出,您只需将其附加到缓冲区,然后向上滚动到会话开始处。获得第 1001 行输出后,缓冲区中的第一行将被擦除,您可以滚动的最远的将是会话的第二行。缓冲区将始终包含屏幕上显示的最新一千行输出,您可以随时向上滚动以查看较早的输出。

  • 它的意思是“子程序”中的“功能”还是“功能”中的“功能”?

    这是“功能”和“功能”一样。终端模拟器具有记录屏幕内容并让您在其中上下滚动的功能。某些系统上的控制台还支持有限回滚。

    一旦你投入其中,它就会变得更加复杂screen。在这一点上,screen正在模拟回滚缓冲区本身 - 这就是为什么您可以在程序中从它复制和粘贴,而不仅仅是(比如)X 选择。

  • 此回滚缓冲区是否有 Unix 标准或 API?

    简短的回答是否定的,它只是由您的终端提供。我们将在底部得到更长的答案。

  • 在程序的“堆栈”中,例如在终端模拟器中启动的 ssh 中启动的 bash 中启动的屏幕中启动的 vim,这些程序中的哪些正在控制回滚缓冲区?

    vimand的情况下bash,他们根本没有控制它(警告,再次,下面)。您的终端为其中的所有程序提供了回滚缓冲区,从您的 shell 开始。screen,如上所述,模拟回滚本身。

  • 我还使用 screen 将回滚转储到文件中。这个文件的顶部有很多空白,我的终端模拟器显示的“视图”似乎只是缓冲区底部的几行。

    这是screen的内部缓冲区。当时屏幕上的内容通常是缓冲区最底部的内容。

  • 这就是为什么像 vim 这样的程序可以“清除”我的整个终端窗口的原因,因为它可以临时访问父 shell 的回滚缓冲区?

    这是它变得更加复杂的一部分。几乎所有基于 X 的终端仿真器都在模拟 VT100,他们所做的一件事就是支持“备用屏幕缓冲区”。与用于与顺序输出的大多数终端交互的普通缓冲区不同,备用屏幕缓冲区只是终端的确切大小。它没有向上或向下滚动,因为它不比显示的大。

    其想法是让全屏应用程序执行其需要执行的操作,而不会受到屏幕上已有的任何内容的干扰,然后让您完全返回到之前的显示状态。这就是为什么当你输入vim它时它会填满整个屏幕,但是当你离开它时,你之前的终端输出——你过去的所有提示和命令输出——又回来了。vim启动时切换到备用屏幕缓冲区,退出时切换回正常缓冲区。

    这个备用缓冲区是我上面提到的警告之一。有时,程序确实有能力告诉终端如何处理缓冲区。

    screen是另一个执行此操作的程序,这就是为什么当您处于屏幕会话时终端的滚动功能通常不起作用的原因 - screen模拟回滚缓冲区本身,因此您必须使用其内部功能来获取旧输出。

  • 或者 vim 是否使用自己的回滚缓冲区,该缓冲区以某种方式覆盖在父回滚缓冲区之上?

    我在上一个问题中主要回答了这个问题,但对这个特定问题的简短回答是,vim确实从终端获得了自己的临时缓冲区,没有回滚,然后在内部执行所有自己的文档滚动。

我提到的所有这些例外情况:

它再次变得稍微复杂一些。我说过应用程序对回滚没有任何控制权,它完全由终端提供。在某些情况下,与某些终端的交互有限。该程序打印出某些转义序列——如果您过去曾经手动使用过终端着色,您就会看到它们的样子——并且终端可以解释这些并改变其行为,甚至将信息发送回程序。termcap(终端功能)数据库中描述了哪些转义序列可用。

一些终端确实支持对回滚缓冲区的有限查询和操作。许多xterm衍生产品具有指示终端滚动其视图的转义序列。许多终端还支持指定屏幕的特定区域进行滚动,其余部分保持不变。这往往会破坏回滚缓冲区。

几乎所有终端都支持在屏幕上移动光标的序列,这就是ncurses库能够更新显示的所有不同部分的方式。您可以查看支持xtermVT100 序列。这些与回滚缓冲区交互的方式有时可能有点奇怪,特别是在实现自己的滚动行为的情况下,例如less命令。您最终可能会在回滚中出现重复或丢失的行,因为less以您的终端没有预料到的方式在顶部重新绘制文本。其他程序有时最终会用整个显示的多个副本填充您的缓冲区。

  • 非常感谢您的精彩回答!尽管主题很复杂,但它非常完整且易于理解。额外的细节既让我想要了解更多,也让我知道去哪里寻找。 (2认同)