Лабораторная 1. Демоны - chrislvt/OS GitHub Wiki

Daemon

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

Daemon - это долгоживущий процесс, который работает в background.

Где их найти?

Раз такой смелый, то можно к примеру здесь ps -axj если вертишься под BSD.

  • a - процессы других пользователей;
  • x - процессы, которые не имеют управляющего терминала (те самые демоны);
  • j - дополнительная информация.

States

  • S - interruptible process;
  • s - session leader;
  • l - multithreaded process;
  • TTY = ?? => нет управляющего терминала;

Классификация демонов

Kernel Daemons

  • ppid = 0 + некоторая специфика реализации системы;
  • Daemons init (Linux), launchd (OS X) не являются Kernel Daemons хотя ppid = 0. Являются user-level command запускаемые ядром;
  • superuser privileges;
  • нет управляющего терминала;
  • Linux:
    • Kernell Daemon который является для всех остальных Kernell Daemon родителем - [kthreadd] - pid = 2.

В Linux, ps выводит имена kernel daemons заключенные в квадратные кавычки.

User-level Daemons

  • ppid = 1;
  • process group leader;
  • session leaders;
  • как правило единственные в process group and session.

Как правило процесс у которого pid = 1 является daemom init (Linux) или launchd (OS X). Это системный демон, который отвечает за запуск системных служб для различного уровня выполнения. Эти службы реализуются с помощью их собственных демонов.

Coding Rules by Rago

  1. Вызвать umask(), что бы установить необходимую маску создания новых файлов (обычно просто сбрасывают в 0).
  2. Вызвать fork(), a для процесса предка выполнить exit(). На это есть следующие причины:
    1. Если daemon был запущен через shell, завершаем бесполезный процесс parent.
    2. Гарантируем что Child не будет process group leader.
    3. Примечание: При защите данной лабораторной, лулзы отхватываются здесь на изи, поэтому лучше 1 подпункт вообще не говорить. Во 2 подпункте сказать, что будет лидером группы, хотя если бы так было, мы бы словили лулзы от setsid() (man setsid()). Реальная цель подпунктов: избавиться от управляющего терминала и сделать бла бла с помощью корректного вызова setsid(), но кого это волнует...
  3. Вызвать setsid(), чтобы создать новую session. Таким образом процесс:
    1. Становится лидером новой session.
    2. Становится лидером новой process group.
    3. Лишается управляющего терминала.
  4. Изменить текущую рабочею директорию (к примеру на /). Причина в том, что от parent наследуется текущая рабочая директория, которая может оказаться mounted. Пока daemon работает на mounted FS, unmount сделать не получится.
  5. Закрыть неиспользуемые файловые дескрипторы. Иначе daemon будет препятствовать их закрытию.
  6. Некоторые daemons открывают файловые дескрипторы 0 (stdin), 1 (stdout), 2 (stderr) в /dev/null таким образом, не будет возникать ошибок при работе библиотечных функций, которые взаимодействуют с stdin, stdout, stderr.

Quest

  1. Собрать демона;
  2. Запустить демона (sudo в помощь);
  3. Вывести то, что делает демон. К примеру: tail -f "Log.txt";
  4. ps -axj;
  5. Рассказать о state;
  6. Ответить почему TTY = ??;
  7. Открыть daemonize.cpp и рассказать по коду, как работает daemonize(). Либо вы шустро говорите, что бы не успели переварить ваши слова, либо говорите мало, но стараетесь выудить наводящие вопросы. Желательно отвечать без использования оборотов, как робот. Можно всё объяснять в виде 0 и 1, либо на ментальном уровне;
  8. Повторять пункт 7, 7 и ещё раз 7 до тех пор пока не постигните дзен;
  9. Верить в силу 777 и получить заветное зачтено.

Top Questions

  • Зачем отнимать управляющий терминал (TTY). Пример
    • Чтобы user не смог взаимодействовать с daemon. К примеру не смог послать сигнал SIG_INT с помощью Ctrl + C тем самым остановив работу daemon.
  • Зачем закрывать файловые дескрипторы?
    • Можно попробовать так. Так как они daemon'у не нужны, то мы их закрываем. Если глубже то, так как daemon был запущен через shell мы унаследовали stdin, stdout, stderr, а поскольку daemon'у они не нужны, то мы их закрываем (всё равно у daemon'a нет терминала и что бы не было потенциальной угрозы). В общем, чтобы не было контакта с юзером. Без понятия, что от вас захотят услышать, но всё будет сводиться к этому.
  • Зачем мы подключили файловые дескрипторы 0, 1, 2?
    • Чтобы не было ошибок, если демон будет использовать функции работающие с stdin, stdout, stderr
  • Покажите PID процесса в lock-файле
    • shell:

$ cd /var/run $ cat daemon.pid ```

  • Покажите место в коде, где процесс становится демоном
    • in main.c function daemonize()