X Window System

Обратите внимание на то, что все заглавные буквы «X» в этой лекции — латинские.

На свете существует множество графических устройств, управление которыми на низком уровне (вывод изображений и ввод данных, например, о перемещении мыши) — задача совсем не для пользователя, тем более, что каждый вид устройства управляется по-своему. Заботы о вводе и выводе на низком уровне берёт на себя графическая подсистема Linux — X Window System, предоставляя пользовательским программам возможность работать в терминах оконного интерфейса.

X Window System появилась всё в той же UNIX, проект этот был настолько наукоёмок и настолько полно охватывал тогдашнюю область задач, связанную с графикой, что ему так и не возникло никаких серьёзных альтернатив.

X-сервер и X-клиенты. Протокол X11

X Window System использует традиционную оконную модель, в которой пространством ресурсов является экран. Экран — это прямоугольник, на котором отображаются команды графического вывода и организуется обратная связь с устройствами графического ввода. Пример обратной связи — указатель мыши. Сама мышь — довольно простое устройство ввода, способное передавать информацию о его перемещении и состоянии кнопок. Указатель же отображает мнение подсистемы об абсолютных координатах гипотетической «точки ввода».

Расположение точки ввода (фокус)

 
Иллюстрация 3. Расположение точки ввода (фокус)

В примере указатель мыши показывает расположение точки ввода (на кнопке «WindowMaker»). Если сейчас Мефодий нажмёт на левую клавиу мыши, графическая подсистема зафиксирует это событие ввода и передаст его той задаче, которой принадлежит соответствующая кнопка. Именно задачи (а не сидящий за монитором пользователь) и являются субъектами для X Window System, между ними разделяются графические ресурсы. Каждой задаче принадлежит одно или несколько окон, представленных некоторой (как правило, прямоугольной) частью экрана. Внутри окна выполняются графические операции (вывод) и именно окнам передаётся поток данных от устройств ввода. Какое окно получит события ввода — определяется с помощью синтетического понятия фокус: вводимые данные передаются от графической подсиcтемы только тому окну, которое «получило фокус», по умолчанию это происходит, когда указатель мыши попадает в часть экрана, занимаемую этим окном.

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

Программа, которая отвечает за работу с устройствами графического ввода и вывода и обеспечивает при этом логику оконной системы, называется X-сервером (X Server, то есть сервер системы «Икс»). В рамках X Window System, X-сервер — это ядро. Подобно ядру, он выполняет низкоуровневые операции и взаимодействует с аппаратурой, ничего самостоятельно не предпринимая. Подобно ядру, он предоставляет задачам унифицированный интерфейс к этим низкоуровневым функциям, а также занимается разделением доступа (окно и фокус) к графическим ресурсам. X-сервер не волнует, отчего эти задачи вообще появляются и чем живут. Он только принимает запросы на выполнение графических действий и передаёт по назначению вводимые данные. Жизнеобеспечение процессов и даже способ передачи X-запросов — дело исключительно операционной системы, по отношению к которой и сам X-сервер — задача.

Задачи, которые обращаются к X-серверу с запросами, называются X-клиентами. Обычно X-клиент сначала регистрирует окно (можно несколько), которое и будет ему полем ввода-вывода. Потом он сможет рисовать в этом окне и обрабатывать происходящие с окном события: активность устройств ввода и изменение свойств самого окна (размер, перемещение, превращение в иконку, закрытие и т. п.). X-клиент в Linux — это процесс, запускаемый обычно в фоне (не связанный по вводу с терминальной линией). В самом деле, зачем процессу читать с терминала, когда для ввода он может использовать X-сервер? Если с X-сервером связаться не удастся, на стандартном выводе ошибок может появиться какое-нибудь сообщение — его легко перенаправить в файл.

X-сервер
Программа, принимающая и обрабатывающая X-запросы.

Клиент передаёт серверу X-запросы любым доступным ему способом. В разных версиях Linux, например, могут использоваться различные объекты файловой системы (чаще всего — т. н. сокеты, сходные по функциональности с двунаправленными каналами). Во многих случаях запросы передаются по сети, при этом неважно, какой именно транспортный уровень будет использован для соединения клиента с сервером (в современных системах это, чаще всего, сеть TCP/IP и протокол TCP). Главное, чтобы клиент посылал стандартные запросы, соответствующие определённому протоколу обмена данными. Кстати сказать, другое имя X Window System — X11 (или X11R6) — это просто номер версии X-протокола, стандартизующего X-запросы, при этом «R6» обозначает номер подверсии (revision) и вполне может увеличиться, если X11R6 устареет настолько, что потребует нового пересмотра (revision).

«Голый» X-сервер, к которому ни присоединён ни один X-клиент, можно запустить из командной строки, для этого достаточно выполнить команду «X» (одна заглавная латинская буква X). Именно так и поступил Мефодий, текстовая консоль сменилась чёрным экраном без всяких окон.

В некоторых вариантах X Window System экран по умолчанию раскрашивается в чёрно-белую крапинку.

На экране есть только крест, который перемещается при перемещении мыши — курсор. Эта картина означает, что X-сервер запущен корректно, установил необходимую связь с устройствами графического ввода и вывода, и ожидает, когда к нему с X-запросами обратится какой-нибудь X-клиент. Однако для пользователя, пока не запущено ни одного X-клиента, X-сервер совершенно бесполезен: кроме перемещения курсора ничего и невозможно сделать. Мефодий мог бы растеряться, оказавшись перед чёрным экраном X-сервера, если бы не знал о том, что может переключиться обратно на любую виртуальную консоль, нажав сочетание клавиш Ctrl + Alt + F N, где N — номер консоли от 1 до 12.

Эта функция не будет работать, если в конфигурационном файле X-сервера включён параметр «DontVTSwitch».

Переключиться обратно на экран, управляемый X-сервером, он сможет комбинацией клавиш Ctrl + Alt + F7.

DISPLAY

Чтобы начать работу с графческой средой, X-клиенты должны каким-то образом доставить свой запрос X-серверу, для этого у X-сервера должен быть какой-то точный адрес. Адрес X-сервера, к которому должны обращаться с запросом X-клиенты, хранится в переменной окруженияDISPLAY. Формат DISPLAY прост: способ_доступа:номер_сервера.номер_экрана. Под способом доступа может подразумеваться сеть (тогда используется сетевой адрес машины с X-сервером) или какой-нибудь ещё механизм, принятый в конкретной системе. Если не написать ничего, будет выбран способ по умолчанию. Номер сервера нужен для различения разных X-серверов, запущенных на одном компьютере. В Linux можно запустить несколько X-серверов и переключаться между ними как между виртуальными консолями — с помощью Ctrl + Alt + F7, Ctrl + Alt + F8 и т. д. В системе может быть несколько виртуальных серверов (см. раздел Виртуальный сервер). Все они должны иметь разные номера. Наконец, один сервер может работать с несколькими экранами — и физически (есть видеокарты с выходами на несколько мониторов), и виртуально (вот тут уж никаких ограничений нет). Правда, это бывает нечасто, и номер экрана тоже можно не указывать.

Адрес X-сервера, запущенного Мефодием, будет выглядеть так: «:0» — поскольку сервер запущен на той же машине, на которой работает Мефодий, можно использовать способ доступа по умолчанию (поэтому адрес начинается с двоеточия), поскольку сервер единственный, он получил номер «0», а экран можно не указывать. Теперь Мефодий может в любой командной оболочке (shell) указать адрес X-сервера в переменной DISPLAY, так что любой запущенный из этой shell X-клиент унаследует это значение и будет отправлять X-запросы тому серверу, который запустил Мефодий.

methody@susanin:~ $ export DISPLAY=:0
methody@susanin:~ $ echo $DISPLAY
:0
methody@susanin:~ $ xcalc &

Пример 1. Запуск X-клиента из виртуальной консоли

В результате этих действий изменился экран X-сервера: в левом верхнем углу открылось окно калькулятора — xcalc. Произошло следующее: при запуске xcalc проверил значение переменной DISPLAY и направил X-запрос по указанному там адресу; по запросу от X-клиента (xcalc) X-сервер выделил ему окно и выполнил необходимые операции графического вывода, чтобы отрисовать содержимое окна (опять же, по запросам xcalc). Теперь при помощи мыши и клавиатуры, переместив точку ввода на это окно, вполне можно что-нибудь вычислить, однако ни переместить окно, ни изменить его размер, ни свернуть — те операции, к которым так привыкли пользователи оконного интерфейса — сам X-сервер не выполняет, для этих операций требуется специальная программа — диспетчер окон, о которой речь пойдёт ниже.

Запуск X-клиента
Иллюстрация 4. Запуск X-клиента

С помощью специальных X-запросов можно изменить вид и поведение самого X-сервера из той же командной оболочки, в которой установлена переменная окружения DISPLAY. Например, команда «xsetroot -solid green &» изменит цвет фона на экране сервера на зелёный.

Итак, X-сервер запускается на одном компьютере, а X-клиенты вполне могут работать на других (причём на нескольких!), посылая ему запросы. С точки зрения человека, сидящего за (обратите внимание!) X-сервером, каждый такой клиент представлен в виде окна. Требования к аппаратуре на машинах, запускающих X- клиенты, будут изрядно отличаться от требований к аппаратуре машины для X- сервера. Типичная машина с X-сервером — это рабочее место (workstation). Она должна быть оборудована качественными устройствами ввода-вывода — монитором, видеокартой, клавиатурой и мышью. Что же касается её вычислительных способностей, то их должно быть достаточно для выполнения X-запросов, и только. Такой компьютер не обязан работать под управлением Linux, на нём даже может вообще не быть операционной системы! В восьмидесятые годы выпускались подобные устройства, называемые «X-терминал» (X terminal).

X-клиент
Программа, осуществляющая ввод и вывод графических данных при попмщи X-запросов, обрабатываемых X-сервером.

В отличие от машины с X-сервером, компьютер для запуска X-клиентов может совсем не иметь устройств графического ввода-вывода. Его задача в том, чтобы все X-программы и запустившие их пользователи не мешали друг другу работать. На такой машине нужна хорошо настронная операционная среда, с достаточным для запуска многих процессов быстродействием и объёмом оперативной памяти. Пара X11R6–Linux весьма неплохо работает на т. н. бездисковых комплексах. Рабочие станции в таких комплексах — самые настоящие X-терминалы, они не имеют жёстких дисков. Вся работа происходит на центральном компьютере, с которого на рабочую станцию загружается по сети урезанный вариант системы, достаточный для запуска X-сервера, и сам X-сервер. В таких комплексах администрировать нужно одну только центральную машину, они надёжнее компьютерных залов и, что немаловажно, стоят дешевле, причём в качестве X-терминалов можно использовать и довольно маломощные, пожилые компьютеры.

Виртуальный сервер

Одно из многих достоинств X-протокола — в том, что X-сервером может служить любая программа, исполняющая X-запросы, а работает ли она на самом деле с каким-нибудь графическим устройством или только притворяется — неважно. Протоколом X11R6 пользуется сервер печати Xprt, который выводит на принтер все X-запросы или Xvnc — X-сервер, управлять которым по специальному протоколу можно с нескольких машин. С помощью Xvnc можно устраивать показ работы какого-нибудь X-клиента по сети, при этом все пользователи одновременно смогут гонять по экрану один и тот же указатель мыши (что, конечно, можно и запретить). Виртуальный X-сервер может вообще никаких действий не выполнять, а только передавать X-запросы куда-нибудь дальше, например, «настоящему» X-серверу. Так поступает демон Secure Shell, sshd (программа терминального доступа, о которой шла речь в лекции Сетевые и серверные возможности), переправляя X-запросы X-серверу в зашифрованном виде. Этим свойством sshd можно воспользоваться, если сообщение по X-протоколу между двумя компьютерами невозможно (запрещено межсетевым экраном), или вы считаете такое соединение небезопасным.

methody@sakura:~ ssh methody@fuji
 methody@fuji's password: 
 Last login: Sat Dec 25 13:26:40 2004 from localhost
methody@fuji:~ $ xcalc
 Error: Can't open display: 
methody@fuji:~ $ export DISPLAY=sakura:0
methody@fuji:~ $ xcalc
 Error: Can't open display: sakura:0
methody@fuji:~ $ logout
 Connection to fuji closed.
methody@sakura:~ ssh -X methody@fuji
 methody@fuji's password: 
 Last login: Sun Dec 26 11:13:08 2004 from sakura.nipponman.ru
methody@fuji:~ $ echo $DISPLAY 
 localhost:10.0
methody@fuji:~ $ xcalc
 # работает :) !

Пример 2. Виртуальный X-сервер ssh

Допустим, Мефодий хочет запустить X-клиент (например, xcalc) на другой машине в локальной сети — fuji, где у него есть учётная запись (тоже methody). После всех операций, проделанных в примере, на экране X-сервера на локальной машине Мефодия (за которой он сидит), появится ещё одно окно xcalc, при этом этот xcalc в действительности запущен на машине fuji и все вычислительные операции выполняются именно там.

Демон SSH заводит виртуальный X-сервер на удалённой машине, причём номер_сервера обычно заводится таким, чтобы не пересекаться с X-серверами, которые могут быть запущены на этой машине (в примере номер_сервера равен 10). Виртуальный sshd-X сервер принимает все X-запросы с того же компьютера и передаёт их — в зашифрованном виде — на компьютер, где запущен ssh и невиртуальный X-сервер. Здесь все X-запросы вынимаются из SSH-«водопровода» и передаются местному серверу, как если бы они исходили от местного X-клиента (так оно и сеть: этот клиент — ssh).

XFree86 и XOrg

Наиболее распространённая версия реализации X11R6 называется XFree86. Эта графическая подсистема изначально проектирвалась как реализация X11R5 для машин архитектуры i386 — самых распространённых на сегодня персональных компьютеров. Главная особенность этой архитектуры — бесчисленное многобразие устройств графического вывода (т. н. видеокарт) и непрестанное нарушение их разработчиками всех мыслимых стандартов. Поэтому главной задачей создателей XFree86 было устроить гибкую структуру компоновки и настройки X-сервера в соответсвии с подвернувшимся под руку устройством графического вывода, а заодно и ввода, потому что клавиатур, мышей и заменяющих их устройств на свете тоже немало. Сегодня XFree86 существует для многих архитектур и многих операционных систем.

В последние годы параллельно с XFree86 развивается основанная на тех же исходных текстах X Window System графическая подсистема XOrg. До недавнего времени по спектру поддерживаемого оборудования, архитектур и функциональности XOrg мало чем отличалась от XFree86, и сейчас они примерно эквивалентны с точки зрения пользователя. Однако направления развития этих двух проектов, состав их разработчиков и лицензионная политика несхожи. В ближайшем будущем вполне вероятно, что Xorg обгонит XFree86 и по возмпожностям, и по частоте использования.

Конфигурация X-сервера

Чтобы приспособить графическую подсистему (в любой реалиации) к имеющемуся оборудованию, требуется организовать соответствующий профиль. Профиль графической подсистемы находится в каталоге /etc/X11, основной конфигурационный файл XFree86 называется XF86Config-4, именно его считывает при запуске X-сервер.

Цифра 4 появилась в названии этого файла c выходом версии 4.0 XFree86, в этот момент изменился синтаксис конфигурационного файла по сравнению с предыдущими версиями. При этом часть старого оборудования не поддерживается четвёртой версией XFree86, поэтому для такого оборудования приходится использовать более ранние версии, для которых конфигурационный файл сохраняет старое название, XF86Config.

Конфигурационный файл XOrg называется xorg.conf, а при его отсутствии используется файл XF86Config.

Мы рассмотрим конфигурацию графической подсистемы на примере XFree86. Файл XF86Config-4 структурирован: состоит из нескольких обязательных разделов, которые могут следовать в любом порядке. В раздел объединяется часть профиля, связанная с одной из сторон деятельности X-сервера. Каждый раздел имеет такую структуру:

Section  "НазваниеРаздела"
КлючевоеСлово "Параметры"
. . .
EndSection

Пример 3. Структура раздела XF86Config

Внутри раздела содержатся записи, каждая из которых занимает обычно одну строку и задаёт значение для одного из параметров профиля XFree86. В начале записи стоит КлючевоеСлово, за которым следуют Параметры, количество и формат которых зависит от ключевого слова. Ниже приводится список обязательных разделов с краткими аннотациями, для чего они служат.

Files          Пути к файлам с ресурсами, необходимыми X-серверу
ServerFlags    Общие параметры X-сервера 
Module         Расширения, которые следует загрузить
InputDevice    Описание устройств ввода
Device         Описание устройства вывода (видеокарты)
Monitor        Описание монитора
Modes          Описание видеорежимов 
Screen         Описание экрана (связывает монитор и видеокарту)
ServerLayout   Конфигурация сервера

Пример 4. Разделы XF86Config

Почти каждый из перечисленных разделов может присутствовать в конфигурационном файле в нескольких экземплярах, например, может быть несколько разделов (InputDevice), описывающих разные устройства ввода (разные мыши и клавиатуры). Однако эти разделы не равноправны, а образуют иерархическую структуру, самым главным (корневым) элементом которой является конфигурация сервера (ServerLayout). В этом разделе указывается, какие именно из описанных в файле устройств ввода (разделы InputDevice, как минимум два — для клавиатуры и мыши) и вывода (Screen, который связывает в единое устройство вывода монитор и видеокарту, ссылаясь на их описания в соответствующих разделах) будут использованы при работе X-сервера. В каждом разделе присутствует строка «Identifier «идентификатор»», именно эта строка используется для выбора нужного из однотипных устройств в разделе «ServerLayout». Например, на машине, где работает Мефодий, общая конфигурация сервера выглядит так:

Section "ServerLayout"
	Identifier "layout1"
	Screen     "screen1"
	InputDevice "Mouse1" "CorePointer"
	InputDevice "Keyboard1" "CoreKeyboard"
EndSection

Пример 5. Раздел ServerLayout конфигурацонного файла XF86Config

Соответственно, при запуске сервера будут использованы тот раздел Screen, в котором содержится запись «Identifier «screen1»», мышь «Mouse1» и клавиатура «Keyboard1».

Чтобы разобраться в подробностях каждого раздела, требуются определённые познания в работе и характеристиках устройств ввода и вывода, поэтому здесь мы не будем приводить конкретных примеров. Подробно о формате XF86Config можно прочитать в соответсвующем руководстве XF86Config(5). Для многих пользователей будет достаточно профиля графической подсистемы, созданного одним из существующих мастеров, самый известный из которых — xf86config. Во многих дистрибутивах имеются собственные полуавтоматическме утилиты настройки X11. С их помощью можно создать более или менее подходящий профиль, не вникая в тонкости, нередко — непосредственно при установке системы. Во всяком случае, у пользователя всегда остаётся возможность корректировать профиль вручную, отредактировав конфигурационный файл. Простой конфигурационный файл можно получить, запустив X-сервер с ключом -configure из-под суперпользователя. При этом в текущем каталоге создастся файл XF86Config.new, в котором X-сервер сохранит результаты автоматического определения внешних устройств.

Модули и расширения

Требование гибкости привело к тому, что в реализации XFree86 и XOrg графическая подсистема стала совсем уже похожа на операционную систему. Сам X-сервер играет роль ядра. Запускаясь, сервер подгружает драйверы — специальные компоненты, работающие с выбранной видеокартой, и модули — компоненты, расширяющие функциональные возможности сервера (в конфигурационном файле XF86Config необходимые модули перечисляются в разделе Modules). Есть весьма нужные расширения, вроде glx (высокоуровневые функции трёхмерной графики) или freetype (поддержка шрифтов TrueType), а есть экзотические, которые иногда могут понадобиться, напрмер, RECORD, позволяющее записывать, а после — «проигрывать» все происходящие с сервером события.

Расширения называются так ещё и потому, что их возможности расширяют сам протокол X11R6. Вместо того, чтобы изменять протокол всякий раз, когда в голову придёт очередная ещё не реализованая в нём возможность, создатели X11 предусмотрели стандартный способ дополнения этого протокола. При этом X- клиент, желающий воспользоваться определённым расширением, всегда может спросить у X-сервера, поддерживается ли оно, и действовать по обстановке.

">