Я не изучал сам экран в глубине, но я написал программу, которая была вдохновлена его на конечного пользователя, и я могу описать, как шахта работает:
Проект мой эмулятор терминала, который имеет эмуляцию ядром, передним интерфейсом 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
Когда присоединять начинается и не может подключиться к существующему процессу, он ветвится и создает съемный бэкенд:
https://github.com/adamdruppe/terminal-emulator/blob/master/attach.d#L454
Пути отделения переднего конца и бэкэнда в отдельные процессы, закрывая один оставляет другого нетронутым. Экран тоже делает это: запустите ps aux | grep -i screen. Процессы 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
, и вы можете видеть два отдельных процессов. экран разветвлен и сделан ЭКРАН, который фактически содержит состояние.Отсоединение убивает процесс 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 и, в меньшей степени, мой терминал клиентской библиотеки (считающая: пользовательские 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, и, хотя они не идентичны, они похожи, поэтому, возможно, вы также сможете получить больше идей, просматривая их.
Вы знаете, как работает vncserver? Это в основном то же самое, но с pty и текстом вместо X-сервера и пикселей. Каждый новый сеанс экрана работает как фоновый процесс, и клиенты могут подключаться к нему через fifos in/var/run/screen. –
Большое вам спасибо! – csteifel