Пользовательский сеанс
Мы сегодня продолжаем прерванный разговор в прошлый раз, когда мы говорили о старте служб. Говоря о старте служб системных, и показывая, как работает systemd, например, я намеренно умолчал о том, что в systemd есть еще один метод активации, а именно - активация по прикладной шине, которая называется dbus. Идея состоит в том, чтобы вместо того, чтобы давать команды нашему systemd вручную с консоли «запусти то-то», «останови то-то», помните, systemctl? Показывал в прошлый раз? Мог и не показывать… Ну, давайте с этого и начнем.
Вот, смотрите. Командочка systemctl по умолчанию выводит кучу всех сервисов, которые сейчас активны. Это не только сервисы, связанные со стартом служб, это и сервисы, связанные с определением устройств, с монтированием, с промежуточными целями, которые таргеты, ну и так дальше и так дальше, тут много чего. Ну, не знаю, кого можно поднять и остановить из этих сервисов? Кого-нибудь нестрашного? Ну, вот, какая-то служба, смотрите.
Вот у нас служба smb запущена
Вот мы говорим systemctl stop smb.service и вот она, соответственно, опущена.
Говорим ей status, она говорит, что ее нет.
Я это не спроста все делаю, я этим напоминаю, что есть такой интерфейс командной строки для запуска системных служб, потому что мы сегодня будем заниматься в числе прочего запуском пользовательских служб таким образом. Говорим ему start, и вот она запущена:
И вот эти самые 4 процесса - вот они перед нами.
В довершении ко всем остальным способам взаимодействия с системой, демон systemd, который у нас занимается изменением профиля оперативного системы, умеет также взаимодействовать с ней через специальную прикладную шину, которая называется dbus.
Прежде чем говорить об межпроцессном взаимодействии с помощью этой самой шины dbus, давайте подумаем над тем, что вообще происходит, когда пользователь регистрируется в системе - получает свой логин.
Вот он, допустим, зарегистрировался (помните, я несколько раз показывал), по сети, допустим. Что при этом должно происходить: ну, со всей очевидностью, должен запуститься шелл. Мы помним, что инвариантом управления системой является командная строка, вот, в данный момент я зарегистрировался на другую машину по сети.
Если бы все было так просто (а так просто было бы еще каких-нибудь 30 или 20 лет назад), на этом бы все и остановилось. Но выясняется, что в момент, когда вы логинитесь в систему, вам нужно параллельно поназапускать некоторое количество программ, которые ну просто вот нужны. Например, к сожалению, нет времени объяснять, но для терминального доступа с помощью протокола secure shell, было бы очень неплохо запустить так называемый secure shell agent, который держит в памяти ваши ключи закрытые и позволяет подключаться удаленно по протоколу secure shell, вводя ключ только один раз. Вот такой агент.
Этот агент надо запускать один раз, когда вы оказываетесь в системе, и убивать один раз, когда вы из системы разлогиниваетесь.
Казалось бы, никаких проблем вставить это в, допустим, тот же самый bash profile (помните, мы его редактировали, он нам писал qq), нету. Вставил запуск агента в bash profile, в специальный файл, который называется bash logout вставил убивание агента - всем хорошо. Дело существенно более осложняется в случае, если нам нужно не просто зайти в систему, а еще запустить целую пачку приложений, которые обслуживают нашу работу в этой системе, в данном случае, графическую подсистему - вот эту.
Давайте посмотрим вот так:
Вот сколько программ запущено от лица пользователя python в нашей системе после логина, видали? Руками все это делать, конечно же, никто не станет. Руками я запустил только броузер и терминал, все остальное было запущено какими-то неведомыми роботами.
Ну, какая идея, идея состоит в том, чтобы залогиниться, запустить графический сервер, который называется X-сервер. Дальше запустить программы, которые нужны для нормального функционирования: на самом деле, их довольно много. Не помню, говорил ли я об этом, но для того, чтобы нормально работала графическая система, нужен не только сервер, потому что он только отрисовывает те графические запросы, которые вы хотите на нем отрисовывать. Например, вот эта вот панель, которая внизу - это отдельная панель:
Это отдельная программа. Какая-нибудь обработка содержимого экрана - отдельная программа, называется xfdesktop, ну и так дальше. Да, немаловажная часть - то, что рисуют декораторы вокруг окон: вот эти вот все рамочки, вот эта красотень - это, разумеется, не дело самого приложения. Приложение не будет рисовать кнопки, внезапно увеличивать окно или уменьшать окно. Это делает специальная программа, которая называется window manager: xfwm4. И тд. Для того, чтобы было запущено графическое окружение, надо запускать целую кучу программ. Естественное решение - написать шелл скрипт, который все это сделает.
Все бы хорошо, но тут начинаются разные такие мелкие проблемы, ну, например: в какой момент этот шелл скрипт запускать? Очевидно, после того, как уже запущен сам их сервер, до этого бессмысленно это делать: X-клиент не получит соединения к этому серверу. Их запускать все подряд или в каком-то порядке? Некоторые можно запускать подряд, некоторые можно запускать только после того, как запущены предыдущие. Ну, например, сначала нужно запустить вот такую штуку, которая называется settings:
Она по определенным правилам рассказывает всей графической среде, которая называется xfce, которая используется на этом компьютере, о том, какие конкретно настройки у приложений, собранных под xfce, есть, и позволяет эти настройки менять. Так вот, сначала нужно запускать ее, а потом приложения, у которых эти настройки можно менять. Вам это ничего не напоминает? Это очень напоминает старт системы. К сожалению, а может быть, не к сожалению, может, просто так пошло развитие, проблема организации и запуска пользовательского окружения таким способом, возникла существенно раньше, чем проблема запуска и организации программного окружения, называемого операционной системой. Еще 10 лет назад пачка шелл скриптов, запускающая операционную систему, было вполне нормальным явлением. Что касается поиска окружения, то у него есть 2 важных момента, которые отличают его от старта операционной системы, а именно - существенно большая связность и существенно более разнообразное количество объектов, которыми приложения могут обмениваться друг с другом. Ну в самом деле: для того, чтобы запускать программы под операционную систему, достаточно сигнала. Запустили программу - она запустилась, демон. Послали ему сигнал «килл» - он умер, послали ему сигнал, дописанный в документации - он там что-то еще сделал. Для того, чтобы управлять этим демоном, написана специальная утилита, которая ходит к этому демону по специальному протоколу и вообще это никак не относится к работе операционной системы. А здесь выясняется, что на рабочем столе есть окна, иконки, трешовница, понятие drag and drop, и так дальше. То есть, рабочий стол предоставляет, вообще говоря, довольно разумный уровень абстракции, существенно более сложными объектами и с существенно более сложной структурой этих объектов, чем взаимодействие процессов на уровне управления процессов. Ну, в самом деле, какую-нибудь простейшую вещь, связанную с тем же самым drag and drop: вот вы запустили файловый менеджер и вот не как в нормальном юниксе, в командной строке, а как полагается в файловых менеджерах: взяли, зацепили мышкой файлик и куда-нибудь его переложили. Вообще говоря, тот факт, что я сделал drag and drop мышкой файлик из того места, где он был, на рабочий стол, и он появился на рабочем столе - желаемый инвариант. Так должны делать любые окружения рабочего стола. И это стало понятно существенно раньше, чем идея какой-нибудь стандартизации, скажем , системных служб, ну, потому что системные службы друг с другом так не взаимодействуют. Поэтому возникло, собственно, две необходимости, и о них мы и поговорим сегодня, плюс маленький бонус про systemd от Арсения.
Возникло две необходимости. Необходимость первая - стандартизовать своего рода объекты для рабочего стола в программном окружении пользователя. Удивительно, но стандарт этот существует уже лет 15, разрабатывается, а следовать ему разработчики, ну, так вот потихонечку начинают. Поначалу все было достаточно странно: у каждого графического окружения - помните, я на первых лекциях их показывал, много разных - все было свое на эту тему: свой drag and drop, свои иконки, свой способ регистрации этих иконок, свое меню. И вторая, на самом деле, еще более главная вещь, которая нужна, для того, чтобы стандартизовать поведение рабочего стола - это какой-то универсальный способ написания тех данных, которые в рамках этого рабочего стола циркулируют, и способов эти данные послать, принять, обработать на каком-то уровне более высоком, чем просто написание программы. То есть придумать какой-то способ, согласно которому у нас будет достаточно универсальное описание, что вот есть, допустим, мусорное ведро, и оно может принимать файлы, и есть программа, которая говорит «я хочу выбросить файлы в мусорное ведро». И есть программа, которая является этим мусорным ведром. И дальше программа по стандартному протоколу «выбросить в мусорное ведро» выбрасывает файл в мусорное ведро, а программа, которая является мусорным ведром, делает то, что полагается с ним делать по стандарту, например складывает в специальный каталог, который называется .trash, кажется. Вот.
С каталогами все понятно, а вот со специальным протоколом, вообще говоря, непонятно. Что у нас имеется в этом случае: имеется такое достаточно специфическое межпроцессное взаимодействие, существенно более сложное, чем, допустим, посылка сигналов, семафоров, вот этого вот всего. Процессы обмениваются объектами. Это значит, что должен быть какой-то универсальный метод обмена этими объектами между процессами, который поддерживает: пространство имен произвольное, чтобы мы могли сказать «все знайте, мой объект такой-то». То есть пространство имен самих объектов, которые… сейчас, давайте введем терминологию. Под словом объект я на самом деле понимаю субъект, действующую программу, которая регистрируется вот в этом пространстве имен. Субъект - это, например, программа трэшовница, или программа, которая хочет выбросить файл в трэш. Под словом «данные» я понимаю ровно то, что между ними ходит. Под словом, допустим, «шина» я понимаю общее место, которое будет аккумулировать эти пространства имен. Ну так вот: должен быть какой-то метод, способ
- объявить о существовании этого пространства имен, где любой объект может зарегистрироваться
- объявить возможность этому объекту предоставлять какие-то услуги для других объектов, например, услугу по выбрасыванию файлов в мусорное ведро
- объявить возможность проверить, какого формата данные этот объект принимает в этом методе, то есть, не просто там любую последовательность байтов посылаешь и внезапно она активизируется и в мусорное ведро выбрасывается, а, вообще говоря, положить файл в мусорное ведро - это операция, которая должна передавать, видимо, имя файла, вернее, путь к нему полный, и еще какие-то дополнительные действия, например, его совсем выбросить, переложить в трэш или что-то такое. Специфицировать более сложный формат. И поскольку у нас на шине может зарегистрироваться очень много объектов, этот формат должен быть обозреваемый, мы должны уметь проверить, а какого же формата данные принимает данный метод.
На самом деле, есть еще одна идея, обратная: это идея связи вот такого рода шины и такого рода объектов с операционной системой и друг с другом. Мы сейчас описали функцию push, когда мы говорим «дорогой объект, выброси файл». Но бывает еще функция, как бы это сказать, wait, когда у нас есть некие объекты-источники данных, например, таким объектом является операционная система, она говорит «а тут флешку примонтировали, никто не хочет?». Или «пришла почта, никто не хочет?». То есть ситуация обратная: мы вместо того, чтобы обращаться к конкретным объектам, чтобы они нам выполнили какие-то действия, мы говорим «я такой-то такой-то, я отвечаю за обработку почты», а другое приложение говорит «пришла почта, забирайте». Первый метод, метод по запросу, когда мы обращаемся к существующему объекту, он называется просто, кажется, сообщения.. Ну запрос, request. А второй метод называется сигнал, когда приложение говорит «вот вам объект, забирайте. Никто не хочет - ну, извините, на нет и суда нет.» Кстати сказать, вот такое взаимодействие, оно вообще никак не прописано: то есть мы каждый раз должны писать какую-то клиент-серверную архитектуру.
Ну вот да, изменение профиля системы. Я воткнул новую клавиатуру. Вот типичный пример, который до сих пор нормально решить не могу, очень хочу его решить. Вот есть ноутбук с ущербной клавиатурой - там ни лампочек никаких лишних, а я люблю, чтобы лампочки зажигались. У меня на ноутбуке вообще только одна лампочка - капс лок, она у меня зажигается в случае переключения на русский, естественно, потому что капс лок используется редко. Втыкаю нормальную клавиатуру: я хочу, чтобы при втыкании нормальной клавиатуры произошло три вещи:
- чтобы это кто-то обнаружил
- чтобы у меня перенастроились иксы - графический сервер - зажигать лампочку скролл лок, а не капс лок, по факту ее включения
- может быть, чтобы я еще перенастроил клавиши, например, чтобы у меня переключение на русский произошло по удобной мне клавише.
Вынул клавиатуру - раз, возникло событие, пошел сигнал, приложение, которое отвечает за настройку иксов, посмотрело на новый профиль графической среды, увидело, что клавиатура другая, и перенастроило.
Вот это все - задача, которая примитивным запуском каких-то там шелл скриптов при запуске системы не решается совсем. Как это все должно происходить в идеале, который пока что не достижим, которого мы неизвестно когда достигнем, а когда достигнем, неизвестно, будет ли он похож на то, что есть сейчас? У нас, как я уже сказал, уже есть механизм реакции на изменения профиля системы, обработки событий в системе, построение зависимости одних служб от других и соответствующий перезапуск пачки и много чего другого. Этот механизм используется системным демоном systemd, но, собственно, сама идея - ее можно реализовать еще как-нибудь. Почему бы нам не воспользоваться этим механизмом для того, чтобы таким же способом строить графическое окружение, ведь фактически, запуск графического окружения - такой же, как запуск операционной системы, только в рамках отдельно взятого пользователя. Такая возможность есть, она, пока что, базовая: в силу причин, о которых я расскажу чуть позже, на этом фронте все еще впереди. Выглядит это так: вы можете запустить свой собственный systemd, совсем не обязательно системный, можно даже от пользователя. По секрету скажу, он даже запускается от имени пользователя:
От имени пользователя python уже запущен systemd, он запущен с кляузой --user. Кстати, обратите внимание, что еще один systemd запущен для пользователа ldm - display manager - та штука, которая встречает нас при логине: она запускается от отдельного пользователя и у нее довольно специфический набор прав, например, она может взять и стать другим пользователем, запустить для него сеанс, что, вообще говоря, требует нарушений дискреционной модели прав доступа, значит, ей кто-то выдает эти права.
Вот этот systemd выглядит примерно так же:
Тут для того, чтобы обеспечивать вам зависимость на наличие устройств, показаны всякие устройства и смонтированы файловые системы. Это делается для того, чтобы вы могли написать свой сервис, который реагирует, например, на появление смонтированной флешки или нового устройства в списке устройств. Дальше, допустим, я хочу написать сервис (спасибо Арсению, который это сделал), который запускается при старте графического окружения. Что я для этого должен сделать: я должен обеспечить моему вот этому systemd -
…а, кстати, у него еще там, кажется… systemctl знает, как к нему ходит, у него открывается специальный сокет, чтобы им управлять, вот туда мы и лезем, когда говорим systemctl. Ну так вот: во-первых, нам нужно рассказать нашему systemd о том, что иксы уже запущены и теперь нужно запускать приложения, которые будут выводить на иксовый сервер что-то. В идеале это должна быть последовательность старта графической подсистемы, но, повторяю, она устроена по-другому, поэтому я показываю примитивные кирпичики, из которых она, по идее, должна быть устроена. Поэтому что мы делаем: мы можем запустить его вручную:
говорим, дорогой systemd, у тебя появился новый таргет, он называется graphical-session. Вот в тот момент, когда мы дадим эту команду, этот таргет появляется. Соответственно, пока мы ее не дали, у нас systemd считает, что этот таргет не достигнут, и если мы поставим какой-нибудь сервис, который зависит от него, он еще к этому моменту не может быть запущен, потому что у нас определена зависимость.
Теперь давайте опишем сервис, который зависит от этого таргета, ну, допустим, xclock какой-нибудь:
Он достаточно простой. Если ему нужны какие-то переменные окружения, то он их найдет в этом файле:
%t - временный каталог, если мне не изменяет память.
А в остальном тут ничего интересного. Запустить вот эту программу - /usr/bin/xclock. Когда? После достижения graphical-session.target.
Собственно, теперь мы можем сказать:
Хлобысь:
Именно их мы видели при старте, потому что он запустился. Потому что таргет был достигнут и наш пользовательский systemd запустил вот этот сервер. Давайте скажем status:
Таково, повторяю, прогнозируемое мною будущее. Мои прогнозы могут не сбыться, потому что мы избавимся от решения одних и тех же задач многими способами, у каждого из которого есть свои грабли. Теперь относительно того, как решаются эти задачи сейчас. Давайте начнем с самого начала: как решалась эта задача раньше путем последовательного запуска шелл скриптов - до сих пор она решается так же во многих случаях. У вас запускается так называемый сеанс работы Х-сервера, этот сеанс означает запуск не только самого Х-сервера, но и кучи приложений и эти приложения по схеме .d имеют свои запускающие сценарии, которые лежат в разных интересных местах, например:
Это пересечение двух разных легаси: в одних дистрибутивах делается так, в других, почему-то, так. Этому легаси лет 20 точно есть, какой-то из них постарше. Запускается вот эта пачка приложений. Потом, на самом деле, в процессе этого еще какие-то приложения запускаются. Потом мы идем сюда и запускаем все шелл скрипты, которые там есть.
И вот там-то как раз, спасибо, опять таки, доброму Арсению, он нам положил соответствующий таргет. То есть, иксы уже запущены, системная часть из /etc/X11/xinit* уже запущена, и после этого запускаются пользовательские какие-то дополнительные приложения.
Это, повторяю, один их самых древних механизмов организации рабочей среды, когда мы просто запускаем последовательно все имеющиеся шелл сценарии на эту тему.
Следующий уровень, который, на самом деле, сейчас и в основном возобладал: когда графическое окружение само заботится о запуске своих компонентов и делает это по-разному.
Было бы неплохо сделать это не по-разному: было бы неплохо навести какую-то стандартизацию. Стандартизацией графического окружения занимается команда, которая называется freedesktop и описание всевозможных стандартов, которые они предлагают (стандартов в том смысле не стандарты, а такие вот «а давайте делать вот так, ребята, мы придумали вот, вроде мы продумали все, давайте делать, как мы придумали, потому что если вы будете делать как вы придумали - будет только хуже»). Так вот, попытка стандартизировать вот этот вот межпроцессные взаимодействия, обмен между процессами и порядок организации графической среды, она как раз привела к тому, что организовалась прикладная шина под названием d-bus, которой тоже занимается freedesktop, ну, есть целая команда. Ну, вот. Итак, что это такое: это API, то есть, соглашение для программистов о том, как программировать межпроцессное взаимодействие, которое включает в себя понятие, собственно, шины - это пространство имен, через которое будет происходить взаимодействие, понятие «подключение к этой шине» или имя этого подключения. Что касается имен подключения - их бывает два вида: первое по принципу «кто первый встал - того и тапки», «я подключился ЧЕТВЕРТЫМ к нашей шине, значит у меня будет подключение 1.4». Второе, так называемое, well-known, которое мы анонсируем, собственно, наше подключение - вот такое. И тут вроде как даже понятно, например, очевидно, что программа под названием xfdesktop подключилась к шине и называет себя вот так:
И опять таки мы имеем ситуацию, что для каждого пользователя, включая: запущенный dbus для всей системы:
dbus, запущенный для того самого ldm:
и dbus, который запущен для пользователя python и пространство имен которого мы просмотрели:
Можно посмотреть более красивым способом:
Тут названия подключений и их уникальные номера. Обратите внимание, что в операционной системе тоже очень много на dbus шине подключений. В действительности, очень много программ запущено, либо сообщают о себе операционной системе, либо наоборот слушают, что им там протокол dbus расскажет по системной шине. Помните два типа взаимодействия - выставить объект, который будет выполнять услуги, или подписаться на сигнал, который будет исходить от объекта. Ровно так происходит реагирование на изменение системного профиля. А вот это наш dbus запущенный для нас:
Тут, если посмотреть, видны разные вполне очевидные вещи. Заодно расскажу о том, что лежит за подключением.
Thunar. Смотрите: вот это наш адрес - это unix-домен сокет, открытый в этом каталоге:
А дальше его имя и его уникальное имя, которое он получает, когда конектится к шине.
Что объект, подключившийся к шине, публикует? Он публикует интерфейсы: по каким протоколам он готов обслуживать клиентов, или по каким протоколам он готов посылать сигналы, которые он посылает. Вот список интерфейсов, которые есть у Thunar:
- обязательный интерфейс Introspectable: для того, чтобы получать от самого подключившегося объекта информацию о типах данных, которые ему нужны - специальный интерфейс Properties: всегда можно посмотреть
- поддерживается интерфейс Trash
- поддерживается свой собственный интерфейс Thunar
Thunar - файловый менеджер, и вот он поддерживает метод DisplayFolder - мы сейчас узнаем что он делает. Ему нужно передать 3 параметра: строчку, экран, на который будет выведено окошко и startup_id. Мы вызываем метод объекта, который называется org.xfce.Thunar, и который по интерфейсу org.xfce.FileManager имеет метод DisplayFolder, мы посылаем запрос с содержимым «имя файла, дисплей, на котором будет открыто окно и непонятный идентификатор, про который я ничего не знаю».
Вупс:
То, что сейчас произошло - следствие того, что я послал по dbus-у сообщение некоторому объекту.
У него даже есть сигнал, который называется TrashChanged: если что-то изменилось в мусорном ведре - нам об этом сообщит org.xfce.Thunar и скажет «ааааа, у нас ведро поменялось».
Маленькое отступление: откуда все это пошло? Идея написать таким образом целиком даже целую операционную систему, была давно. Возможно, вы помните, был такой проект, который назывался CORBA. Идея состояла в том, что все объекты распределенной системы представляются как объекты, обменивающимися сообщениями. Самое смешное, что она даже была реализована в той или иной степени. Более того, она была реализована даже в качестве графической среды. Получилось так медленно! Что просто хоть стой, хоть падай. Если мы обеспечиваем все процессные взаимодействия уникальным универсальным интерфейсом, то какое-нибудь там копирование мегабайтов данных - щелкнул, пошел к шине, получил запрос, сходил, скопировал туда кусочек, получил ответ, скопировал еще кусо… И все это на прикладном уровне, да? Сопровождающееся сотнями переключений контекста, и все это 30 лет назад. 20. Не говоря уже о том, что, как все честные люди, у каждого такого метода есть еще и версия: если версии не совпадают - работать не будет. Короче говоря, все это не работало. Были люди, которые пытались это реализовать. Это работало из рук вон плохо, и поэтому стали делать такие замены. Наиболее адекватной оказалась замена только шины, по которой взаимодействуют приложения по данным. Вот если вам нужно передать файл, вы говорите: «вон тот файл передай», если вам нужно убить файл - так и говорите. А вот если вам нужно ввести более высокий уровень абстракции и сказать «здесь возникает событие, а вот там должен породиться процесс» - вот тогда нужно воспользоваться этим методом. Мне кажется, тут достаточно прозрачно: запущены программы, они регистрируются на шине, как объекты, как какие-то подключения, объект называется вот так, у него есть методы и эти методы можно вызывать. Видите эту красную кнопочку?
Если я ее нажму - закончится запись скринкаста, потому что для того, чтоб записать скринкаст, я запустил специальную программу, которая называется yad, вот она:
которая зарегистрировалась в трее и обрабатывает нажатие на этот трей. Нажатие будет запуском шелл скрипта. Так что мы пока находимся в плане развития всего этого безобразия где-то посередине: между идеалом, когда у нас метод управления системой и метод управления рабочим столом будет одинаковый и не надо будет заучивать 3-4-5-6 разных систем этого идеала. И какой он будет - пока непонятно.
Я обещал рассказать еще об одной фишке: почему, собственно, мы в таком положении уже лет 5 точно. Смотрите. Где там наш d-feet... Обратите внимание, что тут есть большое количество зарегистрированных объектов, которые, ну скажем, d-feet говорит, что объекты как бы есть, но их как бы нет, и что их можно активировать - activatable, они еще курсивом обозначены. Что это значит: это значит, что на самом деле обработчики для них еще не запущены. Вот я кликнул на него и обработчик запустился - вот cheese. Cheese это для работы с веб-камерой. Она не была запущена, пока я не кликнул на него, и тут бац - она запустилась.
И дальше мы можем заставить этот cheese что-нибудь делать.
То есть, dbus поддерживает специальный метод активации и запуска обработчика по этому интерфейса: то есть обработчика нет, я на него потыкал, он появился, dbus запустился. Вам это ничего не напоминает? Это же активация в systemd! Сейчас они договариваются, кто же все-таки должен запускать программы: systemd или dbus. И по этой же причине, в числе прочих причин, dbus был и остается прикладной шиной, в ядро его не собираются запускать. Поскольку если в ядре появится еще один механизм запуска приложений, еще и такой, на С++ написанный, невирифицированный. Так что будущее наше достижимо неизвестно когда, и мне кажется - опять же, чистое вангование - результат будет такой, что из dbus выпилят все то, что должен обслуживать системный демон - активацию, оставят только межпроцессное взаимодействие, сделают его надежным, и тогда его уже можно будет смело впиливать в ядро и не поддерживать вот эти сообщения передачи. Там будут свои проблемы, например, переполнение буфера, но, блин, кто ж без проблем этих.
Чтобы закончить сегодняшнюю лекцию, давайте поговорим о самопровозглашенных стандартизаторах, которые первое, что они говорят - нет, мы не делаем стандарт. О чем сейчас так или иначе уже договариваются люди, которые делают графическое окружение и все остальное? Ну, например, все уже договорились о такой штуке, которая называется спецификация десктоп файла, десктоп файлы я на одной из лекций показывал. На самом деле, не такой уж простой формат, как видите, который включает в себя, во-первых, описание того, а что, собственно, за объект мы описываем, какая будет у него иконка, какое у него будет описание, причем, на всех возможных языках, в каких случаях его показывать, в каких не показывать, например, если он специфичен для определенного вида десктоп, связь его с dbus, если это запускаемый файл - какую программу запускать, запускать, может быть, его в командной строке, если эта программа поддерживает открытие файлов - типы файлов, согласно стандарту MIME, которые могут ею открываться - очень удобная вещь, потому что составляется специальная база данных этих MIME типов и когда вы тыкаете файл на десктопе, вам открываются именно те программы, которые зарегистрировали себя как соответствующие MIME type. Вот, и классификатор. Довольно забавный, но все-таки классификатор. Ну и всякие базовые штуки, например, нужно ли рисовать курсорчик, когда программа запускается, вот это все. Пример десктоп файлов: firefox.desktop
Что мы видим здесь:
Exec=firefox %u - запустить программу firefox с параметром %u, не знаю, что это такое, думаю, что URL.
Icon=firefox - взять иконку firefox. Есть стандарт на то, во что, собственно, раскрывается здесь написанное слово firefox. В специальном заранее определенном месте лежат иконки, разделенные на icon sets, которые, в свою очередь, разделены на растровые и векторные, и согласно тому, чего хочет ваш рабочий стол, будут выбраны соответствующие иконки. Поскольку в стандарте есть - считается правильным тоном написать сюда просто название файла, а уж какого он размера, где лежит и какой имеет конкретный тип - это не вашего ума дела, пускай стандарт и разбирается.
Type=Application - тип - приложение, т.е. он будет запускаться
Name=Mozilla Firefox - название, на разных языках.
MimeType - смотрите, в этом десктоп файле специфицировано, какого типа файлы эта программа может открывать, в данном случае это, понятно, всякие html.
StartupNotify=true - нужно ли рисовать прыгающий курсорчик, если кто-то хочет рисовать прыгающий курсорчик? Нужно.
X-KDE-StartupNotify=true - отдельное, начинающееся на X- поле, которое стандартом не предусмотрено, а которое будет разбирать конкретный десктоп, в данном случае, КДЕ, разницы не вижу.
Categories - категоризатор.
Десктоп может быть описателем не только программы, но и URL-а, который открывается, ну и еще чего-нибудь.
Он довольно сложный, тут много разных дополнений, которые можно вставлять. Откуда взялось слово «Рабочий стол»? Это тоже часть стандарта, это стандарт basedir, и на самом деле, он не такой простой, что «рабочий стол» должен называться «рабочий стол», на самом деле, у вас есть специальное место, где определяются соответствующие переменные. Они все определяются, и сообразно им идет именование ваших каталогов.
Таким образом, у вас он может называться как угодно. Программы, которые будут поддерживать этот стандарт, будут ходить не в каталог «Рабочий стол», а в каталог, название которого записано в переменной окружения. Конфигурационные файлы лежат в каталоге .config/. Точно так же, какой-нибудь кэш лежит в каталое .cache/
Раньше был каталог .thumbnail/, но он переехал в ./cache, потому что он, очевидно, кэш.
Что еще интересного можно посмотреть? Спецификация меню. Вот это меню, вообще говоря, генерится засчет анализа десктоп файлов:
Но есть и специфика, потому что, понятно, не всегда пачка десктоп файлов соответствует тому, что должно появиться в меню. Поэтому у фридесктопа есть рекомендация по тому, из чего состоит меню и как его собирать. Например, что писать в десктоп файл для того, чтобы из него было сгенерировано меню правильной категории.
Опять же, как человек, который пользуется линуксом довольно давно, в сообществе Debian задумались об этом довольно давно и разработали свой собственный вариант меню, которым больше никто не пользовался. Ну, потому что никто больше не задумывался о том, что это проблема. Представляете, лет 20 назад накидать какие-то пункты в меню было делом администратора, которое он делает раз в сколько-то лет.
Тип описателя того, какого типа являются данные в MIME type. Есть специальный каталог, который называется mime, в котором в разных подкаталогах лежат описания разных типов файлов. В них, правда, в формате xml, который не для пользователей, то есть не для людей, описаны разные названия, как предположительно будет выглядеть файл и, собственно говоря, само наличие этого MIME файла позволит к нему обратиться и сказать, что «я буду использовать вот это название: obrázek.png», вот. А по содержимому кэша этих маймов будет выяснено, что это, собственно файл *.png - прямая связь к описанию, которое было там.
Автостарт стандартный интересен не тем, какой он, а тем, что он существует, и входит в конфликт с понятием автостарта путем запуска через systemd. То есть все это еще варится, мы прямо посредине этого сейчас застряли, и когда они договорятся - неизвестно.
Еще больше у них всяких предложений в развитии, например, drag and drop какой-нибудь, спецификация того, что должен уметь делать window manager, каким способом передается информация, которая передается в буфер обмена. Как сделать так, чтобы приложение вставило то, что вы скопировали? Ну и так дальше.
Резюме
Когда вы работаете с линукс-системой с графическим окружением, управлять самой системой вы можете из командной строки безо всяких проблем. Некая подковёрная жизнь этой графической среды - какие-то сообщеньки, которые появляются, внезапно возникающие смонтированные устройства, вот это вот все - результат обмена этих самых приложенек данными друг с другом и с операционной системой, скорее всего, с помощью пресловутой dbus. Самозапуск системы - как видите, dbus тоже умеет их активировать. Ничего, на самом деле, подковёрного в этом нету, просто внутренности этого обмена данными не предназначены для чтения глазами и мы с вами это видим. Если очень хочется - это можно сделать, понаблюдать, как это происходит, есть, в конце концов, dbus-монитор, который может показать все, что происходит. Можно даже воспользоваться программными средствами, которые на это реагируют, но лучше, если вы действительно хотите этим пользоваться, написать для этого свою программу, допустим, на питоне - любой высокоуровневый язык подходит. Скажем так, программный интерфейс к dbus есть и сишный, естественно, но документация по сишному интерфейсу dbus-а открывается словами «Если вы случайно открыли эту документацию - закройте и никогда не пользуйтесь ею». Не надо писать на C, пишите на высокоуровневых языках».
Экзамен планируется 27-го, на экзамен надо записываться на почту: frbrgeorge@gmail.com, причем в этой самой почте обязательно должны встречаться ключевые слова «экзамен» и «linux». Экзамен будет происходить так: я постараюсь за ближайшее время написать список вопросов, в зависимости от того, сколько будет народу, будет соответствующее число экзаменаторов, поделимся там по 7 человек на одного экзаменатора и поговорим про весь курс от начала до конца, это будет длиться где-то часа 2, то есть, возможно, он будет пораньше, часов в 6. По экзамену можно получить любую оценку, в том числе не получить. Если кому-то нужен зачет - говорите об этом заранее, зачет соответствует четверке, тройке не соответствует.