Процессы – действующее начало. В общем случае с процессом связаны код и данные в виртуальной оперативной памяти, отображение виртуальной памяти на физическую, состояние процессора (регистры, текущая исполняемая инструкция и т.п.). Кроме того в Unix с процессом связана информация о приоритете (в том числе понижающий коэффициент nice
), информация об открытых файлах и обработчиках сигналов. Программа, выполняемая внутри процесса, может меняться в течение его существования.
Новые процессы создаются вызовом int pid=fork()
, который создаёт точную копию вызвавшего его процесса. Пара процессов называются "родительский" и "дочерний" и отличаются друг от друга тремя значениями:
fork()
. В родительском это PID дочернего процесса или ошибка (-1), в дочернем fork()
всегда возвращает 0.После создания, дочерний процесс может загрузить в свою память новую программу (код и данные) из исполняемого файла вызовом execve(const char *filename, char *const argv [], char *const envp[]);
Дочерний процесс связан с родительским значением PPID. В случае завершения родительского процесса PPID меняется на особое значение 1 - PID процесса init.
В момент загрузки ядра создаётся особый процесс с PID=1, который должен существовать до перезагрузки ОС. Все остальные процессы в системе являются его дочерними процессами (или дочерними от дочерних и т.д.). Обычно, в первом процессе исполняется программа init поэтому в дальнейшем я буду называть его "процесс init".
В Linux процесс init защищен от вмешательства других процессов. К нему нельзя подключиться отладчиком, к его памяти нельзя получить доступ через интерфейс procfs, ему не доставляются сигналы, приводящие к завершению процесса. kill -KILL 1
- не сработает. Если же процесс init всё таки завершится, то ядро также завершает работу с соответствующим сообщением.
В современных дистрибутивах классическая программа init заменена на systemd, но сущности процесса с PID=1 это не меняет.
При загрузке Linux ядро сначала монтирует корневую файловую систему на образ диска в оперативной памяти - initrd, затем создаётся процесс с PID=1 и загружает в него программу из файла /init. В initrd из дистрибутива CentOS начальный /init - это скрипт для /bin/bash. Скрипт загружает необходимые драйверы, после чего делает две вещи, необходимые для полноценного запуска Linux:
Для того, чтобы выполнить эти два пункта через загрузчик в начального init два параметра:
Если второй параметр опущен то ищется имя зашитое в начальный init по умолчанию.
Если вы загрузите вместо init /bin/bash, как в моём примере, то сможете завершить первый и единственный процесс командой exit и пронаблюдать сообщение:
Kernel panic - not syncing: Attempted to kill init!
Этот пример так же показывает, как получить права администратора при физическом доступе к компьютеру.
Каждый процесс имеет уникальный на данный момент времени идентификатор PID. Поменять PID процесса невозможно.
Значения PID 0 и 1 зарезервированы. Процесс с PID==0 не используется, PID==1 - принадлежит программе init
.
Максимальное значение PID в Linux равняется PID_MAX-1. Текущее значение PID_MAX можно посмотреть командой:
cat /proc/sys/kernel/pid_max
По умолчанию это 2^16 (32768) однако в 64-разрядных Linux его можно увеличить до 2^22 (4194304):
echo 4194303 > /proc/sys/kernel/pid_max
*PID*
назначаются последовательно. При создании нового процесса вызовом fork
ищется *PID*
, больший по значению, чем тот, который был возвращён предыдущим вызовом fork
. Если при поиске достигнуто значение pid_max
, то поиск продолжается с PID=2. Такое поведение выбрано потому, что некоторые программы могут проверять завершение процесса по существованию его PID. В этой ситуации желательно, чтобы PID не использовался некоторое время после завершения процесса.
С процессом связано понятие "владельца" и "группы", определяющие права доступа процесса к другим процессам и файлам в файловой системе. "Владелец" и "группа", это числовые идентификатор UID и GID, являющийся атрибутами процесса. В отличие от файла, процесс может принадлежать нескольким группам одновременно. Пользователь в диалоговом сеансе имеет право на доступ к своим файлам поскольку диалоговая программа (shell), которую он использует, выполняется в процессе с тем же UIDом, что и UID, указанный в атрибутах файлов.
Процесс может поменять своего владельца и группу в двух случаях:
setuid(newuid)
. В этом случае процесс полностью меняет владельца.exec(file)
загрузив в свою память программу из файла в атрибутах которого выставлен флаг suid или sgid. В этом случае владелец процесса сохраняется, но права доступа будут вычисляться на основе UID и GID файла.Прикрепленный файл | Размер |
---|---|
fork-exex-wait.png | 25.8 КБ |