Меню Рубрики

Linux как работает fork

Linux как работает fork

Для порождения процессов в ОС Linux существует два способа. Один из них позволяет полностью заменить другой процесс, без замены среды выполнения. Другим способом можно создать новый процесс с помощью системного вызова fork() . Синтаксис вызова следующий:

pid_t является примитивным типом данных, который определяет идентификатор процесса или группы процессов. При вызове fork() порождается новый процесс (процесс-потомок), который почти идентичен порождающему процессу-родителю. Процесс-потомок наследует следующие признаки родителя:

  • сегменты кода, данных и стека программы;
  • таблицу файлов, в которой находятся состояния флагов дескрипторов файла, указывающие, читается ли файл или пишется. Кроме того, в таблице файлов содержится текущая позиция указателя записи-чтения;
  • рабочий и корневой каталоги;
  • реальный и эффективный номер пользователя и номер группы;
  • приоритеты процесса (администратор может изменить их через nice );
  • контрольный терминал;
  • маску сигналов;
  • ограничения по ресурсам;
  • сведения о среде выполнения;
  • разделяемые сегменты памяти.

Потомок не наследует от родителя следующих признаков:

  • идентификатора процесса (PID, PPID);
  • израсходованного времени ЦП (оно обнуляется);
  • сигналов процесса-родителя, требующих ответа;
  • блокированных файлов (record locking).

При вызове fork() возникают два полностью идентичных процесса. Весь код после fork() выполняется дважды, как в процессе-потомке, так и в процессе-родителе.

Процесс-потомок и процесс-родитель получают разные коды возврата после вызова fork() . Процесс-родитель получает идентификатор (PID) потомка. Если это значение будет отрицательным, следовательно при порождении процесса произошла ошибка. Процесс-потомок получает в качестве кода возврата значение 0, если вызов fork() оказался успешным.

Таким образом, можно проверить, был ли создан новый процесс:

Пример порождения процесса через fork() приведен ниже:

Когда потомок вызывает exit() , код возврата передается родителю, который ожидает его, вызывая wait() . WEXITSTATUS() представляет собой макрос, который получает фактический код возврата потомка из вызова wait() .

Функция wait() ждет завершения первого из всех возможных потомков родительского процесса. Иногда необходимо точно определить, какой из потомков должен завершиться. Для этого используется вызов waitpid() с соответствующим PID потомка в качестве аргумента. Еще один момент, на который следует обратить внимание при анализе примера, это то, что и родитель, и потомок используют переменную rv . Это не означает, что переменная разделена между процессами. Каждый процесс содержит собственные копии всех переменных.

Рассмотрим следующий пример:

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

Так называемые процессы-зомби возникают, если потомок завершился, а родительский процесс не вызвал wait() . Для завершения процессов используют либо оператор возврата, либо вызов функции exit() со значением, которое нужно возвратить операционной системе. Операционная система оставляет процесс зарегистрированным в своей внутренней таблице данных, пока родительский процесс не получит кода возврата потомка, либо не закончится сам. В случае процесса-зомби его код возврата не передается родителю, и запись об этом процессе не удаляется из таблицы процессов операционной системы. При дальнейшей работе и появлении новых зомби таблица процессов может быть заполнена, что приведет к невозможности создания новых процессов.

Источник

Как работает функция fork() в C. Не могу понять результат работы программы

У меня есть вот такой короткий пример кода, нам его дали что бы продемонстрировать работу функции fork():

Мне не совсем понятен результат. В итоге у меня 4 раза в терминале пишет Fork-Test Не понимаю, во-первых почему это происходит больше одного раза, ведь я вызваю метод printf(«Fork-Test\n»); только один раз, во-вторых, раз уже несколько раз, то почему именно 4? При чем еще и в следующем виде:

смысл мне не понятен. буду благодарна за любые пояснения по поводу fork()

2 ответа 2

Процесс после системного вызова fork , раздваивается, у исходного процесса создаётся идентичный потомок-двойник в идентичном состоянии (ну почти). Создавшийся процесс будет занят выполнением того же кода ровно с той же точки, что и исходный процесс.

Различить кто создал, а кто создался, можно по возвращаемому значению fork , поэтому его результат обычно передаётся в if , чтобы эти процессы выполнили какие-то разные вещи, один пошёл в ветку if , другой в ветку else .

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

После второго форка процессов уже 4. И после этих форков каждый процесс доходит до вызова printf и выводит указанную строку. Каждый процесс делает это сам. Поэтому вывод происходит столько раз, сколько вышло процессов.

Можете убедиться в этом, поместив вывод перед вторым форком (вывод произойдёт дважды) или перед первым (единожды).

Завершаются они независимо друг от друга.
У вас получилось, что процесс P завершился вторым. А нечто, через что вы запускали этот процесс, следило только за процессом P , но не его «клонами» (т. к. у них собственные pid , process ID), поэтому для остальных такого вывода нет.

Источник

9.1.1. Создание процесса: fork()

9.1.1. Создание процесса: fork()

Первым шагом в запуске новой программы является вызов fork() :

Использование fork() просто. Перед вызовом один процесс, который мы называем родительским, является запущенным. Когда fork() возвращается, имеется уже два процесса: родительский и порожденный (child).

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

Если была ошибка, fork() возвращает -1, а новый процесс не создается. Работу продолжает первоначальный процесс.

В порожденном процессе fork() возвращает 0.

В родительском процессе fork() возвращает положительный идентификационный номер (PID) порожденного процесса.

Код шаблона для создания порожденного процесса выглядит следующим образом:

/* это первоначальный родительский процесс */

pid_t является знаковым целым типом для хранения значений PID. Скорее всего, это просто int , но специальный тип делает код более понятным, поэтому он должен использоваться вместо int .

На языке Unix, помимо названия системного вызова, слово «fork» является и глаголом, и существительным[88]. Мы можем сказать, что «один процесс ответвляет другой», и что «после разветвления работают два процесса». (Думайте «развилка (fork) на дороге», а не «вилка (fork), нож и ложка».)

Похожие главы из других книг:

9.1.1.1. После fork() : общие и различные атрибуты

9.1.1.1. После fork(): общие и различные атрибуты Порожденный процесс «наследует» идентичные копии большого числа атрибутов от родителя. Многие из этих атрибутов специализированы и здесь неуместны. Поэтому следующий список намеренно неполон. Существенны

10.9. Сигналы, передающиеся через fork() и exec()

10.9. Сигналы, передающиеся через fork() и exec() Когда программа вызывает fork(), ситуация с сигналами в порожденном процессе почти идентична ситуации в родительском процессе. Установленные обработчики остаются на месте, заблокированные сигналы остаются заблокированными и т.д.

Создание процесса

Создание процесса Одной из важнейших функций Windows, обеспечивающих управление процессами, является функция CreateProcess, которая создает новый процесс с единственным потоком. При вызове этой функции требуется указать имя файла исполняемой программы.Обычно принято говорить о

Создание нового процесса

Создание нового процесса В операционной системе Unix создание процессов происходит уникальным образом. В большинстве операционных систем для создания процессов используется метод порождения процессов (spawn). При этом создается новый процесс в новом адресном пространстве,

Создание нового процесса

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

Создание процесса

Создание процесса Как уже обсуждалось, в UNIX проведена четкая грань между программой и процессом. Каждый процесс в конкретный момент времени выполняет инструкции некоторой программы, которая может быть одной и той же для нескольких процессов.[39] Примером может служить

4.7. Функции fork и exec

4.7. Функции fork и exec Прежде чем рассматривать создание параллельного сервера (что мы сделаем в следующем разделе), необходимо описать функцию Unix fork. Эта функция является единственным способом создания нового процесса в Unix.#include pid_t fork(void);Возвращает: 0 в дочернем

7.1 СОЗДАНИЕ ПРОЦЕССА

7.1 СОЗДАНИЕ ПРОЦЕССА Единственным способом создания пользователем нового процесса в операционной системе UNIX является выполнение системной функции fork. Процесс, вызывающий функцию fork, называется родительским (процесс-родитель), вновь создаваемый процесс называется

9.1.2.1 Выгрузка при выполнении системной функции fork

9.1.2.1 Выгрузка при выполнении системной функции fork В описании системной функции fork (раздел 7.1) предполагалось, что процесс-родитель получил в свое распоряжение память, достаточную для создания контекста потомка. Если это условие не выполняется, ядро выгружает процесс из

9.2.1.1 Функция fork в системе с замещением страниц

9.2.1.1 Функция fork в системе с замещением страниц Как уже говорилось в разделе 7.1, во время выполнения функции fork ядро создает копию каждой области родительского процесса и присоединяет ее к процессу-потомку. В системе с замещением страниц ядро по традиции создает

5.1. Системные вызовы fork() и ехес()

5.1. Системные вызовы fork() и ехес() Процесс в Linux (как и в UNIX) — это программа, которая выполняется в отдельном виртуальном адресном пространстве. Когда пользователь регистрируется в системе, под него автоматически создается процесс, в котором выполняется оболочка (shell),

Создание, завершение и просмотр учетной записи процесса

Создание, завершение и просмотр учетной записи процесса К другим основным возможностям инструментария управления WMI относятся возможности работы с процессами, запущенными на удаленном или локальном компьютере. При этом инструментарий предоставляет возможности не

1.5. Действие команд fork, exec и exit на объекты IPC

1.5. Действие команд fork, exec и exit на объекты IPC Нам нужно достичь понимания действия функций fork, exec и _exit на различные формы IPC, которые мы обсуждаем (последняя из перечисленных функций вызывается функцией exit). Информация по этому вопросу сведена в табл. 1.4.Большинство функций

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

  • Все названия mac os
  • Все версии skype для mac os
  • Все версии mac os по порядку
  • Время установки mac os sierra
  • Время загрузки mac os