How to disable tty or enable tty console in Linux ( RHEL / CentOS 7)
How to enable tty for more than 6 console. How to disable all the tty terminals in Linux. systemd disable tty. systemd enable tty using getty service in Linux.
I have written another article to understand the difference between /dev/tty and /dev/pts . In this article I will share the steps to disable tty and enable tty for specific terminal consoles in Linux.
Basic overview on TTY
- tty consoles are managed by systemd in Red Hat Enterprise Linux 7 OS.
- tty consoles are created on-the-fly upon access.
- The allowed number of consoles can be configured in /etc/systemd/logind.conf file.
- Set NAutoVTs= value in this file to desired number to have systemd capable of generating those many tty consoles.
- By default there are 6 terminals available on a Linux system which can be accessed using Ctrl+Alt+F4
Disable TTY terminal console
To disable tty terminal make the below changes in /etc/systemd/logind.conf
Now since our aim is to disable all the terminals, we will leave the value as » N » for ReserveVT . With this step you have disabled all the available terminals. Now you can manually enable the required terminals.
Enable TTY terminal console
For the demonstration of this article I will enable console access for terminal 2 and 3 on my Linux host.
Create a symlink of a tty you want to enable in /etc/systemd/system/getty.target.wants .
Enable tty using systemctl:
Verify the changes
Next reboot the node to activate the changes
Once the node is successfully UP post reboot, attempt to connect to other terminals using Ctrl+Alt+F5 and you will observe that all these terminals will be disabled although terminal 1-3 will be enabled because of our configuration.
Lastly I hope the steps from the article to enable or disable tty on Linux was helpful. So, let me know your suggestions and feedback using the comment section.
How to find all serial devices (ttyS, ttyUSB, ..) on Linux without opening them?
What is the proper way to get a list of all available serial ports/devices on a Linux system?
In other words, when I iterate over all devices in /dev/ , how do I tell which ones are serial ports in the classic way, that is, those usually supporting baud rates and RTS/CTS flow control?
The solution would be coded in C.
I ask because I am using a third-party library that does this clearly wrong: It appears to only iterate over /dev/ttyS* . The problem is that there are, for instance, serial ports over USB (provided by USB-RS232 adapters), and those are listed under /dev/ttyUSB*. And reading the Serial-HOWTO at Linux.org, I get the idea that there’ll be other name spaces as well, as time comes.
So I need to find the official way to detect serial devices. The problem is that none appears to be documented, or I can’t find it.
I imagine one way would be to open all files from /dev/tty* and call a specific ioctl() on them that is only available on serial devices. Would that be a good solution, though?
Update
hrickards suggested to look at the source for «setserial». Its code does exactly what I had in mind:
First, it opens a device with:
If that call returns no error, then it’s a serial device, apparently.
I found similar code in Serial Programming/termios, which suggested to also add the O_NOCTTY option.
There is one problem with this approach, though:
When I tested this code on BSD Unix (that is, Mac OS X), it worked as well. However, serial devices that are provided through Bluetooth cause the system (driver) to try to connect to the Bluetooth device, which takes a while before it’ll return with a timeout error. This is caused by just opening the device. And I can imagine that similar things can happen on Linux as well — ideally, I should not need to open the device to figure out its type. I wonder if there’s also a way to invoke ioctl functions without an open, or open a device in a way that it does not cause connections to be made?
How to close a tty
I’ve opened several ttys and I don’t know the key combination to use to close a tty. I’m using Arch Linux.
2 Answers 2
«Closing» a TTY
- If systemd is not the init being used then this will not help you.
- sysvinit is no longer supported by Arch Linux
systemd ‘s systemctl is used to control all the service units on the system. To learn more about it reference man systemd.unit . Stopping the getty service on the desired tty will perform the task in question. Below is the command to perform this action and I’ve also added a test so you can comfirm the results.
# systemctl stop getty@ttyX.service
- Replace X with the tty number you would like to close
- If [F4] was used to switch to the tty then the service is named getty@tty4.service .
- This procedure will also close all applications/clients ran from the specified tty .
Виртуальные твари и места их обитания: прошлое и настоящее TTY в Linux
Ubuntu интегрирована в Windows 10 Redstone, Visual Studio 2017 обзавелась поддержкой разработки под Linux – даже Microsoft сдает позиции в пользу растущего числа сторонников Торвальдса, а ты всё еще не знаешь тайны виртуального терминала в современных дистрибутивах?
Хочешь исправить этот пробел и открываешь исходный код? TTY, MASTER, SLAVE, N_TTY, VT, PTS, PTMX… Нагромождение понятий, виртуальных устройств и беспорядочная магия? Всё это складывается в довольно логичную картину, если вспомнить, с чего всё началось…
1. START FROM SCRATCH & KEEP CALM
TTY: ПАЛЕОЗОЙ
Мы шагнули прямиком в тридцатые годы XX века и оказались в совсем еще молодой Teletype Corporation. Прямо перед нами перед нами Тот-С-Которого-Всё-Началось – телетайп, представляющий из себя «буквопечатающий телеграф», который передает текстовые сообщения между двумя абонентами.
Абонент А набирает на клавиатуре символы, которые преобразуются в электрические сигналы. По самому обычному кабелю сигналы «бегут» на телетайп абонента Б и уже там печатаются на самой обычной бумаге. Если сигнал дуплексный, то нам крупно повезло, и абонент Б может сразу написать свой ответ; если нет – то ему потребуется сначала подсоединить второй провод для обратной связи.
Здесь, на Teletype Corporation, еще не знают, какое будущее в скором времени ждет их продукт, и уж конечно не подозревают, что аббревиатура TTY намного переживет сам телетайп. Не будем портить для них интригу, пойдем дальше.
TTY: МЕЗОЗОЙ
Прошло сорок лет, мы в лаборатории Digital Equipment Corporation, любуемся первым мини-компьютером (интерактивным!) PDP-1. Для ввода и вывода информации, а также для обеспечения взаимодействия с пользователем к нему подключен уже знакомый нам телетайп.
Дело в том, что ведущие инженерные умы решили велосипед не изобретать и приспособить уже имеющийся дешевый и доступный механизм под новые нужды. Телетайп напрямую подключили к компьютеру (а не к другому телетайпу, как это было раньше) и назвали это дело консолью. Оператор, осуществляющий ввод, видит, как набираемые символы мгновенно печатаются на бумаге, но происходит это без участия ОС – благодаря сохранению в консоли принципа печатающей машинки.
TTY: ПАЛЕОГЕН
Оказываемся в самом начале 80-ых годов, на этот раз в Bell Laboratories. Здесь только что выпущен один из важнейших релизов «раннего» UNIX – Version 7 для PDP-11. Особенности у этого релиза следующие: вводимая пользователем команда теперь отображается по принципу ECHO (набранный на клавиатуре символ сначала попадает в буфер накопления и только потом ОС отправляет инструкцию вывести этот символ на печать), поддерживаются простые возможности редактирования вводимых команд (можно «стирать» символ или целую строку, перемещать каретку), появляется разделение режимов:
- raw mode (редактирование строки не производится; управляющие последовательности распознаются как обычные символы; введенный символ немедленно передается процессу);
- cooked mode (происходит распознавание специальных символов и генерирование сигналов остановки и прерывания для процесса; передача готовой строки процессу осуществляется только после нажатия клавиши Return).
Вполне ожидаемый вопрос: как же можно «стереть» то, что уже напечатал телетайп? Для наглядного выполнения операций редактирования Unix Version 7 предусмотрена печать определенных символов: например, @ — стереть всю строку, # — стереть последний символ. То есть, если наш телетайп напечатал ld@lk#s, и оператор нажал Return, то на исполнение пошла команда ls. Это еще не TTY LINE DISCIPLINE (о ней речь пойдет дальше), но уже большой шаг вперед в отношении обработки ввода на уровне ОС.
Кстати говоря, Digital Equipment Corporation за эти 20 лет не только разработала упомянутый PDP-11, но и подумала о том, как усовершенствовать телетайп: появились так называемые умные терминалы.
Смотрим направо: это VT100, один из первых терминалов, умеющих работать в любви и согласии с PDP-11 и поддерживаемый Unix Version 7.
На уровне ОС и консоль, и умный терминал сейчас воспринимаются как символьные устройства, которые подключаются через интерфейс UART, преобразовывающий асинхронный поток данных в последовательность символов. Для ОС они в принципе идентичны, разница лишь в том, стирать ли символы на экране терминала или печатать символ забоя с помощью телетайпа.
Слева показана в общих чертах схема взаимодействия компьютера и консоли (или умного терминала). У этой схемы есть один недостаток, который совсем не радует оператора консоли PDP-11: с одной консолью ассоциируется одна сессия (или сеанс), в котором пользователь может в фоновом режиме запустить несколько процессов, однако активным в один момент времени на одном TTY будет только один.
И наш бедный оператор вынужден в прямом смысле этого слова переходить от одной консоли к другой, если вдруг ему придет в голову поработать с несколькими сессиями.
TTY: НЕОГЕН
Мы очутились в редакции журнала «PC MAGAZINE», рассматриваем свежий выпуск от 13 января 1987 года. Один из разворотов активно убеждает нас не жалеть денег на ПК с UNIX System V. Каковы аргументы? В частности – grep, awk, sort, split, cut, paste, vi, ed – word processing явно шагнул вперед. И самое интересное: к нашим услугам сейчас эмуляторы терминалов! Благодаря виртуальным консолям, уже можно запустить целых четыре сессии без нужды подключать всё новые и новые физические телетайпы.
Кроме того, жизнь монохромных терминалов нынче можно расцветить: поддерживается CGA, Hercules, EGA графика. Бедолага-оператор может вздохнуть спокойно, телетайп (а также умный терминал) в виде железного зверя угрожает ему только в ночных кошмарах.
Посоветуем оператору лишь одно: ни за что не лезть в директорию /dev – ведь его ждут там аж несколько ttyX и напоминают о том, что под капотом виртуальной консоли живет всё тот же старый-добрый телетайп.
TTY: АНТРОПОГЕН
На предыдущем шаге мы убедились: консоль сделали виртуальной (не будет же солидное издание «PC MAGAZINE» лгать). Что это значит – весь механизм ввода/вывода переписан и в корне изменен? Тогда почему виртуальное устройство – всё еще ttyX? Всё просто: виртуальная консоль эмулируется как самая что ни на есть физическая, а место UART-драйвера, вероятно, занимает кто-то другой. Изменившуюся схему подробно обсудим чуть дальше.
До финишной прямой один шаг, но пропустить его мы не можем хотя бы из уважения к Линусу Торвальдсу. Сейчас 1993 год, и мы наконец имеем счастье рассматривать исходный код Linux 0.95. Почему именно этот релиз? Именно в нем уже сформировалась TTY-абстракция, наиболее близкая к тому, что мы имеем в самых последних дистрибутивах: оформились три обособленных слоя (TTYX — TTY_LINE_DISCIPLINE — TTY_DRIVER).
Кроме того, спустя всего год будет выпущен Linux 1.0, где появится оконный интерфейс, предоставленный проектом XFree86. С этого момента к виртуальным консолям добавятся в придачу еще виртуальные терминалы, которые пользователь (в почти не ограниченном количестве) сможет запускать, не покидая графическую оболочку… Однако прежде, чем окунуться в тонкости и детали усовершенствованной io-магии, вернемся в наше настоящее к Ubuntu 16.04.
2. STOP BEAT AROUND THE BUSH & LOOK INSIDE
ВИРТУАЛЬНЫЕ ТВАРИ И МЕСТА ИХ ОБИТАНИЯ
Лишь некоторые устройства директории /dev/ используются повседневно: /dev/sdaX, /dev/mem, /dev/zero, /dev/random… Но есть несколько групп устройств, которые не часто привлекают наше внимание, однако более чем его заслуживают. Это устройства /ttyX, /vcsX, /vcsaX, а также /ptmx и /pts/X. Собственно говоря, о них и пойдет речь дальше.
И первый наш объект – виртуальная консоль. Каждому такому объекту присущи как минимум сакральное число идентификатор и тотемное животное файл виртуального устройства /tty, коих в виртуальном лесу директории /dev встречают аж 64.
Проверим, есть ли у нас возможность пообщаться с ними. Выполняем Ctrl-Alt-FX (или chvt X, где X – номер консоли, например, Ctrl-Alt-F1) и замечаем, что X может быть равно 1, 2 … 6. При этом перед нами открывается виртуальная консоль, при первом запуске нам предлагают ввести имя пользователя и пароль и создают для нас новый сеанс работы. Если X равен 7, то мы возвращаемся в родные графические пенаты и понимаем, что /tty7 связан с XServer’ом. Идем дальше. Восемь, девять, десять и так далее до 63 — признаков жизни не подают.
Дело в том, что в Linux есть макрос MAX_NR_CONSOLES (64), определяющий максимально допустимое число виртуальных консолей, которые и представлены 64-мя файлами виртуальных устройств /dev/ttyX. Однако последнее слово остается за параметром ACTIVE_CONSOLES (/etc/default/console-setup), и параметр этот по умолчанию равен шести.
Инициализация консолей происходит в несколько стадий. Сперва ядро, получив управление от Grub’a, в ходе инициализации подсистем вызывает функцию «console_init», которая создает первичную консоль – «boot console», предназначенную для вывода отладочной информации. Это консоль осуществляет вывод символов самым примитивным образом: через «putchar», которая напрямую обращается к BIOS, инициализируя и заполняя структуру biosregs, и осуществляет вывод символа в консоль, используя прерывание 0x10.
Позже, в ходе выполнения «fs-initcall» и «console-initcall» происходит создание виртуальных устройств и структур под 6 полноценных виртуальных консолей – «real console». Активацию этих консолей выполняет первый запущенный ядром процесс /sbin/init, запускающий программу getty, которая выполняет чтение конфигурационных файлов /etc/init/console.conf и /etc/init/ttyX.conf и впоследствии отображает на консоль содержимое файла-приветствия etc/issue и запускает login. Далее XServer инициирует активацию консоли на dev/tty7, на которой запускается графическая оболочка.
Однако у нас есть еще вопросы. Что за неведомый объект /dev/tty0? И если каждый /dev/ttyX — это виртуальное устройство консоли, то зачем нужны /dev/console и /dev/tty? За ответом переходим на tty1 (нажимая Ctrl-Alt-F1) и в фоновом режиме запускаем такой скрипт:
Затем переходим на, скажем, tty4 и ждем несколько секунд. По истечении видим следующую картину:
Распределение ролей становится понятно: /dev/tty0 = /dev/console = текущая консоль, т.е. оба всегда ассоциированы с той консолью, которую мы в данный момент видим перед собой, а /dev/tty «помнит» консоль, с которой стартовал процесс. Поэтому пока наш процесс выполнялся, /dev/tty0 и /dev/console определялись для него по ходу пьесы в зависимости от текущей активной консоли, а вот /dev/tty оставался неизменным.
Не спешим покидать директорию /dev. Здесь еще чуть больше дюжины любопытных объектов: /dev/vcsX (virtual console screen) и /dev/vcsaX (virtual console screen with attributes). Еще один опыт: перемещаемся на tty5 и оставляем какие-нибудь следы своего пребывания, затем переходим в любую другую консоль (пусть ее номер 3), делаем «cat» на /dev/vcs5 и видим именно то состояние консоли 5, в каком мы оставили ее несколько секунд назад. При этом, соответственно, /dev/vcs3 и /dev/vcs (а также /dev/vcsa) относятся к консоли 3, на которой мы находимся в данный момент.
Понимаем, что /dev/vcsX — не что иное как омут памяти устройство виртуальной памяти консоли, позволяющее нам без потерь перемещаться между экземплярами tty. В паре с ним — /dev/vcsaX, который предоставляет базовые сведения о состоянии экрана: цвета, различные атрибуты (напр. мерцание), текущее положение курсора, конфигурацию экрана (количество строк и столбцов). Подытожим увиденное схемой:
ВИД СВЕРХУ ЛУЧШЕ
Теперь остановимся с изучением зоологии tty на какое-то время и перейдем к самой tty-абстракции, частью которой и являются наши виртуальные устройства. Посмотрим на общую структуру tty-комплекса и выделим три компонента:
- /dev/ttyX – виртуальное устройство консоли в файловой системе, которое заняло место UART-драйвера и с которым мы уже знакомы. На этом же уровне располагаются устройства /dev/vcsX и /dev/vcsaX, общение с ними осуществляется непосредственно через /dev/ttyX.
- TTY Line Discipline — драйвер, который делает ECHO набираемой команды и дает нам возможности ее редактирования. Также драйвер этого слоя генерирует сигналы при наборе управляющих последовательностей (^C, ^Z и т.д.). По умолчанию здесь царствует N_TTY, однако этот модуль можно заменить, например, своим драйвером – с этим поэкспериментируем немного позже;
- TTY driver – драйвер, который предоставляет набор методов инициализации и открытия консоли, а также методы, обрабатывающие операции ввода/вывода, приостановку консоли при переключении и возобновление ее работы и, конечно, обеспечивает «передачу» полученной от пользователя команды активному процессу.
Помните жалобы оператора PDP-11? Ему не нравилось тратить время на переходы от одной физической консоли к другой. Сейчас дело обстоит следующим образом: у нас есть по умолчанию 7 виртуальных консолей, а перед ними — офисное кресло на колесиках (разумеется, тоже виртуальное). Когда мы переключаемся с одной консоли на другую, операционная система перемещает наше кресло к нужному tty, а вместе с креслом «переключаются» на него и комплекс физических io-устройств: на мониторе теперь состояние нашей новой консоли, на нее же поступает ввод с клавиатуры и т.п.
При этом процессы от первого tty продолжают работать: считывают команды с файла своей виртуальной консоли, пишут в этой файл, но – так как они оторваны от «кресла» – не получают никаких событий (те же ^C и ^Z) и – так как физические устройства «уехали» вместе с «креслом» – могут только накапливать свой «вывод» в буфере, чтоб отправить его на монитор, как только «кресло» вернется.
ПУТЕШЕСТВИЕ К ЦЕНТРУ ЗЕМЛИ
Да, сверху всё смотрится вполне презентабельно. Но тебе, %username%, вероятно, хочется увидеть, как трехуровневое взаимодействие tty-компонентов реализовано непосредственно в коде? За ответом придется опуститься с небес на землю, даже лучше сказать – под землю, в недра исходного кода Ubuntu (работать будем с ядром версии 4.4).
Сделаем упреждающий ход – разберемся, через какие структуры происходит связывание tty-абстракции в единое целое.
Во-первых, это «tty_struct», у которой есть поле «tty_ldisc» (это структура методов драйвера 2-ого слоя), поле «tty_driver» (это драйвер 3-ого слоя) и тут же «tty_operations» (это структура методов драйвера 3-ого слоя, ради удобства вынесенная прямо в «tty_struct»).
То есть, «tty_struct» обеспечивает доступ к слоям TTY_LINE_DISCIPLINE и TTY_DRIVER. Получили к ней доступ – 2/3 стека tty-абстракции, считай, перед нами. Теперь нам нужно понять, как осуществляется переход от файлов виртуальных устройств к этой самой структуре. Ответ прост: у структуры «tty_file_private» как раз есть поле типа «tty_struct». Следовательно, обращаясь к файлу виртуального устройства на 1-ом уровне, мы с легкостью получаем доступ к уровням повыше.
Пока пазл складывается, но нам этого недостаточно. Продебажим ядро (с помощью qemu и cgdb) и рассмотрим backtrace вывода (эхо) единичного символа, введенного пользователем с клавиатуры:
Итак, мы на I уровне tty-стека. Происходит системный вызов «write», который на нашем tty обрабатывается функцией «tty_write». В нее передаются указатель на структуру файла виртуального устройства и буфер с символом. В функции «tty_write» по файлу происходит получение экземпляра «tty_struct». Принимая игру, «tty_struct» первым делом вызывает драйвер TTY_LINE_DISCIPLINE – «tty_ldisc», место которой по умолчанию занимает N_TTY. Первый уровень пройден!
N_TTY принимает эстафету: в свою очередь вызывает метод «n_tty_write», а затем передает буфер функции «output_process_block», которая, удостоверившись, что мы ввели не символ позиционирования каретки, просит «tty_struct» позвать «tty_driver». Всё верно, мы переходим на III уровень.
«Tty_struct» успешно играет роль посредника, и вот – уже запускается метод «con_write» tty-драйвера по имени «console_driver». Драйвер III-его уровня рад бы выполнить своё дело, но он один, консолей много – с какой надо работать? На помощь опять приходит «tty_struct» и вручает драйверу нужный экземпляр структуры «vc» (она отвечает за состояние своей конкретной консоли и содержит её клавиатурные, экранные установки, а также набор методов графического отображения).
«Сonsole_driver» блокирует консоль и призывает «vc_data» выполнить наконец эхо символа. «Vc_data» с ужасом осознает: к ней обратились не ради вопроса о самочувствии вверенной ей консоли, а ради действия. Это значит лишь одно: пора звать на помощь методы «consw», которые в нашем случае представляет VGA (при другой конфигурации ядра это может быть, например, framebuffer). И точно – VGA споро берется за дело, скрывает курсор, печатает символ, при необходимости прокручивает экран или переходит на новую строку, перемещает и отображает курсор. «Vc» выдыхает: «console_driver» работу принял и консоль разблокировал. Можем выдохнуть и мы, ведь все три уровня успешно пройдены, каждый компонент свою миссию выполнил.
3. KEEP AN EYE ON VIRTUAL TERMINAL
Но это еще не всё: пришло время познакомиться с представителями еще одного класса обитателей /dev – c эмуляторами терминалов. Это те самые xterm или gnome-terminal, которые мы запускаем с консоли, оснащенной графической оболочкой, используя, например, Ctrl-Alt-T или Ctrl-Shift-T.
Живут они в отдельном вольере /dev/pts (=pseudo-terminal slave) и представляют собой файлы под номерами 0, 1, 2 и т.д. Выполняем ps в текущем терминале и видим – мы на /dev/pts/1. Нажимаем Alt+5 – перемещаемся на наш четвертый по порядку открытия терминал, файл виртуального устройства которого /dev/pts/20. На любом терминале нас встречает bash, с каждым терминалом связано своё множество процессов. Пока никаких сюрпризов.
Но заметим: /dev/pts/X создаются динамически, запускаются на одной консоли /dev/tty7, не требуют запуска login и самое интересное – здесь нет правила «кресла»: мы можем открыть несколько виртуальных терминалов и одновременно наблюдать, как происходит работа на каждом из них. В очередной раз у %username% может появиться повод для сомнений: сохраняется ли и здесь принцип tty-абстракции и как в этот принцип вписывается устройство — slave, которым, вероятно, управляет некое устройство — master?
Новый объект не заставляет себя ждать: в единственном экземпляре файл ptmx лежит в той же директории /dev (На самом деле он может быть и не один: если запущено более одной консоли с графической оболочкой). По ману, при открытии /dev/ptmx создается подчиненная часть псевдотерминала /dev/pts/X, связанного со своей ведущей частью «ptm» (обращение происходит через дескриптор файла, но реальный файл не создается). Затем «ptm» передается в функции grantpt и unlockpt, и после всего этого можно открывать непосредственно /dev/pts/X, который будет вести себя точно так же, как виртуальная консоль (за исключением описанных выше особенностей).
Для нас в ключе идеи tty-абстракции это означает следующее: когда пользователь хочет запустить эмулятор терминала, XServer обращается к /dev/ptmx с просьбой создать виртуальное устройство /dev/pts/X. Могущественный «мультиплексер» /dev/ptmx любезно делает это, закрепляет файл устройства за экземпляром терминала и … /dev/pts/X занимает место /dev/ttyX, ему назначается драйвер слоя TTY_LINE_DISCIPLINE, его ласково принимает в свои объятия TTY_DRIVER. Стек над /dev/pts/X принимает уже привычный вид. Задача изучения механизма эмулятора терминала плавно сводится к предыдущей истории с виртуальной консолью, однако его подробное изучение требует отдельной статьи (которая входит в планы на будущее!).
4. LET’S PLAY WITH TTY LINE DISCIPLINE
На секунду вспомним tty-«палеозой»: было время, когда слой TTY_LINE_DISCIPLINE и отдельным слоем-то не был и полноценной современной функциональностью не обладал. Попробуем оценить вес перемен, произошедших с тех пор.
Для начала убедимся, что мы действительно имеем дело с N_TTY:
Всё познается в сравнении, поэтому действуем кардинально и с помощью stty отключаем все полезные фичи N_TTY:
Результат наглядно демонстрирует область ответственности N_TTY, без которой вывод не форматируется, ввод не отображается. Причем, если мы откроем новый терминал, то убедимся в целостности и невредимости его LINE_DISCIPLINE. Полученный эффект наталкивает на мысль: мы точно знаем, какой компонент обрабатывает весь наш ввод, мы можем модифицировать его для каждого виртуального терминала в отдельности и, помнится, мы слышали, что этот компонент можно заменить, загрузив свой модуль.
К сожалению, N_TTY сама по себе является частью ядра. Поэтому за основу возьмем другие драйверы слоя LINE_DISCIPLINE, предусмотренные в Linux и загружаемые в виде модулей. По их образу и подобию модифицируем файл исходного кода n_tty.c:
- Добавим функцию отгрузки модуля, в которой вызывается функция tty_register_ldisc, осуществляющая «знакомство» ядра с нашей персональной линией дисциплины. В эту функцию первым параметром передадим ее уникальный идентификатор, а вторым – указатель на структуру с методами драйвера.
- Добавим функцию «выгрузки» модуля, в которой вызывается, соответственно, функция tty_unregister_ldisc.
- В самой структуре «tty_ldisc_ops» зададим новое имя драйвера.
- Позаботимся о том, чтобы наш модуль «узнал» нужные ему функции из файла tty_io.c (он не радует нас макросами «EXPORT SYMBOL», что заставляет либо дописывать все требуемые функции вручную, либо линковать вместе с tty_io.c).
Теперь добавим какой-нибудь функционал, отличающий нашу линию дисциплины от оригинальной. Помним, что именно TTY_LINE_DISCIPLINE обрабатывает служебные последовательности, поэтому грех не поколдовать на этом поприще. Для этого открываем функцию «n_tty_receive_char_special», в которой TTY_LINE_DISCIPLINE проверяет, не является ли введенные символы специальными и при нахождении оных посылает соответствующий сигнал. Для примера поменяем местами сигналы, генерирующиеся для Ctrl+Z и Ctrl+С:
После этого получим из нашего модифицированного файла непосредственно модуль ядра our_ldisc.ko. Загрузим его, убедимся, что загрузка произошла успешно. Проверим, что «our_modyfied_ldisc» действительно зарегистрировалась как TTY_LINE_DISCIPLINE. Откроем терминал и посмотрим номер pts. После этого назначим наш драйвер ответственным за слой TTY_LINE_DISCIPLINE у /dev/pts/X:
Настроим новую линию дисциплины с помощью команды «stty echo cooked» — теперь терминал работает в привычном для нас режиме. Запустим тестовую программу с вечным циклом и сравним эффект Ctrl+Z и Ctrl+С:
Мы добились желаемого: генерация сигналов переопределена на уровне драйвера слоя TTY_LINE_DISCIPLINE в индивидуальном порядке для одного эмулятора терминала! Есть поле для работы фантазии: от фокусов с обработкой служебных последовательностей до кастомизированного фильтра команд.
В ЗАКЛЮЧЕНИЕ
Теперь для тебя, %username%, тайны виртуальных консолей и эмуляторов терминала – больше не тайны, беспорядочная магия – не магия, а технология, прошедшая немалый путь, чтоб создать гибкую подсистему tty, а телетайп – не артефакт древности, а изобретение (кстати говоря, наше, отечественное), без потомков которого современный компьютер представлять как-то не хочется.
Мы любим рассказывать увлекательные истории. Хочешь послушать их вживую? Приходи на «Очную ставку» NeoQUEST-2017, там тебя ждёт множество интересных докладов: от «железа» до криптографии! Вход свободный при регистрации на сайте.