Многозадачность в Linux. Язык программирования C. Статья 2 (функция fork)

31 October 2020
133 full reads
1,5 min.
303 story viewsUnique page visitors
133 read the story to the endThat's 44% of the total page views
1,5 minute — average reading time

Здесь весь мой канал Old Programmer. Здесь: Программирование. Тематическое оглавление моего Zen-канала (Old Programmer). А здесь собраны все ссылки по C и C++. А здесь перечень ссылок на ресурсы, посвященные многозадачности.

Сегодня продолжаем многозадачную тему. Будем рассматривать функцию fork(). Начало темы здесь.

О системной функции fork()

В линуксовой многозадачности fork(), пожалуй, тема самая сложная. Во всяком случае, сразу это в голове не укладывается. Но я придерживаюсь очень простого принципа. Для использования какой либо технологии не обязательно понимать все о ней. Практика постепенно приведет вас к этому пониманию.

Функция fork() создает копию данного процесса. Эта копия называется дочерним процессом. Дочерний процесс получает в свое распоряжение практически все от родительского. Это очень важный вопрос (что все таки он получает, а что нет), но я пока не буду на этом останавливаться. Для простых программ, это пока не важно. Код дочернего процесса, как и код родительского, продолжают выполняться с инструкции, следующей после вызова функции fork(). В результате действительно fork() это вилка.

Пример использования функции fork() в Linux

Рассмотрим программу multi1010.c. Компилируется она обычным образом:

gcc multi1010.c

Интерпретация выполнения этой программы как раз позволяет нам понимать, как работает функция fork(). Суть ситуации заключается в том, что в родительском процессе переменная t получает значение, равное идентификатору дочернего процесса, а в дочернем процессе переменная t равна нулю. Вот это и позволяет в коде "определять" поведение дочернего и родительского процессов. Условной конструкцией if(!t) мы и разделяем обработку для родительского и дочернего процессов.

Ну и, наконец, две функции getpid() - получить идентификатор текущего процесса, getppid() - получить идентификатор родительского процесса. Соответственно, идентификатор getpid() в родительском процессе, совпадает с идентификатором getppid() в дочернем процессе. Ну а значение getpid() в дочернем процессе совпадет со значением переменной t в родительском. Такие дела.

Результат выполнения программы:

До 89
После 89
Родительский 16773
Дочерний 16774
После 89
Дочерний 16774
Родительский 16773

Объясните ка, почему строка 'До 89' появляется в листинге один раз, а строка 'После 89' дважды.

При использовании функции fork необходимо отслеживать дочерние процессы. Когда дочерний процесс завершается, связь его с родителем сохраняется, пока родительский процесс не завершится или не вызовет функцию wait. Т.е. дочерний процесс остается в системе, являясь "зомби" - процессом.

Следующая статья о многозадачности здесь.

Многозадачность это когда у тебя ребенок на одной руке, телефонная трубка в другой, а ты при этом переворачиваешь блины на сковороде, одновременно крася ногти. Обычный день женщины.

Подписываемся на мой канал Old Programmer.

Фрагмент программы multi1010.c
Фрагмент программы multi1010.c
Фрагмент программы multi1010.c