Linux – PID 0 ( swapper)
Начиная изучать внутреннее устройство ОС, мы должны понимать, какие процессы выполняются по умолчанию (роли, задачи и т.д.). В связи с этим я собираюсь начать серию постов под названием “Идентификационная карта процессов” (цель – предоставить словарь ОС). На основании проведенного мной опроса я собираюсь начать с Linux (Windows последует за ним).
Чтобы составить список процессов, о которых я хочу рассказать, я установил чистую виртуальную машину Ubuntu 22.04 (настольная версия) и выполнил команду ps. Вероятно, лучший способ сделать это – просмотреть процессы в порядке возрастания их PID.
Сначала я хочу поговорить о том, кого мы не обнаружили в списке, это PID 0 (мы видим, что он является PPID для PID 1 и PID 2 – о них в следующих постах). Итак, давайте погрузимся в подробности о PID 0, он же swapper (но также он имеет названия sched и idle, основанные на различных ролях, которые он выполнял в течение многих лет). Во-первых, это не обычный процесс пользовательского режима, а часть ядра (о потоках ядра мы поговорим в следующих заметках).
Исторически сложилось так, что старые Unix-системы использовали своппинг, а не подкачку по требованию. Таким образом, swapper отвечал за “процесс свопинга” – перемещение всех страниц определенного процесса из/в память/в резервное хранилище (включая структуры данных ядра связанного процесса). В случае Linux PID 0 использовался как ” idle process”, просто ничего не делающий (как nops). Он был создан для того, чтобы в Linux всегда было что-то, что процессор может выполнить (для случаев, когда процессор не может быть остановлен для экономии энергии). Кстати, системный вызов idle не поддерживается с версии ядра 2.3.13 (более подробную информацию можно найти в “man 2 idle”). Итак, каково же текущее назначение swapper сегодня? Помощь в pageout? Очистка кэша? Простой? Обнуление буфера? Я обещаю, что мы ответим на этот вопрос более подробно, пока будем разбираться с другими процессами и объяснять взаимосвязь между ними.
Но как вы можете поверить, что swapper (PID 0) вообще существует, если вы не можете увидеть его с помощью ps. Я собираюсь использовать “bpftrace” для демонстрации этого (если вы не знаете о bpftrace, я настоятельно рекомендую вам прочитать о нем). В демонстрации я собираюсь отследить функцию ядра “hrtimer_wakeup”, которая отвечает за пробуждение процесса и перемещение его в набор запускаемых процессов. Во время трассировки я собираюсь вывести pid вызывающего процесса (BTW, в ядре все называется задачей – подробнее об этом в следующих постах) и имя исполняемого процесса (поле comm структуры task_struct [/include/linux/sched.h]). Вот команда:
sudo bpftrace -e ‘kfunc:hrtimer_wakeup { printf(“%s:%d\n”,curtask->comm,curtask->pid); }’
Из вывода видно, что у нас есть 3 экземпляра swapper: swapper/0, swapper/1 и swapper/2, все они имеют PID 0. Причина наличия трех экземпляров заключается в том, что моя виртуальная машина имеет 3 виртуальных процессора, и для каждого из них существует процесс swapper – см. вывод команды на рисунке ниже.
Увидимся на PID 1