Gnu screen GNU屏幕实际上是如何工作的

Gnu screen GNU屏幕实际上是如何工作的,gnu-screen,Gnu Screen,因此,我一直在试图找到一些关于GNU屏幕如何在不必阅读源代码的情况下以高速度工作的信息,但我一直无法做到这一点 屏幕做了什么,即使在终端会话关闭时,它也能保持不变?它是否作为守护进程或其他什么运行,每个调用screen的人都只是连接到它,然后它会找到要附加到哪个伪tty会话,还是它做了一些完全不同的事情?在这个问题中有很多潜在的问题,所以我将只集中在一个问题上: 屏幕做了什么,即使在终端会话关闭时,它也能保持不变 屏幕捕捉HUP信号,所以当其控制终端离开时不会自动退出。相反,当它获得HUP时,它

因此,我一直在试图找到一些关于GNU屏幕如何在不必阅读源代码的情况下以高速度工作的信息,但我一直无法做到这一点


屏幕做了什么,即使在终端会话关闭时,它也能保持不变?它是否作为守护进程或其他什么运行,每个调用screen的人都只是连接到它,然后它会找到要附加到哪个伪tty会话,还是它做了一些完全不同的事情?

在这个问题中有很多潜在的问题,所以我将只集中在一个问题上:

屏幕做了什么,即使在终端会话关闭时,它也能保持不变


屏幕捕捉HUP信号,所以当其控制终端离开时不会自动退出。相反,当它获得HUP时,它进入后台模式(因为它不再连接实际的终端)并等待。当您使用各种-d/-d/-r/-r/-RR选项启动screen时,它会查找已经运行的screen进程(可能在收到HUP后分离,和/或可能通过发送HUP直接分离),并接管该screen进程的子终端会话(一种协作过程,在此过程中,旧的screen进程将所有主PTY发送到新进程,以便其在退出之前进行管理)。

我没有深入研究screen本身,但我在用户端编写了一个受其启发的程序,我可以描述我的程序是如何工作的:

该项目是我的终端仿真器,它有一个仿真核心、一个gui前端、一个终端前端和两个类似屏幕的组件:attach.d和detaccable.d

attach.d是前端。它通过unix域套接字连接到特定的终端,并将活动屏幕的输出转发到实际的终端。它还向后端进程发送消息,告诉它从头开始重新绘制以及其他一些事情(还有更多事情,我的东西还不完美)

My terminal.d library提供了一个事件循环,用于转换终端输入和信号。其中一个是HUP信号,在控制终端关闭时发送。当它看到这一点时,前端连接进程关闭,后端进程保持不变:

当attach启动且无法连接到现有进程时,它会分叉并创建可分离的后端:

通过将前端和后端分离为单独的进程,关闭其中一个进程会使另一个进程保持不变。Screen也会这样做:运行ps aux | grep-i屏幕。所有caps屏幕进程都是后端。前端是小写屏幕进程

me        3479  0.0  0.0  26564  1416 pts/14   S+   19:01   0:00 screen 
root      3480  0.0  0.0  26716  1528 ?        Ss   19:01   0:00 SCREEN  
在这里,我刚刚启动了
screen
,您可以看到这两个独立的进程。screen分叉并生成screen,它实际上保存了状态。分离会杀死进程3479,但保留进程3480

我的后端是一个完整的终端仿真器,维护所有内部状态:

这里:它从套接字读取,读取消息,并将其作为终端输入转发给应用程序

这里的重画方法:循环通过其内部屏幕缓冲区(存储为属性和字符数组),并将它们写回连接的终端

您可以看到,这两个源文件都不是很长——大部分工作都是在终端仿真器核心中完成的。在较小的程度上,还有我的终端客户端库(想想:自定义ncurses lib)

Attach.d您可以看到,它还管理多个连接,使用
select
在每个打开的插槽中循环,并且仅绘制活动屏幕:

我的程序为每个单独的终端屏幕运行一个单独的后端进程。GNU屏幕对整个会话使用一个进程,可能有多个屏幕。我猜屏幕在后端的工作比我多,但基本上是相同的原则:观察每个pty上的输入并更新内部屏幕缓冲区。当您运行<代码>screen-r要连接到它,它通过文件系统中的命名管道-a FIFO连接(在我的gnu屏幕配置中,它们存储在
/tmp/screens
)而不是我使用的unix套接字,但原理相同-它将状态转储到屏幕上,然后来回转发信息


无论如何,我被告知我的源代码比screens和xterm的源代码更容易阅读,虽然不完全相同,但它们是相似的,所以也许你也可以从中获得更多的想法。

你知道vncserver是如何工作的吗?基本上是一样的,但它使用pty和文本,而不是X服务器和像素。每个新的屏幕会话都作为后台运行und进程,客户端可以通过/var/run/screen中的FIFO连接到它。有趣的是,这不是答案,因此超出了SO的QA格式。问题是“屏幕如何工作”。答案与我上面描述的非常相似。类似于有人问“bash如何工作?”还有人写了一篇关于如何编写shell的教程。这并不完全是bash的工作原理(为此,您可以只看它自己的源代码),但它非常相似,并给出了解释,使实际的源代码更加清晰。