Поверхностное сравнение архитектуры консоли в Windows и Unix

Довольно интересно сравнить, как устроена консоль в Windows и Unix. Вот упрощенная схема как это работает в Unix:

Консоль в Unix

Посимвольный ввод и вывод через stdin/stdout – единственный канал общения с консолью (терминалом), доступный приложению. Терминалом, при этом, может быть все что угодно – файл на диске, виртуальный терминал в X Window, труба (pipe) из другого приложения и т.д. Между терминалом и приложением передается текст. Нажатия нетекстовых клавиш (клавиш управления курсором, функциональных клавиш и т.п.) транслируются терминалом в управляющие последовательности/ESC коды (см. Ecma-35). С помощью аналогичных управляющих последовательностей приложение может посылать терминалу команды вроде «перейти на следующую строку».

Собственно говоря, полностью корректная отработка ESC кодов, - это весьма сложная задача ввиду сильнейшего разнообразия различных видов терминалов. Библиотека ncurses, к примеру, содержит описания более чем полутора тысяч разных терминальных конфигураций. Неразберихи добавляет и необходимость согласования кодировок текста, которым обмениваются терминал и приложение. К счастью, и разнообразие терминалов, и разнообразие кодировок постепенно сходит на нет – «железные» терминалы почти вымерли; Unicode шагает по планете.

Архитектура консольной подсистемы в Windows во многом отличается от Unix:

Консоль в Windows

Вместо символьного ввода-вывода, приложение общается с консолью через вызовы удаленных функций (RPC). Клавиатурный ввод передается в виде последовательности нажатий клавиш, а не в виде последовательности символов, полученной в результате нажатия этих клавиш. В результате в Windows приложение может, например, отличить Ctrl+Shift+Left от Shift+Left. С другой стороны, в Windows приложение обязано знать тип и раскладку клавиатуры, выбранные в терминале, что в случае удаленного терминала превращается в проблему.

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

Стандартный ввод-вывод отделен от собственно консоли. В результате, перенаправление стандартного ввода-вывода не перехватывает весь консольный ввод-вывод. Попробуйте на досуге перенаправить вывод Far Manager в файл. А затем посмотрите, что получится если сделать то же самое с Midnight Commander.

Продолжение, надеюсь, следует…

comments powered by Disqus