Coding — Механизм создания процессов в Linux
Создать процесс в системе можно несколькими способами, здесь я опишу как происходит создание процесса начиная с функции fork():
fork() создает дочерний процесс, который является практически точной копией родительского процесса. Одним из различий являются значения PID и PPID.
fork() при успешном вызове возвращает два значения, одно в родительский — PID созданного потомка, а второе в дочерний — 0. Если же вызов оказался неудачным, то родителю возвращается -1, потомок не создается, а в errno устанавливается код ошибки.
Возвращаемое значение имеет тип pid_t, хотя на самом деле это обычное целое (int). Это можно проследить в коде ядра:
Приведем простой пример использования функции fork():
Функция fork(), в свою очередь, вызывает системный вызов sys_clone(). В этом можно убедиться, если выполнить трассировку программы с помощью команды strace или ltrace:
Системный вызов sys_clone (определен в файле arch/x86/kernel/process_XX.c), о котором можно прочитать на страницах справочного руководства man, является архитектурно-зависимым, вот его прототип (прототипы приводятся только для архитектуры x86):
В любом случае sys_clone ссылается на архитектурно-независимую функцию do_fork():
Функция do_fork(), как уже было сказано, является архитектурно-независимой функцией и несет ответственность за процесс дублирования. Она определена в файле kernel/fork.c, вот ее прототип:
do_fork() в свою очередь вызывает функцию copy_process(), которая выполняет фактическую работу по созданию нового процесса и повторному использованию данных родительского процесса. Ее вызов происходит следующим образом:
В итоге выстраивается следующая схема:
vfork() ->
fork () -> sys_clone() -> do_fork() -> copy_process()
clone() ->
Хочу сказать, что статью считать "от и до" своей я не могу, это своего рода "компиляция" различных статей с моими доработками.
P.S. Вот выложил pdf (и тут) с этим же текстом, плюс в нем приводится полный код функций do_fork() и copy_process() с небольшими комментариями.
P.P.S. И да, это первый пост.
1 2 3 |
#include <sys/types.h> |
fork() создает дочерний процесс, который является практически точной копией родительского процесса. Одним из различий являются значения PID и PPID.
fork() при успешном вызове возвращает два значения, одно в родительский — PID созданного потомка, а второе в дочерний — 0. Если же вызов оказался неудачным, то родителю возвращается -1, потомок не создается, а в errno устанавливается код ошибки.
Возвращаемое значение имеет тип pid_t, хотя на самом деле это обычное целое (int). Это можно проследить в коде ядра:
1 2 3 4 |
#define pid_t __pid_t (<sys/types.h>) |
Приведем простой пример использования функции fork():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
/* fork_ex.c --- простой пример использования fork() */ |
Функция fork(), в свою очередь, вызывает системный вызов sys_clone(). В этом можно убедиться, если выполнить трассировку программы с помощью команды strace или ltrace:
1 2 3 4 5 6 7 8 9 |
$ strace ./fork_ex |
Системный вызов sys_clone (определен в файле arch/x86/kernel/process_XX.c), о котором можно прочитать на страницах справочного руководства man, является архитектурно-зависимым, вот его прототип (прототипы приводятся только для архитектуры x86):
1 2 3 4 5 6 7 8 |
/*** arch/x86/kernel/process_32.c ***/ |
В любом случае sys_clone ссылается на архитектурно-независимую функцию do_fork():
1 2 3 |
... |
Функция do_fork(), как уже было сказано, является архитектурно-независимой функцией и несет ответственность за процесс дублирования. Она определена в файле kernel/fork.c, вот ее прототип:
1 2 3 4 5 6 |
long do_fork(unsigned long clone_flags, |
do_fork() в свою очередь вызывает функцию copy_process(), которая выполняет фактическую работу по созданию нового процесса и повторному использованию данных родительского процесса. Ее вызов происходит следующим образом:
1 2 3 4 |
... |
В итоге выстраивается следующая схема:
vfork() ->
fork () -> sys_clone() -> do_fork() -> copy_process()
clone() ->
Хочу сказать, что статью считать "от и до" своей я не могу, это своего рода "компиляция" различных статей с моими доработками.
P.S. Вот выложил pdf (и тут) с этим же текстом, плюс в нем приводится полный код функций do_fork() и copy_process() с небольшими комментариями.
P.P.S. И да, это первый пост.