
- •Часть 3. Подсистема управления процессами
- •Глава 7. Среда окружения процесса 2
- •Глава 8. Управление процессами 16
- •Глава 9. Взаимоотношения между процессами 49
- •Глава 10. Сигналы 62
- •Глава 11. Процессы-демоны 98
- •Глава 7. Среда окружения процесса
- •7.1. Введение
- •7.2. Функция main
- •7.3. Завершение работы процесса
- •7.3.1. Функции семейства exit
- •7.3.2. Функция atexit
- •7.4. Аргументы командной строки
- •7.5. Раскладка памяти программы на языке c
- •7.6. Разделяемые библиотеки
- •7.7. Распределение памяти
- •7.8. Список переменных окружения
- •7.9. Функции getrlimit и setrlimit
- •7.10. Выводы по главе 7
- •7.11. Упражнения по главе 7
- •Глава 8. Управление процессами
- •8.1. Введение
- •8.2. Идентификаторы процесса
- •8.3. Функция fork
- •8.4. Совместное использование файлов
- •8.5. Функция exit
- •8.6. Функции wait и waitpid
- •8.7. Гонка за ресурсами
- •8.8. Функция exec
- •8.9. Изменение идентификаторов пользователя и группы
- •8.9.1. Функции setreuid и setregid
- •8.9.2. Функции seteuid и setegid
- •8.9.3. Идентификаторы группы
- •8.10. Интерпретируемые файлы
- •8.11. Функция system
- •8.12. Идентификация пользователя
- •8.13. Временные характеристики процесса
- •8.14. Выводы по главе 8
- •8.15. Упражнения по главе 8
- •Глава 9. Взаимоотношения между процессами
- •9.1. Введение
- •9.2. Вход с терминала
- •9.2.1. Вход в систему с терминала в bsd-системах
- •9.2.2. Вход в систему с терминала в Linux
- •9.3. Вход в систему через сетевое соединение
- •9.3.1. Вход в систему через сетевое соединение в bsd-системах
- •9.3.2. Вход в систему через сетевое соединение в Linux
- •9.4. Группы процессов
- •9.5. Сессии
- •9.6. Управляющий терминал
- •9.7. Функции tcgetpgrp, tcsetpgrp и tcgetsid
- •9.8. Выводы по главе 9
- •9.9. Упражнения по главе 9
- •Глава 10. Сигналы
- •10.1. Введение
- •10.2. Концепция сигналов
- •10.3. Функция signal
- •10.3.1. Запуск программы
- •10.3.2. Создание процесса
- •10.4. Ненадежные сигналы
- •10.5. Прерванные системные вызовы
- •10.6. Реентерабельные функции
- •10.7. Надежные сигналы. Терминология и семантика
- •10.8. Функции kill и raise
- •10.9. Функции alarm и pause
- •10.10. Наборы сигналов
- •10.11. Функция sigprocmask
- •10.12. Функция sigpending
- •10.13. Функция sigaction
- •10.14. Функция sigsuspend
- •10.15. Функция abort
- •10.16. Функция system
- •10.17. Функция sleep
- •10.18. Дополнительные возможности
- •10.19. Выводы по главе 10
- •10.20. Упражнения по главе 10
- •Глава 11. Процессы-демоны
- •11.1. Введение
- •11.2. Характеристики демонов
- •11.3. Правила программирования демонов
- •11.4. Журналирование ошибок
- •11.5. Демоны в единственном экземпляре
- •11.6. Соглашения для демонов
- •11.7. Модель клиент-сервер
- •11.8. Выводы по главе 11
- •11.9. Упражнения по главе 11
11.6. Соглашения для демонов
В ОС Linux демоны придерживаются следующих соглашений:
если демон использует файл блокировки, то этот файл помещается в каталог /var/run. Однако чтобы создать файл в этом каталоге, демон должен обладать привилегиями суперпользователя. Имя файла обычно имеет вид name.pid, где name – имя демона или службы. Например, демон cron создает файл блокировки с именем /var/run/crond.pid;
если демон поддерживает определение дополнительных настроек, то они обычно сохраняются в каталоге /etc. Имя конфигурационного файла, как правило, имеет вид name.conf, где name – имя демона или службы. Например, конфигурационный файл демона syslogd называется /etc/syslog.conf;
демоны могут запускаться из командной строки, но все-таки чаще всего запуск демонов производится из сценариев инициализации системы (/etc/rc* или /etc/init.d/*). Если после завершения демон должен автоматически перезапускаться, мы должны указать это процессу init, добавив запись respawn в файл /etc/inittab;
если демон имеет конфигурационный файл, то настройки из него считываются демоном во время запуска, и затем он обычно не обращается к этому файлу. Если в конфигурационный файл были внесены изменения, то демон пришлось бы останавливать и перезапускать снова, чтобы новые настройки вступили в силу. Во избежание этого некоторые демоны устанавливают обработчики сигнала SIGHUP, в которых производится считывание конфигурационного файла и перенастройка демона. Поскольку демоны не имеют управляющего терминала и являются либо лидерами сессий без управляющего терминала, либо членами осиротевших групп процессов, у них нет причин ожидать сигнала SIGHUP. Таким образом, он может использоваться для других целей.
Пример. Программа, представленная листингом 11.4, демонстрирует один из способов заставить демон перечитать файл конфигурации.
Листинг 11.4. Реализация демона, который перечитывает конфигурационный файл по сигналу
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <syslog.h>
extern void daemonize(const char *);
extern int already_running(void);
void reread(void)
{
/* ... */
}
void sigterm(int signo)
{
syslog(LOG_INFO, "Получен сигнал SIGTERM; выход");
exit(0);
}
void sighup(int signo)
{
syslog(LOG_INFO, "Чтение конфигурационного файла");
reread();
}
int main(int argc, char *argv[])
{
char *cmd;
struct sigaction sa;
if ((cmd = strrchr(argv[0], '/')) == NULL)
cmd = argv[0];
else
cmd++;
/*
* Перейти в режим демона.
*/
daemonize(cmd);
/*
* Убедиться в том, что ранее не была запущена другая копия демона.
*/
if (already_running())
{
syslog(LOG_ERR, "Демон уже запущен");
exit(1);
}
/*
* Установить обработчики сигналов.
*/
sa.sa_handler = sigterm;
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGTERM);
sa.sa_flags = 0;
if (sigaction(SIGTERM, &sa, NULL) < 0)
{
syslog(LOG_ERR, "Невозможно перехватить сигнал SIGTERM: %s",
strerror(errno));
exit(1);
}
sa.sa_handler = sighup;
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGHUP);
sa.sa_flags = 0;
if (sigaction(SIGHUP, &sa, NULL) < 0)
{
syslog(LOG_ERR, "Невозможно перехватить сигнал SIGHUP: %s",
strerror(errno));
exit(1);
}
/*
* Остальная часть программы-демона.
*/
/* ... */
exit(0);
}
Для перехода в режим демона программа использует функцию daemonize из листинга 11.1. После возврата из нее вызывается функция already_running из листинга 11.2, которая проверяет наличие других запущенных копий демона. После инициализации демона устанавливаются обработчики сигналов SIGHUP и SIGTERM. У нас есть два варианта обработки сигнала SIGHUP: либо читать конфигурационный файл внутри функции-обработчика, либо просто установить в обработчике специальный флаг, а все необходимые действия выполнять в основном потоке программы.