Windows Terminal – новый взгляд на старые вещи – Записки IT специалиста

Tty_set_operations

Функция tty_set_operations() всего лишь устанавливает таблицу функций для текущего драйвера:

void tty_set_operations(struct tty_driver *driver,
            const struct tty_operations *op)
{
    driver->ops = op;
};

Структура tty_operations — это таблица функций, которая используется для доступа к функциям драйвера TTY устройства.

Выделю самое главное в структурах pty_unix98_ops и ptm_unix98_ops, которые являются таблицей функций для соответствующих частей псевдотерминала:

static const struct tty_operations ptm_unix98_ops = {
    .install = pty_unix98_install,
    .remove = pty_unix98_remove,
    .open = pty_open,
    .close = pty_close,
    .write = pty_write,
    // ...
};

static const struct tty_operations pty_unix98_ops = {
    .install = pty_unix98_install,
    .remove = pty_unix98_remove,
    .open = pty_open,
    .close = pty_close,
    .write = pty_write,
    // ...
};

Здесь можете наблюдать уже знакомую по статье о Сишном printf функцию pty_write — к ней мы вернемся чуть позднее.

Давайте добавим данную структуру в нашу корзину компонентов:
Windows Terminal - новый взгляд на старые вещи - Записки IT специалиста

Как видите, основные методы обоих драйверов совсем не отличаются. Кстати, заметьте, что отсутствует функция для read() операции — нет ничего похожего на pty_read(). Дело в том, что чтение будет обслуживаться исключительно дисциплиной линии. Таким образом, мы узнаём о второй важной особенности дисциплины линии — чтение данных с TTY утройства.

Ptmx_open

Теперь перейдем к ptmx_open():

static int ptmx_open(struct inode *inode, struct file *filp)
{
    struct tty_struct *tty; // запомните эту структуру - она очень важна!
    fsi = devpts_acquire(filp); // получаем виртуальную файловую систему devpts

    index = devpts_new_index(fsi); // получаем индекс для нового устройства в /dev/pts
    // ...
    tty = tty_init_dev(ptm_driver, index);
    // ...
    devpts_pty_new(fsi, index, tty->link); // создаём новый файл в /dev/pts

    retval = ptm_driver->ops->open(tty, filp); // открываем PTM устройство, ничего особенного
}

Нас интересует функция tty_init_dev(), где первым аргументом является драйвер PTM устройства, а вторым — индекс устройства. Здесь мы покидаем зону ответственности PTY драйвера и переходим к файлу, который отвечает только за общие TTY устройства и ничего не знает о нашем псевдотерминале.

struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
{
    struct tty_struct *tty;
    tty = alloc_tty_struct(driver, idx);

    retval = tty_driver_install_tty(driver, tty);

    /*
     * Structures all installed ... call the ldisc open routines.
     */
    retval = tty_ldisc_setup(tty, tty->link); // ничего необычного, просто открывает дисциплину линии обоих устройств

    return tty;
}

Сначала разберем функцию alloc_tty_struct():

struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx)
{
    struct tty_struct *tty;

    tty = kzalloc(sizeof(*tty), GFP_KERNEL); // создаем tty_struct

    tty_ldisc_init(tty) // создает дисциплину линии для текущей tty_struct

    tty->driver = driver; // устанавливает ссылку на драйвер в текущей tty_struct
    tty->ops = driver->ops;  // устанавливает ссылку на операции драйвера в текущей tty_struct. Сделано просто для удобства
    tty->index = idx; // устанавливает индекс tty устройства

    return tty;
}

Единственное, что нас здесь интересует, это функция tty_ldisc_init():

int tty_ldisc_init(struct tty_struct *tty)
{
    struct tty_ldisc *ld = tty_ldisc_get(tty, N_TTY);
    if (IS_ERR(ld))
        return PTR_ERR(ld);
    tty->ldisc = ld; // устанавливает ссылку на дисциплину линии в текущей tty_struct
    return 0;
}

Которая вызывает tty_ldisc_get():

static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc)
{
    struct tty_ldisc *ld; // структура дисциплины линии
    struct tty_ldisc_ops *ldops; // таблица функций дисциплины линии

    ldops = get_ldops(disc); // получает операции для выбранной дисциплины линии. Дело в том, что дисциплины линии могут быть разного типа. Наш тип - N_TTY

    ld = kmalloc(sizeof(struct tty_ldisc), GFP_KERNEL | __GFP_NOFAIL);
    ld->ops = ldops; // устанавливает таблицу функций для текущей дисциплины
    ld->tty = tty; // устанавливает ссылку на tty_struct в текущей дисциплине. Это требуется для доступа к драйверу устройства из дисциплины

    return ld;
}

Итак, мы рассмотрели вызов функции alloc_tty_struct(), которая создает структуру tty_struct вместе с дисциплиной линии — структурой tty_ldisc. Обе структуры имеют ссылки друг на друга. Давайте познакомимся с данными структурами поближе.

struct tty_struct {
    struct tty_driver *driver; // драйвер TTY устройства
    const struct tty_operations *ops; // операции драйвера. Это то же самое, что и driver->ops, то есть сделано просто для удобства
    int index; // индекс устройства
    struct tty_ldisc *ldisc; // указатель на дисциплину линии
    struct tty_struct *link; // указатель на другую часть PTY
    // ...
}
struct tty_ldisc {
    struct tty_ldisc_ops *ops; // таблица функций дисциплины
    struct tty_struct *tty; // указатель на tty_struct текущей дисциплины. Используется для доступа к драйверу устройства
};

Вроде бы ничего сложного? Давайте добавим все рассмотренные до этого момента структуры в нашу корзину и свяжем их таким же образом, как они связаны в коде:
Строение tty_struct

Но мы создали tty_struct всего лишь для PTM устройства. А что же о PTS устройстве? Для этого вернемся к функции tty_init_dev() и вспомним о том, что дальше нас ожидает вызов функции tty_driver_install_tty():

/**
 * This method is responsible
 * for ensuring any need additional structures are allocated and configured. 
*/
static int tty_driver_install_tty(struct tty_driver *driver,
                        struct tty_struct *tty)
{
    return driver->ops->install ? driver->ops->install(driver, tty) :
        tty_standard_install(driver, tty);
}

Terminal

Terminal (терминал) — это комбинация дисплея и клавиатуры, то есть физическое устройство. До того, как терминалы стали именно данной комбинацией, они являлись неким устройством под названием teleprinter (teletype, teletypewriter или TTY сокращенно), то есть комбинацией принтера и клавиатуры.

Обычно несколько терминалов подключались к одному и тому же компьютеру. Таким образом возможно было работать нескольким пользователям за одним и тем же компьютером, причем каждому выделялась своя сессия, независимая от других. Терминал был назван так потому, что он находился на конце терминального кабеля (terminal end).

Это Teletype:

Teletype

А это Terminal:

Terminal

Terminal emulator

Terminal Emulator — эмулятор старого доброго терминала. Эмулятор терминала требуется для программ, которые не могут напрямую взаимодействовать с X Window System — Bash, Vim и прочие.

Давайте для начала установим обязанности терминала:

  1. Передача ввода пользователя в компьютер
  2. Доставка вывода компьютера на дисплей

Так и наш Terminal Emulator выполняет абсолютно то же самое: он доставляет ввод пользователя в запущенную программу, а также отображает вывод программы на дисплей. В любом случае, смысл сохраняется — между пользователем и запущенной программой, существует какой-то слой, отвечающий за ввод/вывод. Примеры Terminal Emulator: gnome-terminal, xterm, konsole.

Прошу не путать Shell и Terminal Emulator!Terminal Emulator — GUI приложение, то есть окно в X Window System. Shell — это command line interpreter, то есть просто исполнитель команд, он не имеет графической оболочки. Если говорить совсем правильно, вы не запускаете Bash, вы запускаете Terminal Emulator, который запускает внутри себя Bash.

Далее в статье все упоминания терминала будут относиться к эмулятору терминала.

Terminal emulator и pseudoterminal

Каждый раз, когда мы открываем новый терминал в X Window System, GNOME Terminal Server порождает новый процесс и запускает в нём выбранную по умолчанию программу. Обычно, это какой-то Shell (например, Bash).

Общение с запущенной программой происходит через так называемый Pseudoterminal (псевдотерминал, PTY). Сам псевдотерминал существует в ядре, однако ввод получает из пользовательского пространства — из эмулятора терминала.

Псевдотерминал состоит из следующих двух виртуальных TTY устройств:1) PTY master (PTM) — ведущая часть псевдотерминала. Используется GNOME Terminal Server для передачи ввода с клавиатуры в запущенную внутри терминала программу, а также для чтения вывода программы и отображения вывода на дисплей.

GNOME Terminal Server в свою очередь общается с X Window System по X протоколу.2) PTY slave (PTS) — ведомая часть псевдотерминала. Используется программой, запущенной внутри терминала, для чтения ввода с клавиатуры и отображения вывода на экран. По крайней мере, так думает сама программа (объясню, что это значит, чуть далее).

Любые данные, записанные в PTS устройство, являются вводом PTM устройства, то есть становятся доступны для чтения на PTM устройстве. И наоборот: любые данные, записанные в PTM устройство, являются вводом PTS устройства. Именно таким образом и происходит общение GNOME Terminal Server и запущенной внутри терминала программы. Каждому PTM устройству сопоставляется свое PTS устройство.

Процесс запуска нового терминала выглядит примерно следующим образом:1) GNOME Terminal Server создает master и slave устройства с помощью вызова функции open() на специальном устройстве /dev/ptmx. Вызов open() возвращает файловый дескриптор созданного PTM устройства — master_fd.2)

GNOME Terminal Server создает новый процесс с помощью вызова функции fork(). Данный процесс и будет являться новым терминалом.3) В терминале PTS устройство открывается на файловых дескрипторах 0, 1, 2 (stdin, stdout и stderr соответственно).

Теперь стандартные потоки ввода/вывода терминала ведут на данное устройство.4) В терминале запускается нужная программа с помощью вызова функции exec(). Обычно запускается какой-то Shell (например, Bash). Любая программа, запущенная впоследствии из Bash, будет иметь те же файловые дескрипторы, что и сам Bash, то есть потоки программы будут направлены на PTS устройство.

Вы можете сами посмотреть, куда направлены стандартные потоки вывода терминала, с помощью команды ls -la /proc/self/fd:
Windows Terminal - новый взгляд на старые вещи - Записки IT специалиста

PTS устройство находится по пути /dev/pts/N, а путь к PTM устройству нас абсолютно не интересует. Дело в том, что GNOME Terminal Server уже имеет файловый дескриптор открытого PTM устройства и ему не требуется путь к нему, однако в дочернем процессе мы должны открыть PTS устройство на стандартных потоках вывода с помощью вызова функции open(), которая требует путь к файлу.

Помните, я сказал, что программа, использующая PTS устройство, только думает, что она общается напрямую с терминалом? Дело в том, что PTS также является терминальным устройством (TTY устройством), но разница между PTS устройством и действительным TTY устройством в том, что PTS устройство ввод получает не с клавиатуры, а с master устройства, а вывод идет не на дисплей, а на master устройство.

Именно поэтому псевдотерминал назван так — псевдотерминал лишь имитирует (опять??) терминал. Разница между эмулятором терминала и псевдотерминалом в том, что эмулятор терминала — это лишь графическая программа, позволяющая запускать терминал прямо внутри оконного интерфейса, но реализована эта возможность с помощью псевдотерминала.

То, что PTS устройство является TTY устройством — это очень важно. Вот почему:

Tty устройства

Каждому терминалу назначается свое TTY устройство (терминальное устройство), которое обеспечивает работу консоли. Хотя телетайпы вы вряд ли уже найдете, но сокращение TTY дошло и до наших дней.

TTY устройство состоит из двух фундаментальных компонентов:

  1. Драйвер устройства. Он отвечает за доставку ввода с клавиатуры в программу и за отображение вывода программы на экран.
  2. TTY Line Discipline (рус. — дисциплина линии). Дисциплина линии — это интерфейс доступа к драйверу, который, однако, привносит немало логики в TTY устройство. Можно сказать, что дисциплина линии проксирует вызовы к драйверу. Какова зона ответственности данного компонента, мы будем узнавать по ходу статьи.
:/>  Как удалить Xbox Game Bar, DVR и игровой мониторинг в Windows 10

Строение TTY устройства:

Существует 3 типа TTY устройств:

  1. Console device — обеспечивает работу Virtual Console. Ввод и вывод данного устройства управляется полностью ядром.
  2. PTY device (псевдотерминал) — обеспечивают работу терминала в оконном интерфейсе. Ввод и вывод данного устройства управляется эмулятором терминала, который работает в пользовательском пространстве.
  3. Serial device — общается напрямую с железом. Обычно не используется напрямую, а существует как самый нижний уровень в организации архитектуры терминального устройства.

В данной статье мы будем говорить именно о втором типе TTY устройств — псевдотерминалах.

Windows terminal – новый взгляд на старые вещи

windows-terminal-000.pngКазалось бы, что может быть более неизменным, нежели Командная строка Windows? Это приложение, словно живое ископаемое, кажется, помнит времена первых версий Windows NT и Windows 95, возможности тоже остались где-то там, в далеких и светлых днях. То, что терминал нужно менять было понятно еще давно, но не было понятно как. Ведь терминальные приложения в современных ОС это не только командная строка, но и PowerShell, и консоли WSL. Но Microsoft отлично справилась с этой проблемой, новое приложение Windows Terminal способно не только объединить все в одном месте, но и существенно расширить возможности привычных оболочек.

Научиться настраивать MikroTik с нуля или систематизировать уже имеющиеся знания можно на углубленном курсе по администрированию MikroTik. Автор курса, сертифицированный тренер MikroTik Дмитрий Скоромнов, лично проверяет лабораторные работы и контролирует прогресс каждого своего студента. В три раза больше информации, чем в вендорской программе MTCNA, более 20 часов практики и доступ навсегда.

Взаимоотношения Windоws и командной строки долгое время были достаточно прохладными. Основная парадигма управления системой строилась вокруг графических инструментов и мыши, а командная строка рассматривалась как дополнительный атрибут и инструмент восстановления. Ни о каком полноценном управлении системой через терминал речи не шло, даже для автоматизации предлагался отдельный скриптовый язык VBScript.

Все стало меняться с выходом PowerShell и появлением Core-версий Windows – постепенно Microsoft стала осознавать важность консольного инструмента для управления системой, и чаша весов снова качнулась в другую сторону, сегодня ряд продуктов не имеют полноценных графических инструментов настройки, зато предлагают для этого PowerShell. Подсистема Windows для Linux также не предполагает никаких графических инструментов, снова напоминая о том, что терминал не пережиток прошлого, а мощный и удобный инструмент.

Windows Terminal – это современное приложение, демонстрирующее новый взгляд Microsoft на старые вещи, причем не только новый, но и достаточно неожиданный. Это свободное ПО под лицензией MIT исходные коды которого расположены на GitHub и принять участие в его разработке может каждый. Как видим, времена действительно меняются, и компания, еще недавно называвшая открытое ПО “раковой опухолью” теперь выпускает под открытой лицензией один из основных инструментов администрирования.

Продукт доступен в двух версиях: стабильной Windows Terminal и версии для разработчиков и инсайдеров Windows Terminal Preview. Последняя получает все новые функции непосредственно после их разработки и является наиболее интересной и в дальнейшем мы будем рассматривать именно ее.

Рекомендованным способом получения приложения является Microsoft Store, но также возможны и альтернативные методы установки, более подробно о них можно узнать на странице GitHub.

windows-terminal-001.pngПосле установки приложении автоматически добавит профили для всех установленных в системе консольных приложений Windows и WSL, а также будет их автоматически регистрировать при добавлении в систему, например, если вы установите новую версию PowerShell или новый экземпляр Linux в WSL. Кроме того, отдельно добавляется профиль для Azure Cloud Shell. Профилем по умолчанию является встроенный в систему Windows Power Shell.

windows-terminal-002.pngПриятные новшества радуют с первых секунд работы с новым терминалом. Во-первых, это вкладки, теперь ничего не мешает удобно организовать рабочее пространство и не путаться в мешанине окон. Во-вторых – это рендеринг текста поддержкой ускорения на GPU, что дает отличную прорисовку шрифтов и делает текст визуально привлекательным.

windows-terminal-003.pngК сожалению графической оболочки для настройки терминала пока нет, при выборе пункта Параметры будет открыт JSON-файл с настройками, однако это не должно пугать любителя командной строки. В конфигурационном файле сначала идут глобальные параметры, а затем описания профилей. Структура достаточно простая и не должна вызвать особых сложностей.

Прежде всего переопределим командную оболочку по умолчанию. Для этого найдите guid нужного профиля и скопируйте его в опцию defaultProfile:

defaultProfile": "{574e775e-4f2a-5b96-acle-a2962a402336}",

Затем включим привычное Linux-пользователям поведение, когда текст копируется при его выделении и потом может быть вставлен правым кликом мыши:

copyOnSelect": true,

Перейдем к самим профилям. Их настройки достаточно просты и очевидны: это guid, наименование, источник или командная строка запуска и видимость. Если вы не хотите видеть профиль в списке выбора, то просто установите опцию hidden в true, мы таким образом скрыли оболочку Azure.

hidden": true,

windows-terminal-004.pngВсе изменения применяются налету, перезапускать терминал не нужно.

Еще одной долгожданной особенностью являются панели, позволяющие разделить окно терминала на несколько областей. Для разделения по горизонтали нажмите Alt Shift , для разделения по вертикали Alt Shift -, чтобы закрыть панель используйте Ctrl Shift W. При этом в новой панели будет открыта командная оболочка по умолчанию. Чтобы открыть в панели другой профиль просто выберите его из списка с зажатой клавишей Alt. Для дублирования текущего профиля нажмите Alt Shift D. В заголовке вкладки будет отображаться наименование текущей панели.

windows-terminal-005.png

Для изменения размера панелей используйте клавиши со стрелками одновременно зажав Alt Shift, при этом будет меняться размер активной панели.

windows-terminal-006.png

Терминал поддерживает практически полную кастомизацию. Можно изменять цвет, шрифт, фоновое изображение, прозрачность панелей, задавать иконки, также поддерживаются темы, включающие множество настроек для различных вариантов отображения. Мы не будем углубляться так далеко, большее количество настроек можно найти в документации: https://msconfig.ru/ru-ru/windows/terminal/get-started.

Но некоторые настройки мы все-же сделаем. По умолчанию все панели выглядят одинаково, что может приводить к некоторой путанице, поэтому есть смысл изменить цвет фона, чтобы быстро понимать, где какая консоль запущена, для этого добавьте в профиль опцию background с шестнадцатеричным кодом цвета, например, “родной” цвет для PowerShell:

"background": "#012456",

Мы указали для разных консолей привычные цвета и сразу стало гораздо удобнее:

windows-terminal-007.pngТакже очень легко можно создавать свои профили. Допустим мы хотим добавить в терминал подключение по SSH к одному из своих Linux-серверов. Прежде всего для нового профиля нужно получить guid, для этого в среде PowerShell выполните:

[guid]::NewGuid()

windows-terminal-008.pngТеперь добавим в конфигурационный файл секцию нового профиля:

{
"guid": "{437dc877-4e9d-405a-8c86-837093861986}",
"name": "Debian 1C Server",
"commandline": "ssh andrey@192.168.233.141",
"icon": "ms-appdata:///roaming/icons8-console-32.png",
"hidden": false
},

Синтаксис довольно прост, но поясним некоторые параметры. Опция commandline указывает строку запуска, а в опции icon мы задали индивидуальную иконку профиля, для этого можно использовать как ico-файлы, так и обычные png. Иконку следует разместить в специальной директории, для Windows Terminal это:

%LOCALAPPDATA%PackagesMicrosoft.WindowsTerminal_8wekyb3d8bbweRoamingState

Для Windows Terminal Preview:

%LOCALAPPDATA%PackagesMicrosoft.WindowsTerminalPreview_8wekyb3d8bbweRoamingState

После чего к ним можно будет обращаться как:

ms-appdata:///roaming/имя_файла

windows-terminal-009.pngПодобным образом можно добавлять неограниченное число профилей на все случаи жизни и практически к любому приложению. Например. мы создали еще один профиль для работы с командной строкой PostgreSQL, для этого мы заглянули в “родной” bat-файл для запуска и позаимствовали оттуда строку запуска:

{
"guid": "{5507e755-60ae-4d8e-aa01-e75da98b95c8}",
"name": "PSQL Shell",
"commandline": "C:\Program Files\PostgreSQL 1C\10\bin\psql.exe -h localhost -U postgres -d postgres -p 5432",
"icon": "ms-appdata:///roaming/PostgreSQL_logo.png",
"hidden": false
}

Обратите внимание, если это последний профиль в списке, то запятая после закрывающей фигурной скобки не ставится.

windows-terminal-010.pngВ заключение хочется сказать, что новый Windows Terminal нам очень понравился и мы рекомендуем всем, кто еще не пробовал, попробовать работу с ним. Это действительно новый подход Microsoft к старым и привычным вещам и на этот раз у них действительно получилось современное, удобное и динамично развивающееся приложение.

Научиться настраивать MikroTik с нуля или систематизировать уже имеющиеся знания можно на углубленном курсе по администрированию MikroTik. Автор курса, сертифицированный тренер MikroTik Дмитрий Скоромнов, лично проверяет лабораторные работы и контролирует прогресс каждого своего студента. В три раза больше информации, чем в вендорской программе MTCNA, более 20 часов практики и доступ навсегда.

Вкладки и профили

Популярной сейчас функцией является поддержка интерфейса с вкладками, который мы будем определять как одно окно терминала, содержащее в себе еще несколько терминалов. Для разных терминалов эта функция отличается, и хотя традиционные терминалы вида xterm вообще не поддерживают вкладки, более современные инкарнации терминала в лице Xfce Terminal, GNOME Terminal и Konsole эту функцию имеют.

Также поддержка вкладок есть и у Urxvt, но только при условии использования плагина. Но с точки зрения поддержки вкладок как таковых безусловным лидером является Terminator: он не только поддерживает вкладки, но также может размещать терминалы в произвольном порядке (см изображение ниже).

Еще одной особенностью Terminator является возможность «группировать» эти вкладки вместе и посылать одни и те же нажатия клавиш на несколько терминалов одновременно, что обеспечивает грубый инструмент выполнения массовых операций на нескольких серверах одновременно.

Особенно хорошо вкладки работают вкупе с профилями: например, у вас может быть одна вкладка для электронной почты, другая для чата и так далее. Это хорошо поддерживается терминалом Konsole и GNOME Terminal. Оба позволяют каждой вкладке автоматически запускать свой профиль.

Глобальные настройки

Следующие глобальные настройки являются наиболее полезными, хотя другие задокументированы в документации Терминала.

«defaultProfile» определяет GUID профиля, который используется по умолчанию при запуске Windows Terminal.

Установите «copyOnSelect»для trueавтоматического копирования выделенного текста в буфер обмена без необходимости нажимать Ctrl Shift  C.

Установите, «copyFormatting»чтобы falseпросто копировать простой текст без какого-либо стиля. (Хотелось бы, чтобы это было по умолчанию для всех приложений!)

Задайте «initialColumns»и «initialRows«равным количеству знаков для горизонтального и вертикального размеров.

«tabWidthMode» может быть установлен на:

  1. «equal»: каждая вкладка одинаковой ширины (по умолчанию)
  2. «titleLength»: каждая вкладка устанавливается равной ширине ее заголовка, или
  3. «compact»: неактивные вкладки уменьшаются до ширины их значка.

«disabledProfileSources«устанавливает массив, который предотвращает автоматическое создание профилей. Например:

"disabledProfileSources":["Windows.Terminal.Wsl","Windows.Terminal.Azure","Windows.Terminal.PowershellCore"],

Это отключит все сгенерированные профили; удалите те, которые хотите сохранить.

Задержка


После тщательного исследования производительности терминалов я пришел к выводу, что важнейшим параметров в этом плане является размер задержки (пинг). В своей статье

Павел Фатин рассмотрел задержку различных текстовых редакторов и намекнул, что терминалы в этом плане могут работать медленнее, чем самые быстрые текстовые редакторы. Именно этот намек и привел меня, в конечном итоге, к запуску собственных тестов и написанию этой статьи.

:/>  Способы 3 для восстановления удаленных или утерянных файлов после обновления Windows 10

Но что такое задержка, и почему она так важна? В своей статье Фатин определил её как «задержку между нажатием клавиши и соответствующим обновлением экрана» и процитировал «Руководство по взаимодействию человека с компьютером», в котором говорится:

Фатин объясняет, что такой пинг имеет более глубокие последствия, нежели просто удовлетворение: «печатание становится медленнее, возникает больше ошибок, увеличивается напряжение глаз и мышц». Другими словами, большая задержка может привести к опечаткам, а также снижению качества кода, так как приводит к дополнительной когнитивной нагрузке на мозг.

Но что еще хуже, пинг «увеличивает напряжение глаз и мышц», что, по-видимому, подразумевает развитие профессиональных травм в будущем (по всей видимости, автор имеет в виду проблемы с мышцами глаз, спиной, руками и, конечно же, зрением, — прим. пер.) из-за повторяющегося напряжения.

Некоторые из этих эффектов известны давно, а результаты исследования, опубликованного еще в 1976 году в журнале Ergonomics, говорят, что задержка в 100 миллисекунд «значительно ухудшает скорость набора». Совсем недавно в руководстве пользователя GNOME было внесено приемлемое время отклика в 10 миллисекунд, а если идти дальше, то Microsoft Research показывает, что идеалом является 1 миллисекунда.

Фатин проводил свои тесты на текстовых редакторах; он создал портативный инструмент под названием Typometer, который я использовал для проверки пинга в эмуляторах терминала. Имейте в виду, что тест проводился в режиме симуляции: в действительности нам надо учитывать и задержку ввода (клавиатура, USB-контроллер и так далее) и вывода (буфер видеокарты, монитор).

По словам Фатина, в типичных конфигурациях она составляет около 20 ms. При наличии геймерского оборудования можно достигнуть показателя всего в 3 миллисекунды. Так как у нас уже есть такое быстрое оборудование, приложение не должно вносить еще и свою задержку.

А вот результаты моих измерений, а также некоторые результаты Фатина для того, чтобы показать, что мой эксперимент согласуется с его тестами:

Первое, что меня поразило — это лучшее время отклика у старых программ, таких как xterm и mlterm. С наличием худшей задержки регистра (2,4 ms) они показали результат лучше, чем самый быстрый современный терминал (10,6 ms для st). Ни один современный терминал не опускается ниже порога в 10 миллисекунд.

В частности, Alacritty не соответствует требованиям к «самому быстрому из существующих эмуляторов терминала», хотя его результаты улучшились с момента первой проверки в 2022 году. Действительно, авторы проекта в курсе ситуации и работают над улучшением отображения.

Также необходимо отметить, что Vim, использующий GTK3, на порядок медленнее своего аналога GTK2. Из этого можно сделать вывод, что GTK3 создает дополнительную задержку, и это отражается на всех прочих терминалах, которые его используют (Terminator, Xfce4 Terminal и GNOME Terminal).

Однако для глаза отличия могут быть незаметны. Как объясняет Фатин: «не обязательно осознавать наличие задержки, чтобы она имела на вас эффект». Фатин также предупреждает о стандартном отклонении: «любые нарушения в длительности задержки (дрожание) создают дополнительную нагрузку из-за их непредсказуемости».

График выше взят получен на чистом Debian 9 (stretch) с i3 window manager. Эта среда дает наилучшие результаты в тестах на определение задержки. Как оказалось, GNOME создает дополнительный пинг в 20 ms для всех измерений. Возможное объяснение этому — наличие программ с синхронной обработкой входных событий.

Фатин приводит для такого случая в пример Workrave, который добавляет задержку обрабатывая все input-события синхронно. По умолчанию GNOME также оснащен менеджером окон Mutter, которые создает дополнительный уровень буферизации, что влияет на пинг и добавляет минимум 8 миллисекунд задержки.

Зачем это нужно:

Выполнение некоторых задач с помощью Терминала может быть намного быстрее, чем с помощью графических приложений и меню. Еще одно преимущество — доступ к большему количеству команд и сценариев.

Обычная задача терминала по установке приложения может быть выполнена с помощью одной команды, по сравнению с перемещением через Центр программного обеспечения или Synaptic Manager.

Например, следующий код установит клиент BitTorrent Deluge:

 sudo apt-get install deluge 

Чтобы сохранить подробный список файлов в текущем дереве каталогов в файл с именем isting.txt :

 find -type f>  list.txt 

Иногда вы также увидите следующие обозначения:

 $ whoamicalum $ lsDownloads Documents 

Это означает, что выполняется команда whoami , которая дает в качестве вывода calum . После этой команды выполняется ls , который выводит Downloads Documents .

Аналогичное обозначение:

 # apt-get update 

Это означает, что команда должна запускаться от имени пользователя root, то есть с использованием sudo :

 $ sudo apt-get update 

Обратите внимание, что символ # также используется для комментариев .

 # эта команда даст ваше имя пользователяwhoami # следующая команда покажет содержимое текущего каталога 

Как загрузить в консольный (текстовый) режим с помощью debian/ubuntu, fedora, arch linux/manjaro и др.

В этой статье объясняется, как загрузить дистрибутив Linux, такой как Debian, Ubuntu, Fedora, Arch Linux/Manjaro и т. д., в консольном режиме, временно или постоянно.

Инструкции в этой статье должны работать с любым дистрибутивом Linux, который использует systemd (для постоянного режима ниже) и GNU GRUB (для временного режима), но я лично пробовал это только с Debian , Ubuntu, Manjaro и Fedora.

Загрузка в консольном режиме (текстовый режим/tty) позволяет вам войти в вашу систему из командной строки (как обычный пользователь или как пользователь root, если он включен), без использования графического пользовательского интерфейса . Это полезно в случае, если ваша система не загружается при использовании графического режима, или, возможно, у вас есть компьютер под управлением Linux, для которого вы не регулярно используете графический интерфейс и ssh, поэтому вы хотите сэкономить некоторые системные ресурсы, загрузка в текстовом режиме. Но независимо от причины в этой статье показано, как загрузиться с консоли/text/tty в Linux.

Параметры командной строки

Терминал Windows можно запустить с ярлыка или с любого терминала Windows или Linux, запустив его wt.exe. Поддерживаются следующие варианты:

вариантописание
—help, -h, -?,/?отображает справку
—maximized, -Mзапуск максимизирован
—fullscreen, -Fзапускать в полноэкранном режиме

Вы также можете передать список команд, разделенных точкой с запятой. Команды используются для определения новых вкладок и панелей с дополнительными параметрами управления:

командапараметрыописание
new-tab—profileили -p, —startingDirectoryили -d, commandline,—titleоткрыть новую вкладку
split-pane—horizontalили -H, —verticalили -V, —profileили -p, —startingDirectoryили -d, commandline,—titleоткрыть новую панель
focus-tab—target или же -tсфокусировать вкладку

Поддержка юникода

Свои тесты я начал с поддержки юникода. Первым тестом терминалов было отображение оными строки о юникоде из

: «é, Δ, Й, ק, م, ๗, あ, 叶, 葉 и 말». Этот простой тест показывает, может ли терминал корректно работать по всему миру. Терминал xterm не отображает арабский символ

в конфигурации по умолчанию:

По дефолту xterm использует классический «фиксированный» шрифт, который, согласно все той же Вики, имеет «существенный охват юникода с 1997 года». В этом шрифте происходит что-то, что заставляет символ отображаться в виде пустой рамки и только при увеличении шрифта текста до 20 пунктов символ наконец-то начинает отображаться правильно. Однако такой «фикс» ломает отображение других символов юникода:

Эти скриншоты были сделаны в Fedora 27, так как именно она давала лучшие результаты, нежели Debian 9, где некоторые старые версии терминалов (а конкретно — mlterm) не могли должным образом работать со шрифтами. К счастью, это было поправлено в более поздних версиях.

Теперь обратите внимание на отображение строки в xterm. Оказывается, символ Mem и следующий за ним Semitic Qoph относятся к сценариям начертания RTL (right-to-left), поэтому технически они должны отображаться справа налево. Веб-браузеры, например Firefox 57, правильно обрабатывают приведенную выше строку.

«Многие компьютерные программы не могут правильно отображать двунаправленный текст. Например, еврейское имя «Сара» состоит из символов син (ש) (который появляется справа), затем реш (ר) и, наконец, хе (ה) (который должен появляться слева)».


Многие терминалы не проходят этот тест: Alacritty, VTE-производные терминалы Gnome и XFCE, urxvt, st и xterm отображают «Сара» в обратном порядке, как если бы мы записывали это имя как «Арас».

Другая проблема двунаправленных текстов заключается в том, что их надо как-то выровнять, особенно если речь идет о смешении RTL и LTR-текстов. Сценарии RTL должны запускаться с правой стороны окна терминала, но что должно происходить для терминалов, по умолчанию работающих с LTR-английским?

Примеры

Следующие примеры необходимо запускать из стандартной cmdкомандной строки или ярлыка.

Открыть терминал для Windows с Ubuntuи Windows Powershellзакладками:

wt -p "Ubuntu"; new-tab -p "Windows PowerShell"

Откройте Windows Terminal с Ubuntu, Windows Powershell, и Command Promptпрофили в отдельных областях:

wt -p "Ubuntu"; split-pane -V -p "Windows PowerShell"; split-pane -H -p "Command Prompt"

Дополнительные примеры запуска Windows Terminal из оболочки Linux или Powershell доступны в документации Windows Terminal.

Рюшечки

Последнее, что я рассмотрю в первой части этой статьи, — внешний вид терминалов. Например GNOME, Xfce и urxvt поддерживают прозрачность, но недавно свернули поддержку фоновых изображений, что заставило некоторых пользователей перейти на терминал

. Лично меня устраивает и просто

Xresources

, который устанавливает базовый набор цветов фона для urxvt. Однако нестандартные цветовые темы могут создавать и проблемы. Например,

с приложениями

, так как они уже используют собственные цвета.

Оригинальный терминал VT100 не поддерживал цвета, а новые зачастую ограничивались 256-цветной палитрой. Для опытных пользователей, которые стилизуют свои терминалы, запросы оболочки или строки состояния какими-то сложными способами, могут стать неприятным ограничением.

Gist отслеживает, какие терминалы имеют поддержку «True Color». Мои тесты подтверждают, что st, Alacritty и терминалы на базе VTE прекрасно поддерживают True Color. Другие терминалы в этом плане чувствуют себя не очень хорошо и по факту не отображают даже 256 цветов.

Ниже вы можете увидеть разницу между поддержкой True Color в терминалах GNOME, st и xterm, которые неплохо справляются с этой задачей с помощью своей 256-цветовой палитры, и urxvt, который не только не проходит тест, но даже показывает какие-то мигающие символы вместо них.

Некоторые терминалы также анализируют текст на наличие URL-шаблонов, чтобы сделать ссылки кликабельными. Это относится ко всем производным от VTE терминалам, тогда как urxvt требует специальный подключаемый модуль, который бы трансформировал URL-адреса по щелчку или с помощью сочетания клавиш. Другие протестированные мной терминалы отображают URL-адреса иными способами.

:/>  Не загружается рабочий стол Windows 7, 8, 10 | HowWindows

Наконец, новый тренд терминалов — опциональность буфера прокрутки. Например, в st нет буфера прокрутки; предполагается, что пользователь будет использовать терминальный мультиплексор, вроде tmux и GNU Screen.

В Alacritty также отсутствуют буферы обратного скролла, но вскоре добавится его поддержка из-за «обширного фидбека» на эту тему со стороны пользователей. Помимо этих выскочек, каждый проверенный мною терминал, который я смог найти, поддерживает обратную прокрутку.

Скорость прокрутки

Следующий тест — это традиционная проверка «скорости» или «полосы пропускания», которая измеряет, как быстро терминал может прокручивать страницу, отображая большое количество текста на экране. Механика теста варьируется; оригинальный тест состоял в том, чтобы просто генерировать одну и ту же текстовую строку с помощью команды seq. Другие тесты включают в себя проверку Томаса Е. Дики (сопровождающего xterm), в рамках которого многократно

. В еще одном обзоре производительности терминалов

использует строку случайных байтов в кодировке base32, которая выводится в терминал с помощью cat. Луу считает такой тест «настолько бесполезным эталоном, насколько это можно себе представить» и предлагает использовать вместо этого отклик терминала в качестве основного показателя.

Дики также называет свой тест вводящим в заблуждение. Тем не менее, оба автора признают, что пропускная способность окна терминала может быть проблемой. Луу обнаружил зависание Emacs Eshell при отображении больших файлов, а Дики оптимизировал терминал, чтобы избавиться от визуальной медлительности xtrerm.

Здесь мы видим, что rxvt и st вырываются вперед на фоне конкурентов, следом идет намного более новый Alacritty, разрабатываемый с упором на быстродействие. Далее идут Xfce (семейство VTE) и Konsole, которые работают почти вдвое быстрее. Последним идет xterm с показателем в пять раз медленнее rxvt.

Во время теста xterm также сильно рябил, проходящий текст было трудно разглядеть, даже если это была одна и та же строка. Konsole оказался быстрым, но он временами «хитрил»: дисплей время от времени зависал, показывая текст частично или не отображая его вовсе. Другие терминалы отображали строки четко, включая st, Alacritty и rxvt.

Дики объясняет, что различия в производительности связаны с дизайном буферов прокрутки в разных терминалах. В частности, он обвиняет rxvt и другие терминалы в том, что они «не следуют общим правилам»:

«В отличие от xterm, rxvt не пытался отобразить все обновления. Если он отстает, он откажется от некоторых обновлений, чтобы наверстать упущенное. Это оказало большее влияние на мнимую скорость прокрутки, чем на организацию внутренней памяти. Один недостаток состоял в том, что анимация ASCII была несколько неточной».


Чтобы исправить эту кажущуюся медлительность xterm, Дики предлагает использовать ресурс

, позволяющий xterm отбрасывать некоторые обновления экрана, чтобы не отставать от потока. Мои тесты подтверждают, что fastScroll повышает производительность и выводит xterm на один уровень с rxvt. Это, однако, довольно грубый костыль, как объясняет сам Дики: «иногда xterm — как и konsole — кажется, останавливается, так как он ожидает нового набора обновлений экрана после того, как некоторые из них были удалены». В этом ключе кажется, что другие терминалы нашли наилучший компромисс между скоростью и целостностью дисплея.

Случай a. временная загрузка в консольный режим (текстовый режим)

Используя эти инструкции, ваш компьютер загрузится с консолью только для текущей загрузки. После перезагрузки компьютер загрузится нормально, поэтому эти изменения временные.

Для временной загрузки в консольный режим (tty), запустите компьютер и сразу после заставки BIOS/UEFI нажмите и удерживайте Shift (BIOS) или несколько раз нажмите клавишу Esc (UEFI), для доступа к меню GRUB.

2. Когда вы увидите экран GNU GRUB , с выбранной первой записью из меню, нажмите e ключ. Это позволяет вам редактировать параметры ядра перед загрузкой.

Ищите строку, которая начинается с linux (используйте Up/Down/ Клавиши со стрелками влево/вправо для навигации); vmlinuz также должен находиться в той же строке. В конце этой строки (вы можете поместить курсор, используя клавиши со стрелками в начале строки, затем нажмите клавишу End , чтобы переместить курсор в конец этой строки) добавьте пробел , за которым следует число 3. Больше ничего не меняйте.

Управление вкладками и панелями

Откройте новую вкладку для профиля по умолчанию, нажав на или значок Ctrl Shift T. Чтобы открыть вкладку для другого профиля, выберите ее из раскрывающегося меню или нажмите Ctrl Shift  N, где N — номер профиля.

Нажмите Alt Shift , D чтобы продублировать и разделить панель. Активная панель делится на две части по самой длинной оси при каждом использовании:

Чтобы принудительно создать:

  • вертикальная панель, нажмите Alt Shift или
  • горизонтальная панель, нажмите Alt Shift±

Чтобы открыть другой профиль на новой панели, удерживайте Altклавишу при выборе его в раскрывающемся меню.

Удерживайте Altи используйте клавиши курсора для переключения между активными панелями с клавиатуры. Размер панели можно настроить, удерживая Alt Shiftи используя клавиши курсора для соответствующего изменения размера.

Вкладки можно переименовать, дважды щелкнув текст. Вы также можете изменить имя или цвет, щелкнув вкладку правой кнопкой мыши и выбрав пункт меню:

Это влияет только на текущую вкладку, он не меняет профиль навсегда.

Чтобы закрыть активную панель или вкладку, нажмите Alt Shift Wили введите стандартную команду выхода терминала (обычно exit).

Устройство псевдотерминала

Мы все ближе приближаемся к заключительной части статьи, но перед этим заглянем “под капот” Linux — рассмотрим устройство псевдотерминала на уровне ядра. Будет много кода, но я постараюсь объяснять каждый приведенный блок кода максимально подробно, сокращать неважные детали и идти последовательно.

Перед началом введем так называемую “корзину компонентов”. По мере продвижения по ядру, мы будет добавлять в нее всё больше компонентов и находить связь между ними. Надеюсь, это еще лучше поможет понять устройство псевдотерминала. Приступим.

Когда Linux запускается, он загружает необходимые драйверы устройств. Такой драйвер имеется и у нашего псевдотерминала. Его регистрация начинается с вызова данной функции:

static int __init pty_init(void)
{
    legacy_pty_init();
    unix98_pty_init(); // <- то, что нас интересует
    return 0;
}
device_initcall(pty_init); // сообщает, какую функцию вызывать при регистрации драйвера

Для всех современных систем будет вызвана функция unix98_pty_init():

static void __init unix98_pty_init(void)
{
    ptm_driver = tty_alloc_driver(NR_UNIX98_PTY_MAX,
            TTY_DRIVER_RESET_TERMIOS |
            TTY_DRIVER_REAL_RAW |
            TTY_DRIVER_DYNAMIC_DEV |
            TTY_DRIVER_DEVPTS_MEM |
            TTY_DRIVER_DYNAMIC_ALLOC);
    if (IS_ERR(ptm_driver))
        panic("Couldn't allocate Unix98 ptm driver");
    pts_driver = tty_alloc_driver(NR_UNIX98_PTY_MAX,
            TTY_DRIVER_RESET_TERMIOS |
            TTY_DRIVER_REAL_RAW |
            TTY_DRIVER_DYNAMIC_DEV |
            TTY_DRIVER_DEVPTS_MEM |
            TTY_DRIVER_DYNAMIC_ALLOC);
    if (IS_ERR(pts_driver))
        panic("Couldn't allocate Unix98 pts driver");

    ptm_driver->driver_name = "pty_master";
    ptm_driver->name = "ptm";
    ptm_driver->major = UNIX98_PTY_MASTER_MAJOR;
    ptm_driver->minor_start = 0;
    ptm_driver->type = TTY_DRIVER_TYPE_PTY;
    ptm_driver->subtype = PTY_TYPE_MASTER;
    ptm_driver->init_termios = tty_std_termios;
    ptm_driver->init_termios.c_iflag = 0;
    ptm_driver->init_termios.c_oflag = 0;
    ptm_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
    ptm_driver->init_termios.c_lflag = 0;
    ptm_driver->init_termios.c_ispeed = 38400;
    ptm_driver->init_termios.c_ospeed = 38400;
    ptm_driver->other = pts_driver;
    tty_set_operations(ptm_driver, &ptm_unix98_ops);

    pts_driver->driver_name = "pty_slave";
    pts_driver->name = "pts";
    pts_driver->major = UNIX98_PTY_SLAVE_MAJOR;
    pts_driver->minor_start = 0;
    pts_driver->type = TTY_DRIVER_TYPE_PTY;
    pts_driver->subtype = PTY_TYPE_SLAVE;
    pts_driver->init_termios = tty_std_termios;
    pts_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
    pts_driver->init_termios.c_ispeed = 38400;
    pts_driver->init_termios.c_ospeed = 38400;
    pts_driver->other = ptm_driver;
    tty_set_operations(pts_driver, &pty_unix98_ops);

    if (tty_register_driver(ptm_driver))
        panic("Couldn't register Unix98 ptm driver");
    if (tty_register_driver(pts_driver))
        panic("Couldn't register Unix98 pts driver");

    /* Now create the /dev/ptmx special device */
    tty_default_fops(&ptmx_fops);
    ptmx_fops.open = ptmx_open;

    cdev_init(&ptmx_cdev, &ptmx_fops);
    if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
        register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
        panic("Couldn't register /dev/ptmx driver");
    device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");

Здесь нас интересует 3 вещи:

  1. Вызовы tty_set_operatons для драйвера pty master и pty slave устройств.
  2. Функция ptmx_open, которая отвечает за создание обоих частей псевдотерминала при открытии специального устройства /dev/ptmx. Важно: /dev/ptmx — это не PTM устройство, а всего лишь интерфейс для создания нового псевдотерминала.
  3. Регистрация драйвера PTM и PTS устройств.

Пойдем по порядку:

Заключение

В первой части статьи мы обнаружили, что терминалы на основе VTE имеют хороший набор функций, но теперь мы видим, что это связано с некоторыми затратами на обеспечение их производительности. Сейчас память не является проблемой, потому что всеми VTE-терминалы можно управлять через Daemon-процесс, который ограничивает их аппетит.

Тем не менее, старые системы, имеющие физические ограничения по количеству оперативной памяти и буфера ядра, могут по-прежнему нуждаться в более ранних версиях терминалов, так как они потребляют значительно меньше ресурсов. Хотя терминалы VTE показали себя хорошо в тестах на пропускную способность (прокрутка), их задержка отображения данных на дисплее выше установленного порога в руководстве пользователя GNOME.

Вероятно, разработчикам VTE стоит это учесть. Если принять в расчет то, что даже для начинающих пользователей Linux встреча с терминалом неизбежна, они могут сделать его более дружелюбным по отношению к юзеру. Для опытных гиков переход с терминала по умолчанию может означать даже снижение нагрузки на зрение и возможность избежать профессиональных травм и заболеваний в будущем из-за продолжительных рабочих сессий.

Контрольные измерения также показали, что из-за развития графических сред Linux разработчикам пришлось пойти на ряд компромиссов. Некоторым пользователям стоит взглянуть на обычные оконные менеджеры, так как они обеспечивают значительное снижение пинга.

К сожалению, для Wayland измерить задержку не получилось: программа Typometer, которой я пользовался, была создана для того, что Wayland призван предотвращать — шпионаж за другими окнами. Я надеюсь, что композитинг Wayland по производительности лучше, чем X.org, а также надеюсь и на то, что в будущем кто-нибудь найдет способ оценить уровень задержки в этой среде.

Промежуточные итоги


Во второй части материала (

в оригинале это были две разные статьи, — прим. пер.

) мы сравним производительность, использование памяти и задержку. Но мы уже видим, что некоторые из рассматриваемых терминалов имеют серьезные недостатки. Например, пользователи на регулярной основе работающие с RTL-скриптами могут обратить внимание на mlterm и pterm, так как они лучше других справляются с подобными задачами. Konsole также хорошо проявил себя. Пользователи, не работающие с RTL-скриптами, могут выбирать что-нибудь другое.

С точки зрения защищенности от вставки вредоносного кода urxvt стоит особняком из-за своей особой реализации защиты от этого вида атак, которая мне кажется определенно удобной. Тем, кто ищет какие-нибудь навороты, стоит посмотреть на Konsole. Наконец, стоит отметить, что VTE — отличная база для терминалов, которая гарантирует поддержку цветов, распознавание URL и так далее.

Продолжаем разговорВообще, производительность терминалов сама по себе может показаться надуманной проблемой, однако, как оказалось, некоторые из них демонстрируют удивительно большую задержку для ПО такого фундаментального типа.

Оставьте комментарий

Adblock
detector