Системные вызовы setrlimit() и getrlimit() позволяют процессу устанавливать и получать ограничения на потребление им разных ресурсов. Каждое ограничение состоит из двух значений: мягкого, действие которого обеспечивается ядром, и жесткого, которое является граничным значением для мягкого ограничения. Непривилегированный процесс может устанавливать мягкие ограничения на ресурсы в диапазоне от 0 до жесткого ограничения (которое нельзя превысить). Привилегированный процесс может вносить любые изменения в ограничения обоих типов, но при этом мягкое ограничение всегда должно быть меньше жесткого или равно ему. Достигая мягкого ограничения, процесс обычно уведомляется об этом факте либо с помощью сигнала, либо неудачным завершением системного вызова, который пытается превысить ограничение.

36.5. Упражнения

36.1. Напишите программу для демонстрации того, что флаг RUSAGE_CHILDREN вызова getrusage() получает информацию только о потомках, для которых была выполнена операция wait() (пусть программа создаст дочерний процесс, потребляющий некоторое процессорное время, затем родитель должен сделать вызов getrusage() до и после wait()).

36.2. Напишите программу, которая выполняет команду и затем показывает, сколько она потребила ресурсов. Это аналогично действию команды time(1). Запускаться она должна следующим образом:

$ ./rusage command arg…

36.3. Напишите программу, чтобы определить, что происходит при исчерпании процессом различных ограничений, которые задаются с помощью вызова setrlimit().

<p>37. Демоны</p>

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

37.1. Краткий обзор

Демон (англ. daemon) — это процесс, обладающий следующими свойствами.

• Имеет длинный жизненный цикл. Часто демоны создаются во время загрузки системы и работают до момента ее выключения.

• Выполняется в фоновом режиме и не имеет контролирующего терминала. Последняя особенность гарантирует, что ядро не сможет генерировать для такого процесса никаких сигналов, связанных с терминалом или управлением заданиями (таких как SIGINT, SIGTSTP и SIGHUP).

Демоны создаются для выполнения специфических задач. Например:

• cron — демон, который выполняет команды в запланированное время;

• sshd — демон защищенной командной оболочки, который позволяет входить в систему с удаленных компьютеров, используя безопасный протокол;

• httpd — демон HTTP-сервера (Apache), который обслуживает веб-страницы;

• inetd — демон IP-служб (описан в разделе 56.5), который ожидает входящих сетевых подключений на заданных портах TCP/IP и запускает соответствующие серверные программы для их обслуживания.

Многие стандартные демоны работают в качестве привилегированных процессов (то есть их действующий пользовательский идентификатор равен 0), поэтому при их написании следует руководствоваться рекомендациями, перечисленными в главе 38.

Названия демонов принято заканчивать буквой d (хотя это не является обязательным правилом).

В Linux некоторые демоны выполняются в качестве потоков ядра. Код таких процессов является частью ядра и обычно запускается во время загрузки системы. Команда ps(1) выводит их названия в квадратных скобках ([]). В качестве примера можно привести демон pdflush, который периодически сбрасывает «грязные» страницы памяти (например, страницы из кэша буфера) на диск.

37.2. Создание демона

Для того чтобы стать демоном, программа должна выполнить следующие шаги.

1. Сделать вызов fork(), после которого родитель завершается, а потомок продолжает работать (в результате этого демон становится потомком процесса init). Этот шаг делается по двум следующим причинам.

• Исходя из того, что демон был запущен в командной строке, завершение родителя будет обнаружено командной оболочкой, которая вслед за этим выведет новое приглашение и позволит потомку выполняться в фоновом режиме.

• Потомок гарантированно не станет лидером группы процессов, поскольку он наследует PGID от своего родителя и получает свой уникальный идентификатор, который отличается от унаследованного PGID. Это необходимо для успешного выполнения следующего шага.

2. Дочерний процесс вызывает setsid() (см. раздел 34.3), чтобы начать новую сессию и разорвать любые связи с контролирующим терминалом.

3. Если после этого демон больше не открывает никаких терминальных устройств, мы можем не волноваться о том, что он восстановит соединение с контролирующим терминалом. В противном случае нам необходимо сделать так, чтобы терминальное устройство не стало контролирующим. Это можно сделать двумя нижеописанными способами.

• Указывать флаг O_NOCTTY для любых вызовов open(), которые могут открыть терминальное устройство.

Перейти на страницу:

Похожие книги