![回滚和回滚缓冲区到底是什么?](https://linux22.com/image/40076/%E5%9B%9E%E6%BB%9A%E5%92%8C%E5%9B%9E%E6%BB%9A%E7%BC%93%E5%86%B2%E5%8C%BA%E5%88%B0%E5%BA%95%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%9F.png)
bash
和等程序中的“回滚”和“回滚缓冲区”是什么screen
,它们与 tty、正在运行的程序以及 stdin/stdout/stderr 有何关系?
这是迄今为止我发现的“回滚”的唯一定义(在archlinux 维基):
回滚是在文本控制台中实现的一项功能,允许用户返回查看已滚动出屏幕的文本行。这是通过在视频适配器和显示设备之间专门为此目的创建的缓冲区来实现的;回滚缓冲区。
但是,这给我带来了更多问题:
- 它的意思是“子程序”中的“功能”还是“功能”中的“功能”?
- 这个回滚缓冲区有 Unix 标准或 API 吗?
- 在程序“堆栈”中,例如
vim
在终端模拟器中启动screen
的启动中bash
启动的启动中ssh
,这些程序中的哪些程序正在控制回滚缓冲区?
我也screen
曾经将回滚转储到文件。该文件的顶部有很多空白,终端模拟器向我显示的“视图”似乎只是缓冲区的底部几行。
- 这就是为什么像这样的程序
vim
可以“清除”我的整个终端窗口,因为它可以临时访问父 shell 的回滚缓冲区? - 或者是否
vim
使用自己的回滚缓冲区,该缓冲区以某种方式覆盖在父回滚缓冲区之上?
答案1
这是一个有点复杂的问题。我将尝试依次回答您的问题,但首先进行一般性描述:
回滚缓冲区由终端模拟器(xterm
、Konsole、GNOME 终端)实现。它包含屏幕上显示的所有文本,包括终端中运行的每个程序的标准输出和标准错误。它完全是终端功能,可让您查看可能已滚动到您身边的过去的输出或检查之前所说的内容。
您可以将回滚缓冲区视为一长页记录的输出,并将终端窗口视为在任何时候仅查看其中一部分的窗口。如果您没有向上滚动任何内容,那么您看到的是缓冲区的尾部。通常,终端中会配置一个限制,限制在开始忘记之前要跟踪多少行。
假设限制为 1000 行。对于会话中的前一千行输出,您只需将其附加到缓冲区,然后可以直接向上滚动到会话的开头。一旦获得第 1001 行输出,缓冲区中的第一行就会被删除,您可以滚动到的最远位置将是会话的第二行。缓冲区将始终包含屏幕上显示的最新一千行输出,并且您可以随时向上滚动以查看较早的输出。
它的意思是“子程序”中的“功能”还是“功能”中的“功能”?
这就是“功能”和“特征”。终端模拟器具有记录屏幕上内容并允许您在其中上下滚动的功能。某些系统上的控制台还支持有限的回滚。
screen
一旦你加入其中,事情就会变得更加复杂。此时,screen
正在模拟回滚缓冲区本身 - 这就是为什么您可以在程序中复制并粘贴它,而不是仅使用(例如)X 选择。这个回滚缓冲区有 Unix 标准或 API 吗?
简短的回答是否定的,它只是由您的终端提供的。较长的答案我们将在底部找到。
在程序“堆栈”中,例如在屏幕中启动的 vim 在终端仿真器中启动的 bash 中启动的 ssh 中启动的这些程序中的哪些程序正在控制回滚缓冲区?
vim
在和的情况下bash
,他们根本无法控制它(再次警告,如下)。您的终端从 shell 开始为其中的所有程序提供回滚缓冲区。screen
如上所述,正在模拟回滚本身。我还使用 screen 将回滚转储到文件中。该文件的顶部有很多空白,终端模拟器向我显示的“视图”似乎只是缓冲区的底部几行。
这是
screen
的内部缓冲区。当时屏幕上显示的内容通常是缓冲区最底部的内容。这就是为什么像 vim 这样的程序可以“清除”我的整个终端窗口,因为它可以临时访问父 shell 的回滚缓冲区吗?
这是事情变得更加复杂的部分之一。几乎所有基于 X 的终端仿真器都在模拟 VT100,它们所做的一件事就是支持“备用屏幕缓冲区”。与用于大多数终端与顺序输出交互的普通缓冲区不同,备用屏幕缓冲区恰好是终端的大小。其中没有向上或向下滚动,因为它不大于显示的内容。
这个想法是允许全屏应用程序执行它需要执行的操作,而不会受到屏幕上已有的任何内容的干扰,然后让您返回到之前的显示状态。这就是为什么当您输入时
vim
它会填满整个屏幕,但是当您离开它时,您之前的终端输出(所有过去的提示和命令输出)会再次出现。vim
启动时切换到备用屏幕缓冲区,退出时切换回正常缓冲区。这个备用缓冲区是我上面提到的警告之一。有时,程序确实有能力告诉终端如何处理缓冲区。
screen
是另一个执行此操作的程序,这就是为什么当您处于屏幕会话中时,终端的滚动功能通常不起作用 -screen
模拟回滚缓冲区本身,因此您必须使用其内部功能来获取旧输出。或者 vim 是否使用自己的回滚缓冲区,该缓冲区以某种方式覆盖在父回滚缓冲区之上?
我在上一个问题中主要回答了这个问题,但对这个特定问题的简短回答是,它
vim
确实从终端获取自己的临时缓冲区(没有回滚),然后在内部执行文档的所有滚动。
我提到的所有这些例外:
它再次变得稍微复杂一些。我说过应用程序对回滚没有任何控制权,它完全由终端提供。在某些情况下,与某些终端的交互是有限的。该程序打印出某些转义序列 - 如果您过去曾经手动使用过终端着色,您就会看到它们的样子 - 并且终端可以解释这些序列并更改其行为,甚至将信息发送回程序。哪些转义序列可用,请参见termcap(终端能力)数据库。
某些终端确实支持回滚缓冲区的有限查询和操作。许多xterm
衍生产品都有转义序列,可以引导终端滚动其视图。许多终端还支持指定屏幕的特定区域进行滚动,而其余部分保持不变。这往往会破坏回滚缓冲区。
几乎所有终端都支持在屏幕上移动光标的序列,这就是ncurses
库能够更新显示的所有不同部分的方式。你可以看看VT100 序列支持xterm
。它们与回滚缓冲区交互的方式有时可能有点奇怪,特别是在实现自己的滚动行为的情况下,例如命令less
。您最终可能会在回滚中出现重复或缺失的行,因为less
以终端未预期的方式在顶部重新绘制了文本。其他程序有时最终会用整个显示的多个副本填充您的缓冲区。