Страницы

Поиск по вопросам

понедельник, 23 декабря 2019 г.

Недопонимание с Linux на примере демона.

#linux #c #процесс #демон


Чтобы создать демона (по крайней мере в Linux), то нужно предпринять ряд событий,
которые я сейчас опишу. В конце вопросы, если кто-то разбирается, то просьба овтетить,
буду признателен.

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

if( (pid = fork()) < 0)
         return -1;
else if(pid)
         exit(0);


2) Затем мы вызываем функцию setsid(), которая создает новый сеанс. К тому же, вызывающий
процесс становится ведущим в группе, ведущим процессом нового сеанса и не имеет контролирующего
терминала.

if(setsid() < 0) 
        return -1;


В книге "Разработка сетевых приложений" Стивенс У.Р, откуда я и беру этот пример,
автор вызывает еще один раз функцию fork(), для того, чтобы гарантировать, что демон
не сможет автоматически получить управляющий терминал, когда будет открывать устройство
терминала. Заметьте, что при завершении родительского процесса (в нашем случае первого
дочернего процесса), посылается всем процессам в сеансе (в том числе и нашему второму
дочернему процессу) сигнал SIGHUP (when someone kills the terminal, without killing
app running inside of termiтal window, OS sends the signal to the program), который
нам нужно игнорировать. 

3) Производим смену текущего каталога командой chdir("/");

4) Закрываем дескрипторы файлов. Автор делает это таким образом

for(i = 0; i < 64; i++) 
        close(i);


И дальше больше... Остальной код приводить не буду, так как он не относится к сути
вопросов, но в интеренете есть книга, которую я указал ранее, где вы можете найти пример
полностью. 

Собственно говоря, мои вопросы:

1) Вопрос может показаться глупым, но я не совсем понимаю, что означает управляющий
терминал. Это что-то вроде терминала из под root? Объясните, пожалуйста, что это и
что он делает.

2) Зачем нужно менять текущий каталог? В книге об этом сказано мало и мне не совсем
понятно

3) За что отвечают дескрипторы, которые мы закрываем? И нужно ли их вообще закрывать? 
    


Ответы

Ответ 1



Вопрос может показаться глупым, но я не совсем понимаю, что означает управляющий терминал. Это что-то вроде терминала из под root? Объясните, пожалуйста, что это и что он делает. Если кратко, то это терминал связанный с текущей консольным сеансом (session). Указан в частности в столбце TTY ps'а. По факту он эквивалентен одному из устройств /dev/tty* для «настоящей» консоли или /dev/pts* для псевдотерминалов (unix98). Также есть специальное устройство /dev/tty, ссылающееся на управляющий терминал (controlling terminal) текущего процесса. Основное назначение этой абстракции — переключение между группами процессов — только одна из которых может быть на переднем плане (foreground), а остальные в фоне (background). Также УТ (находясь в каноническом режиме) отвечает за посылку сигналов процессам находящимся на переднем плане при появлении на входе специальных символов (например ^C или ^Z) . Кроме того с помощью УТ программы могут запрашивать непосредственно у пользователя какие-то данные, например пароль, когда ввод/вывод перенаправлен, так в частности поступают ssh или sudo. Вообще говоря, в UNIX управление заданиями, да и всей подсистемы связанной с терминалами, — довольно запутанная вещь со множеством мелких и крупных кочек, большинство из которых навеяно историей и необходимостью сделать всё гибко, но в то же время чисто, так что описание назначения и деталей УТ, а также таких абстракций, как «группа процессов», «сессия», «лидер сессии» итд, заслуживают отдельной главы в книге или хотя бы статьи. 2) Зачем нужно менять текущий каталог? В книге об этом сказано мало и мне не совсем понятно В принципе это не обязательно, но является хорошей практикой освобождать неиспользуемые ресурсы. Например, если это не сделать, то нельзя будет отмонтировать ФС с каталогом откуда пользователь запустил демона. 3) За что отвечают дескрипторы, которые мы закрываем? И нужно ли их вообще закрывать? То же что и предыдущее, не обязательно, но обычно является хорошей практикой. Первые три — это стандартные потоки ввода/вывода/ошибок, а остальные — другие дескрипторы, которые могут быть открыты — различные сокеты, файлы итп. К сожалению, в POSIX нет простого и переносимого способа, который позволяет просто «закрыть все открытые дескрипторы» или хотя бы «запросить все открытые д.», поэтому обычной практикой является перебирать их все подряд, от нулевого до последнего и закрывать. Да, более переносимым вариантом, не полагающийся на магическую константу «64», будет: for(int fd=0, maxfd=sysconf(_SC_OPEN_MAX); fd

Комментариев нет:

Отправить комментарий