Наши партнеры








Книги по Linux (с отзывами читателей)

Библиотека сайта rus-linux.net

X Window -- восполняя пробелы. Часть 1

Андрей Зубинский

Масштабность X Window как программного проекта выражается даже не столько объемом кода (хотя последний впечатляет и нарушает каноническое представление о непригодности языка программирования C для создания больших систем -- более 1,5 млн. строк), сколько бездной, отделяющей временную отметку начала и масштаб проекта от его сегодняшнего состояния.

Не углубляясь в исторические дебри, уделим несколько строк короткой исторической справке. Первые десять (!) версий X Window создавались фактически всего тремя людьми -- Робертом Шейфлером (Robert Sheifler), Джимом Геттисом (Jim Gettys) и Роном Ньюменом (Ron Newman). Три "основоположника" представляли в разумной пропорции главные движущие силы технологического развития IT-индустрии -- академическую науку (двое -- из Массачусетского технологического института, MIT) и знаменитую в те давние времена своими инновациями корпорацию DEC. Еще один примечательный исторический момент -- технологическая трансформация, которую претерпела система на ранних этапах развития. Возможно, что без нее вся история X Window, как действительно удачного (хоть и спорного) программного проекта, потеряет всякий "вкус". Все дело в том, что в далеком 1984 году первый разработчик X Window использовал весьма привлекательный и совершенный по сегодняшним меркам... объектно-ориентированный язык программирования CLU. И только затем совсем молодой проект был перепрограммирован на "компьютерной чуме XX века" -- языке C. Факт "сдачи технологических позиций" и последовавший за ним успех системы мы пока обсуждать не будем, как и мотивацию разработчиков X Window. Воспримем это пока как ошибку -- впоследствии мы подробно поговорим о "секретном" оружии, использовавшемся как при проектировании, так и при реинжениринге системы, и позволившем спасти проект от, казалось бы, неминуемого поражения со стороны главного врага программиста -- сложности.

Эволюция пользовательских интерфейсов, построенных на основе X Window, наглядно доказывает преимущество выбранного разработчиками системы подхода. Свобода в определении политик и простота использования механизмов позволили X Window ПО пройти эволюционным путем от внешне примитивного вида OpenLook к де-фактно стандартному экранному представлению примитивов пользовательского интерфейса Motif, к гибко настраиваемому современному виду KDE и, наконец, к прообразам трехмерного интерфейса
Начиная с 11-й версии системы, той, с которой сегодня имеют дело многочисленные пользователи рабочих станций под управлением ОС Unix или ее клонов, проект X Window утратил характер "малой рабочей группы" и превратился фактически в транснациональную смешанную академическо-корпоративную организацию, расширившую представительство со стороны академической науки университетами Карнеги-Миллан и Беркли, а со стороны корпоративного сектора -- компаниями Sun, Hewlett-Packard, Siemens, Stellar, Tektronix, Wyse, BBS... (список слишком велик, чтобы его целесообразно было продолжать).

В нашем коротком историческом обзоре остался упущенным один важный момент -- название. Действительно, почему именно "X"? И наступило время для первой оговорки -- "основоположники" X Window, естественно, "стояли на плечах гигантов". Несмотря на то что разработки их предшественников канули в Лету, не упомянуть имен этих программистов автор не может. Заодно мы найдем и объяснение "тайне" названия системы. А она, как это водится, весьма прозаична: "X" -- потому что в английском алфавите эта буква следует за буквой "W". А вот графическую подсистему W, сегодня полностью забытую, создали в Стэнфордском университете два талантливых программиста (впоследствии ставших сотрудниками исследовательских лабораторий DEC) -- Поль Асентэ (Paule Asente) и Брайан Рейд (Brian Reid).


Что же такое X Window?

Увы, короткий ответ на этот вопрос найти трудно (если вообще возможно) по одной простой причине -- X Window настолько насыщенная и разносторонне функциональная система, что любой краткий ответ гарантированно будет страдать неполнотой.

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

С функциональной точки зрения X Window часто называют "не зависящей от платформы растровой графической оконной системой, обеспечивающей прозрачное использование ее ресурсов с помощью сетевых соединений". В этом определении кроется много ответов на много вопросов, но все же далеко не все. Очевидно, что X Window работает только с растровыми устройствами отображения информации, очевидно, что система образует некоторый дополнительный, более высокий по сравнению с примитивным понятием "пиксел", уровень абстракции -- "окно", ну и, наконец, X Window обеспечивает удаленное использование ресурсов графической подсистемы. Расхожее определение оставляет вне поля зрения идеологическую основу X Window -- "врожденную" поддержку взаимодействия между разными программными компонентами, выполняющимися в разных защищенных областях памяти одного компьютера или на разных компьютерах -- характерную особенность систем класса middleware. Скрытая в упоминании о сетевых "способностях" X Window суть на деле означает, что система является, выражаясь современными терминами, распределенной клиент-серверной. И наконец, такое простое понятие, как "растровый", куда сложнее, чем это может показаться на первый взгляд. С 1984 г. растровые графические системы неузнаваемо изменились, а X Window продолжает работать фактически на любом вычислительном устройстве, обладающем графической подсистемой. И при этом X Window надежно защищает порой бесценные разработки программистов прошлого от влияний этих изменений, гарантированно обеспечивая работоспособность даже очень старых, но не утративших актуальности программ. Возможно, пользователю современного ПК упоминание подобного достоинства покажется надуманным, а напрасно -- мир компьютеров все-таки был, есть и будет очень разнообразным. Да и действительно хорошие программы остаются таковыми, несмотря на их "преклонный" возраст.


Принципы и инструменты

Наступила пора "выстрелить" секретному оружию, о котором было упомянуто. Авторы "неоклассических" толкований искусства программирования небезосновательно утверждают, что предел сложности реализуемого на языке C проекта составляет несколько сотен тысяч строк исходных текстов. Наиболее строгая оценка -- 100 тыс. строк. За этим пределом программный проект становится неуправляемым, утрачивает пригодность к реинжинирингу, и затраты на его сопровождение астрономически возрастают. Все эти оценки, естественно, не взяты "с потолка" и отражают опыт создания реальных программ. Но действительность слишком многогранна, чтобы они были той самой правдой, которая "всегда одна". X Window -- яркий пример "другой правды" -- упорно нарушает неоклассические каноны. И, как ни странно, благодаря элементарным "секретам". Впрочем, давайте прислушаемся к самим разработчикам X Window, а именно, к принципам и подходам, которые использовались ими при проектировании системы, благо, никаких тайн в открытом проекте нет. Эти "выжимки" из стандартной документации X Window (естественно, не в дословном переводе) можно смело называть "Евангелием X".

Главный принцип "основоположников" X Window -- строгое соблюдение простого правила: потребность в изменениях системы определяется выполнением необходимых условий. Для конкретики программного проекта этот же общеинженерный принцип (заимствованный из конфуцианства) можно перефразировать так: не создавать добавочную функциональность, пока имеющаяся достаточна для решения задач, стоящих перед системой.

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

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

Четвертый принцип -- это целая философия, но между тем он прост и также не нов для инженера: "единственное, что хуже обобщения, основанного на одном реальном факте, -- это обобщение, основанное на отсутствующих фактах или предположениях". В проекте X Window соблюдение этого принципа было исключительно важным фактором из-за... объектно-ориентированного подхода при проектировании.

Пятый принцип -- принцип здравого смысла: "если проблему невозможно полностью понять, лучше не пытаться предлагать ее решений".

Шестой принцип -- "ленивой эффективности": если для достижения 90% желаемых показателей эффективности системы нужно затратить всего 10% ресурсов, достижение оставшихся 10% эффективности целесообразно просто игнорировать. Или, иначе, простое решение, всего на 10% менее эффективное, но более надежное и доступное для понимания (а значит, и более долговечное), предпочтительнее, чем сложное, независимо от его эффективности. Это правило также является классикой инженерного проектирования и имеет не только более чем вразумительные обоснования в теории многокритериальной оптимизации, но и богатейшую базу практических доказательств. К последним, например, относится ОС Unix, разработчики которой никогда не стремились к "выдающимся" показателям производительности своего детища, что исключительно положительно сказалось на жизнеспособности ОС как программного проекта.

Седьмой принцип также общеизвестен -- его называют по-разному, но мы будем придерживаться оригинальных терминов X Window -- "изоляция сложности". Учитывая объектно-ориентированное проектирование системы и ее глубинные ООП-корни (первый язык реализации -- CLU), здесь можно было бы ограничиться термином "инкапсуляция" и... ввести читателя в заблуждение. Разработчики X Window под "изоляцией сложности" понимали вполне определенное свойство, основывающееся на рациональном и очевидном соображении: систему, состоящую из множества взаимодействующих друг с другом частей (компонентов) трудно понять и еще труднее модифицировать (сопровождать). Соответственно, принцип "изоляции сложности" означает не только и не столько "упрятывание" функциональности в "компонентные" или объектные "обертки" (что, собственно, и называется инкапсуляцией), сколько максимальное сокращение связей между компонентами -- даже за счет "перекладывания" ответственности за часть функциональности на разработчиков приложений.

И последний принцип, за который яростно ругают X Window, -- "принцип свободы", предусматривающий реализацию исключительно механизмов, а не политик использования этих механизмов. Так как X Window является подсистемой, "ответственной" за взаимодействие человека с компьютером, то "принцип свободы", в частности, означает возможность самостоятельного выбора пользователем (или разработчиком) политик использования/реализации графического интерфейса.

Итак, "Евангелие X" завершилось. Но семь достаточно очевидных инженерных принципов -- это, естественно, не все, что гарантировало успех проекта. Вторая составляющая успеха -- использованные инструментальные средства. Им можно посвятить не одну отдельную статью (а некоторым -- не одну книгу), поэтому здесь остается только заметить -- истории о гуру, с реактивной скоростью "отстукивающих" в терминальных редакторах по несколько тысяч строк абсолютно гениального кода в день, к X Window имеют весьма отдаленное отношение, разве что к самому раннему периоду разработки. Сложность есть сложность... и в ход давным-давно пущена "тяжелая артиллерия" программной инженерии (software engineering) -- метаязыки описания модульной структуры проекта, поддерживающие автоматическую генерацию тестов и автоматическое тестирование, трассировщики выполнения программ с графическим выводом результатов, специализированные библиотеки контроля за управлением памятью и т. д. и т. п. Короче говоря, вся та атрибутика, которая сегодня считается чуть ли не уникальной для "суперсовременных" интегрированных сред разработки.


Белое и черное

Концептуальная схема X Window
Как любой большой и долгоживущий программный проект, имеющий к тому же и смешанный инструментально-системный характер, X Window обладает массой весьма специфических достоинств и недостатков. Говорить о преимуществах этой системы трудно -- не потому что их нет, а из-за ее большой "разноплановости", допускающей множество точек зрения.

Но некоторые достоинства очевидны -- X Window работает, X Window хорошо работает (в том числе и в первую очередь -- в приложениях mission critical), X Window работает на всем, "что движется", X Window развивается, и наконец, X Window остается уникальной системой, для которой нет реальной альтернативы с 1984 г.

Недостатки системы охарактеризовать намного проще -- они, как говорится, у всех "на слуху". X Window ругают обоснованно и необоснованно, но чаще всего ругают конкретные реализации системы. Исторически первый прецедент обоснованной критики был связан с сетевым характером X Window и элементарностью получения удаленного доступа к компьютеру, использующему эту графическую подсистему. С тех пор утекло много воды -- появились и специализированные средства защиты (например, прокси-серверы X-протокола), да и в самих спецификациях/реализациях X Window значительно улучшился арсенал "защитных" средств. Но противоречие между функциональностью и защищенностью остается актуальным -- сетевые возможности X Window при некомпетентном администрировании системы оставляют потенциальные "лазейки", угрожающие безопасности вычислительной системе в целом. Впрочем, некомпетентность умудряется оставлять "лазейки" всегда, и сегодня этот недостаток X Window стал больше историческим фактом. Второй недостаток куда более серьезен и курьезен одновременно -- X Window часто объявляют "зависимой от аппаратных средств системой", подразумевая под этим... растровую модель отображения. Впрочем, пока векторные устройства не вернулись на дисплейную арену, а разрешение реальных экранов не достигло предельной возможности сегодняшних реализаций X Window (65535 65535 точек), и этот "недостаток" можно не принимать во внимание. Как и "недостаток", вытекающий из незнания "принципа свободы", -- растровый минимализм X Window не позволяет в базовой системе поддерживать и, например, унифицированный "прозрачный" для программиста вывод на устройства печати. Такая критика хоть не беспочвенна, но -- это не недостаток, а свойство X Window. Другое дело, что для решения проблемы унификации печати и отображения на экране не нашлись столь же талантливые разработчики... Если предыдущие недостатки можно было применить к X Window как набору спецификаций, то последний, наиболее известный, касается исключительно конкретных реализаций системы. "X Window -- медленный прожорливый монстр, обеспечивающий надежный способ заставить работать вашу 100-мегагерцевую рабочую станцию со скоростью IBM PC 4 MHz". К счастью, эта особенность X Window давно осталась в прошлом -- сегодняшние реализации могут быть и микроминиатюрными (например, всего 600 KB), и скоростными, и какими угодно вообще (впрочем, как и неудачными, медленными и даже содержащими грубые ошибки).


Базовые концепции X Window

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

Итак, главные понятия X Window -- сервер и клиент. По отношению к их "расхожим" толкованиям они кажутся реверсивными -- в X Window пользователь-человек "сидит" за сервером (называемым X-сервером), а программы, с которыми пользователь работает, именуются клиентами. На самом деле никакого противоречия в "терминологическом реверсе" нет: X-сервер -- это действительно сервер, предоставляющий свои ресурсы -- растровую память и информацию о событиях от клавиатуры и устройства позиционирования курсора -- программам-клиентам, отвечающим за всю остальную функциональность. При этом никакой разницы для человека-пользователя, сидящего за конкретным X-сервером, в месте исполнения различных программ-клиентов, нет -- один X-сервер может быть одновременно подключен ко многим машинам и даже обладать собственной вычислительной мощностью (например, выполняться на рабочей станции). Что, естественно, означает принципиальную возможность использовать ресурсы разных вычислительных машин без специальных ухищрений при разработке ПО.

Второе "самое главное понятие" -- событие. X Window -- система, основанная на абстракциях "события" и обработке потока событий. Условно можно выделить три класса событий -- генерируемые при изменении состояния физических устройств пользовательского ввода, генерируемые при изменении состояния отображаемых окон и события поддержки взаимодействия между программами-клиентами.

Процесс "общения" между сервером и клиентом осуществляется с помощью специального сетевого протокола -- так называемого "X-протокола". Это весьма скромный как по количеству понятий, так и по требованиям к пропускной способности сети протокол. В нем всего 4 базовых типа сообщений с простейшими форматами -- запрос, ответ, оповещение о событии и сообщение об ошибке. На этом базисе и строится все "общение": описание стандарта X-протокола -- более чем скромный документ с "немодным" для сегодняшней компьютерной индустрии объемом в 176 страниц. Главная особенность X-протокола, революционно отличавшая самую первую реализацию X Window от своей предшественницы системы W, -- асинхронный характер взаимодействия клиента с X-сервером. Она означает, что ни клиент, ни X-сервер не должны ожидать завершения/подтверждения какой-либо атомарной операции "общения" для выполнения других действий. И если это свойство можно назвать замечательным, вторая особенность X-протокола весьма спорная и заключается в неспособности X Window "сохранять состояние" протокола -- при потере связи между клиентом и X-сервером, состояние последних на момент потери связи не сохраняется. Такая особенность, с одной стороны, ограничивает применение базовой X Window в беспроводных системах (где замирания и пропадания сигналов не редкость), с другой -- стимулирует создание многочисленных расширений системы, ликвидирующих этот недостаток.

Комбинация X-сервера с соответствующим аппаратно-программным обеспечением образует в терминах X Window "дисплей". Дисплеем может быть рабочая станция или специализированный бездисковый компьютер весьма экзотической архитектуры -- это не важно. Главное, чтобы дисплей мог выполнять программу X-сервера и обслуживать одну-единственную клавиатуру и позиционирующее устройство (мышь, световое перо, трекбол, многокоординатный рычаг и т. д.). Еще одна особенность дисплея -- принципиальная способность поддержки множества физических "экранов" -- комбинаций отвечающего за отображение растровой картинки "железа" и мониторов. Количество обслуживаемых экранов в сегодняшних реализациях X Window ограничено максимальным значением целого числа, поддерживаемым системой (для 32-битовых машин -- 231 соответственно). Каждый экран дисплея может содержать множество перекрывающихся окон -- прямоугольных или произвольной формы (с учетом расширений системы X Window) отображаемых областей растровой памяти. Окна образуют строгие иерархии на основании простого правила -- в каждом экране по умолчанию существует одно уникальное окно-родитель (корневое или root-окно), каждое окно должно иметь "родителя" и само может быть "родителем" для других окон. Окно обладает собственной системой координат с начальным положением в левом верхнем углу окна, обозначением вертикальной оси как "y", горизонтальной как "x" и отсчетом в пикселах. X Window реализует целый ряд операций как над окнами, так и над содержимым окон -- окна можно создавать, перерисовывать на экране, удалять, в них можно выводить текст и графические примитивы.

"Наследственная" иерархия (родитель-потомок) в X Window дополняется так называемым "стековым порядком", информирующем о полном или частичном перекрытии одних окон другими. Но при этом, в соответствии с "Евангелием X", забота о перерисовке содержимого окна, изменившего свое положение в "стековом порядке", -- это забота программиста, а не X Window (что, впрочем, не сильно сказалось на сложности программирования системы).

Собственно, базисные понятия на этом исчерпались. Наступило время отвечающих за эффективность реализации всей X Window нюансов. Сетевой характер системы, как очевидно, требует очень бережного отношения к трафику -- пропускная способность сетей хоть и растет, но остается ограничивающим ресурсом. А даже такое "простое" понятие, как прямоугольная область отображаемой растровой памяти -- окно, требует минимальной передачи его положения в системе координат родительского окна, размеров по горизонтали и вертикали и весьма обширной дополнительной информации. Учитывая, что окна -- относительно "дешевый" (в терминах вычислительной мощности и объемов памяти для описаний) ресурс, и современные пользовательские интерфейсы построены именно на основе множества окон (да-да, все эти кнопочки, ниспадающие меню, строки ввода и даже обрамления вокруг окон реализованы с помощью... окон), передача описаний окон по сети может превратить требования к пропускной способности в нереальные. А ведь кроме окон, существует еще ряд абстракций, без реализации которых ценность графической подсистемы равна нулю. Разработчики X Window нашли эффектное решение этой проблемы с помощью создания двух обобщающих понятий -- "ресурса" и "идентификатора ресурса".

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

Теперь о ресурсах можно говорить подробнее -- в эту категорию попадают такие понятия, как окна, пиксельные карты (pixmap), курсоры, шрифты, графические контексты и палитры. Окна как объекты X Window мы кратко рассмотрели, пиксельные карты на деле являются специальным форматом представления растровых картинок, курсоры и шрифты в дополнительных комментариях на этом уровне ознакомления не нуждаются.

Графический контекст -- один из уникальных атрибутов X Window, связанный одновременно со скромными базовыми графическими возможностями системы и с ее клиент-серверными особенностями. Набор поддерживаемых X Window операций вывода графики можно считать более чем скромным -- в него входит рисование точки (пиксела), линии, текста, растрового изображения и ограниченного контуром или закрашенного многоугольника. Но каждая такая операция требует для передачи по сети слишком много дополнительной информации -- о цвете, стиле линии, короче говоря, обо всех возможных атрибутах. Именно это множество атрибутов и называется "графическим контекстом" (GC). Использование модели "ресурс-идентификатор" в данном случае также позволяет добиться существенного уменьшения трафика -- перед началом выполнения множества операций "рисования" программа-клиент регистрирует необходимые GC, а затем выполняет операции с указанием коротких идентификаторов вместо множества дублирующих друг друга данных.

Если предыдущие понятия были относительно просты, то палитры, как и все, что касается управления цветом в X Window, исключительно сложная тема. Дело в том, что система создавалась для потенциальной поддержки любых устройств растрового графического вывода, которые существенно отличаются принципами формирования цвета из кода пиксела. Не вдаваясь в подробности, здесь целесообразно только определить "палитру" как таблицу, ставящую в соответствие коду пиксела тройку значений {R,G,B} -- интенсивностей трех базовых цветов. X-сервер поддерживает как разделяемую между всеми клиентами общую палитру, так и возможность создания для каждого клиента собственной виртуальной палитры (это высказывание справедливо далеко не для всех аппаратных средств).

И вот, последние и почти самые главные понятия -- "свойства" (properties) и "атомы" (atoms). Это одни из ключевых абстракций X Window. "Свойства" представляют собой именованные наборы данных, а атомы -- компактные идентификаторы этих наборов данных. Схожесть с моделью "ресурс-идентификатор" здесь, на первый взгляд, очевидна, но и различия весьма существенны -- если "ресурсы" можно потенциально разделять между программами-клиентами, работающими с одним X-сервером, то "свойства" являются общедоступными (для клиентов одного сервера). В этом же правиле можно заметить и дополнительный нюанс -- атомы, в отличие от идентификаторов ресурсов, уникальны только для одного окна -- ведь одно "свойство" может быть присуще разным окнам. С точки зрения программного архитектора, реализацию свойств можно отнести к нечасто встречающейся разновидности архитектуры -- "классной доске" (иначе называемой "доской объявлений"). Ни к "содержимому" свойств, ни к их именам X Window не предъявляет фактически никаких особых требований, но существует фиксированное множество имен и соглашения о содержимом свойств, которые необходимы для нормального функционирования любого приложения в среде X Window, эти соглашения об именах/содержании свойств с предопределенными атомами называются ICCCM -- "Соглашения о взаимодействии между программами-клиентами".

Андрей Зубинский
www.itc.ua

Продолжение