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

时间:2014-12-31 23:16:34

标签: gnu-screen

所以我一直试图找到一些关于GNU屏幕如何实际工作的信息,而不必实际阅读源代码,但我无法这样做。

即使终端会话关闭,屏幕还能做什么?它是作为一个守护进程运行的吗?每个调用屏幕的人只是连接到它然后它找到要附加的伪tty会话或者它做了一些完全不同的事情?

2 个答案:

答案 0 :(得分:4)

在这个问题上有很多潜在的问题,所以我只专注于一个:

  

即使终端会话关闭,屏幕能做什么呢?

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

答案 1 :(得分:2)

我没有深入研究过Screen本身,但是我在用户端写了一个受它启发的程序,我可以描述一下我的工作方式:

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

https://github.com/adamdruppe/terminal-emulator

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

https://github.com/adamdruppe/terminal-emulator/blob/master/attach.d

我的terminal.d库提供了一个转换终端输入和信号的事件循环。其中之一是HUP信号,它们在控制终端关闭时发送。当它看到时,前端附加过程关闭,留下后端进程:

https://github.com/adamdruppe/terminal-emulator/blob/master/attach.d#L709

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

https://github.com/adamdruppe/terminal-emulator/blob/master/attach.d#L454

通过将前端和后端分成单独的过程,关闭一个使另一个完整。屏幕也这样做:运行ps aux | grep -i屏幕。全部大写SCREEN进程是后端。前端是小写的屏幕进程。

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,它实际上保持着状态。分离杀死过程3479,但将过程3480留在原位。

我的后端是一个完整的终端模拟器,可以维持所有内部状态:

https://github.com/adamdruppe/terminal-emulator/blob/master/detachable.d

这里:https://github.com/adamdruppe/terminal-emulator/blob/master/detachable.d#L140它从套接字附件中读取,读取消息,并将其作为终端输入转发给应用程序。

重绘方法,这里:https://github.com/adamdruppe/terminal-emulator/blob/master/detachable.d#L318遍历其内部屏幕缓冲区 - 存储为属性和字符数组 - 并将它们写回连接的终端。

您可以看到两个源文件都不是很长 - 大部分工作都是在终端仿真器核心中完成的。 https://github.com/adamdruppe/terminal-emulator/blob/master/terminalemulator.d以及在较小程度上我的终端客户端库(想想:custom ncurses lib)https://github.com/adamdruppe/arsd/blob/master/terminal.d

Attach.d你可以看到管理多个连接,使用select遍历每个打开的套接字,只绘制活动屏幕:https://github.com/adamdruppe/terminal-emulator/blob/master/attach.d#L300

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

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