Введение в ос linux

Вид материалаДокументы

Содержание


Отец всех процессов
Запуск системных служб
Чему служат демоны?
Стартовый сценарий системной службы
Схема ". d"
Подобный материал:
1   ...   29   30   31   32   33   34   35   36   ...   62

Отец всех процессов


Если в параметрах не сказано иного, ядро считает, что init называется /sbin/init. В стартовом виртуальном диске это обычно некоторый простейший сценарий, а в полноценной системе у init другая задача: он запускает все процессы. Если не он сам, то его потомки, так что все процессы Linux, кроме ядерных, происходят от init, как весь род людской -- от Адама.

Первым делом init разбирает собственный конфигурационный файл -- /etc/inittab. Файл этот имеет довольно простую структуру: каждая строка (если она не комментарий) имеет вид "id: уровни: действие: процесс", где id -- это некоторая двух- или однобуквенная метка, уровни -- это слово, каждая буква которого соответствует уровню выполнения, (об уровнях выполнения будет рассказано далее), действие -- это способ запуска процесса. Например, запись 4:2345:respawn:/sbin/mingetty tty4 означает, что меткой "4" помечен запуск /sbin/mingetty tty4(6) на уровнях выполнения 2, 3, 4 и 5 по алгоритму "respawn" (запустить в фоне, а когда процесс завершится, запустить заново). Помимо "respawn" существуют методы "once" (запустить в фоне однократно), "wait" (запустить интерактивно, при этом никаких других действий не выполняется, пока процесс не завершится) и множество других, включая даже "ctrlaltdel" -- процесс, запускаемый, когда пользователь нажимает на консоли Ctrl+Alt+Del(7).

Наконец-то Мефодий до конца понял, отчего getty ведёт себя так непохоже на остальные процессы: не просто запускает из-под себя login, а дожидается окончания его работы, отсутствуя при этом в таблице процессов. На самом деле дожидается не getty, а init, используя метод "respawn": порождается (в фоне) процесс getty с определённым PID, а init бездействует до тех пор, пока существует процесс с этим PID getty, login, стартовый командный интерпретатор или программа, запущенная из него с помощью exec); когда же процесс, наконец, умирает, порождается новый getty.

Запуск системных служб


Полноценно загруженная Linux-система -- не только login на виртуальной консоли. Системе есть чем заняться и помимо идентификации пользователей. Даже если компьютер не работает WWW-, FTP- или почтовым сервером для "внешнего мира", себе самой и своим пользователям система предоставляет множество услуг: отсылка заданий на печать и обеспечения их очереди, запуск заданий по расписанию, проверка целостности и т. п. Набор утилит и системных программ, предназначенных для предоставления таких услуг, принято называть подсистемами или службами.

Чему служат демоны?


Как правило, системная служба организована так. Во время начальной загрузки запускается в фоновом режиме программа, которая всё время работы системы находится в таблице процессов, однако большей частью бездействует, ожидая, когда её о чем-нибудь попросят. Для того, чтобы попросить эту программу об услуге, которую она предоставляет, используются утилиты, взаимодействующие с ней по специальному протоколу. По аналогии с сократовским "даймонионом", который незримо присутствует, по своей инициативе не делает ничего, не даёт совершать плохое и потворствует хорошему, такую программу стали называть "daemon". Не знакомые с творчеством Платона программисты-любители частенько переименовывали её в "demon" (демон); к сожалению, именно в такой, слегка инфернальной форме, daemon и вошёл в русскоязычную терминологию. Выходит, что в Linux услуги пользователям предоставляют... демоны!

демон

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

В ранних версиях UNIX всё, что нужно было запускать при старте системы, вписывалось в inittab. Было довольно удобно в одном файле указывать, какие именно демоны должны работать в системе, и в каком порядке их запускать. Само поведение демона при запуске явно рассчитано на использование в inittab по методу "wait": классический демон запускается интерактивно, проверяя правильность конфигурационных файлов и прочие условия работы, а затем самостоятельно уходит в фон (попросту делая fork() и завершая родительский процесс). Таким образом, init ждёт, пока демон работает интерактивно, а когда служба, возглавляемая этим демоном, готова к работе, переходит к следующей строке inittab. Однако часто бывает так, что автор демона знать не знает, какие именно условия разработчики той или иной версии Linux сочтут пригодными для запуска. Для этого ими создаётся стартовый сценарий, в котором запрограммирована логика запуска и останова службы. Кроме того, если на каждом из уровней выполнения запускается много различных служб, попытка записывать их запуск в inittab делает его громоздким и совсем неочевидным.

Гуревич посоветовал Мефодию отложить на время изучение загрузки системы, а сначала посмотреть, как управлять стартовыми сценариями.

Стартовый сценарий системной службы


Стартовый сценарий -- программа (обычно написанная на shell), управляющая включением или выключением какого-нибудь свойства системы. Это может быть запуск и остановка HTTP-сервера, активизация и деактивизация сетевых настроек, загрузки модулей и настройка звуковой подсистемы и т. п. Простейший стартовый сценарий обязан принимать один параметр, значение которого может быть словом "start" для запуска (включения) и "stop" для остановки (выключения). Если в определённом дистрибутиве Linux принято решение, что стартовые сценарии должны понимать и другие параметры, например "restart" (обычно "stop" + "start", но не всегда) и "status" (для опроса состояния), это требование распространяется на все стартовые сценарии. Единообразие позволяет, например, легко запускать и останавливать демоны, не выясняя, каков PID останавливаемого процесса и какой именно сигнал ему следует послать. Достаточно запуск написать так, чтобы PID процесса откладывался в специальный файл (обычно /var/run/имя_службы), а в остановку вписать что-то вроде kill -правильный_сигнал `cat /var/run/имя_службы`.

Все стартовые сценарии служб, которыми может воспользоваться система, принято хранить в каталоге /etc/rc.d/init.d (в некоторых дистрибутивах, для совместимости со старыми версиями UNIX, используется /etc/init.d, иногда это -- просто символьная ссылка на /etc/rc.d/init.d). Запустить или остановить службу можно, просто вызвав соответствующий сценарий с параметром "start" или "stop". Часто ту же самую задачу выполняет и специальная команда service -- которая проверяет, есть ли указанный стартовый сценарий, и запускает его(8).

[root@localhost root]# lsmod > old

[root@localhost root]# /etc/rc.d/init.d/sound stop

Saving OSS mixer settings: [ DONE ]

Unloading sound module (es1371): [ DONE ]

[root@localhost root]# lsmod > nosound

[root@localhost root]# service sound start

Loading sound module (es1371): [ DONE ]

Loading OSS mixer settings: [ DONE ]

[root@localhost root]# lsmod > new

[root@localhost root]# diff3 old new nosound

====3

1:2,5c

2:2,5c

es1371 25608 0

ac97_codec 11880 0 [es1371]

soundcore 3652 4 [es1371]

gameport 1628 0 [es1371]

3:1a

Перезапуск звуковой подсистемы

Здесь Мефодий сначала остановил, а потом снова активизировал звуковую подсистему. Остановка привела к выгрузке звуковых модулей, а повторный запуск -- к загрузке, полностью аналогичной исходной. В этом Мефодий убедился, сравнив с помощью утилиты diff3 три списка модулей: old (до остановки звуковой подсистемы), new (после повторного запуска) и nosound (между остановкой и повторным запуском). Файлы old и new полностью одинаковы, а от nosound оба отличаются тем, что со второй строки по пятую содержат названия тех самых модулей ядра (среди которых затесался gameport, отвечающий за джойстик).

Схема ". d"


Итак, имеется способ единообразно и гибко управлять запуском и остановкой каждой системной службы в отдельности (или включением и выключением одного свойства системы). Однако задача целиком организовать загрузку системы, от запуска init до полноценной работы, этим ещё не решается. Первая из возникающих задач такова: чаще всего нужно загружать не все из размещённых в /etc/rc.d/init.d сценариев, потому что некоторые из установленных в системе служб администратор решил не использовать. Удалять оттуда не используемые при загрузке сценарии -- значит, лишать администратора возможности запускать эти сценарии вручную.

Создателям ранних версий UNIX пришла в голову простая мысль: написать один большой сценарий по имени /etc/rc, в который и заносить только нужные для запуска команды вида /etc/init.d/сценарий start. Можно даже занести туда все имеющиеся стартовые сценарии, но строки, запускающие те, что не используются, закомментировать. Такая (монолитная) схема имела существенный недостаток: добавление и удаление службы в систему (например, добавление и удаление пакета, содержащего исполняемые файлы службы) требовало редактирования этого файла. Если учесть, что порядок запуска служб весьма важен (например, бессмысленно запускать сетевые демоны до активизации сетевых настроек), становится ясно, что автоматическое изменение такого файла не может гарантировать нормальную загрузку системы, а значит, недопустимо.

На помощь пришла тактика, известная под именем "схема. d". Суть её в следующем. Пусть некоторый процесс управляется конфигурационным файлом, содержимое которого зависит от наличия и активации других служб системы (таким процессом может быть демон централизованной журнализации syslogd, ведущий журнал всех событий системы, или сетевой метадемон inetd, принимающий сетевые запросы и превращающий сетевой поток данных в обыкновенный посимвольный ввод-вывод). Тогда, чтобы избежать постоянного редактирования конфигурационного файла, его превращают в каталог (например, вдобавок к файлу /etc/xinetd.conf заводится каталог /etc/xinetd.d). Каждый файл в таком каталоге соответствует настройке одной службы: при добавлении её в систему файл появляется, при удалении -- исчезает. Остаётся только обучить тот же xinetd читать настройки не из одного xinetd.conf, но и из всех файлов в xinetd.d, и задача решена.

На случай запускаемых сценариев схема ". d" распространяется с двумя дополнениями. Во-первых, как уже было сказано, стартовые сценарии можно запускать, а можно и не запускать. Поэтому сам init.d не годится на роль ". d"-каталога. Впрочем, достаточно организовать ещё один каталог, скажем, rc.d, и создать там ссылки (для наглядности лучше символьные) на те сценарии из init.d, которые планируется запускать при старте системы. Общий стартовый сценарий rc как раз и будет заниматься запуском стартовых сценариев из rc.d.

Во-вторых, необходимо обеспечить строгий порядок запуска этих сценариев. Теоретически это совсем просто: отсортировать их по алфавиту, как это делает ls, и запускать подряд. Практически же такое требование накладывает ограничение на имя ссылки в ". d"-каталоге, поэтому принято, чтобы в начале имени стояло двузначное число. Тогда, запуская подряд все сценарии, отсортированные алфавитно, rc будет в первую очередь руководствоваться этим номером, а уж потом -- названием службы, которое после него стоит. Конец формы