Системные вызовы

Форк системного вызова Linux

Форк системного вызова Linux

Форк системного вызова

Системный вызов fork используется для создания новых процессов. Вновь созданный процесс является дочерним процессом. Процесс, который вызывает fork и создает новый процесс, является родительским процессом. Дочерний и родительский процессы выполняются одновременно.

Но дочерний и родительский процессы находятся в разных областях памяти. Эти пространства памяти имеют одинаковое содержимое, и любая операция, выполняемая одним процессом, не повлияет на другой процесс.

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

Дочерний процесс точно такой же, как и его родительский, но есть различия в идентификаторах процессов:

  1. Идентификатор дочернего процесса - это уникальный идентификатор процесса, который отличается от идентификаторов всех других существующих процессов.
  2. Идентификатор родительского процесса будет таким же, как и идентификатор родительского процесса дочернего процесса.

Свойства дочернего процесса

Ниже приведены некоторые свойства дочернего процесса:

  1. Счетчики ЦП и использование ресурсов инициализируются для сброса на ноль.
  2. Когда родительский процесс завершается, дочерние процессы не получают никакого сигнала, потому что атрибут PR_SET_PDEATHSIG в prctl () сбрасывается.
  3. Поток, используемый для вызова fork (), создает дочерний процесс. Таким образом, адрес дочернего процесса будет таким же, как и у родительского.
  4. Файловый дескриптор родительского процесса наследуется дочерним процессом. Например, смещение файла или состояние флагов и атрибуты ввода-вывода будут совместно использоваться дескрипторами файлов дочерних и родительских процессов. Таким образом, файловый дескриптор родительского класса будет ссылаться на тот же файловый дескриптор дочернего класса.
  5. Дескрипторы очереди открытых сообщений родительского процесса наследуются дочерним процессом. Например, если файловый дескриптор содержит сообщение в родительском процессе, то же сообщение будет присутствовать в соответствующем файловом дескрипторе дочернего процесса. Таким образом, мы можем сказать, что значения флагов этих файловых дескрипторов одинаковы.
  6. Аналогичным образом потоки открытых каталогов будут унаследованы дочерними процессами.
  7. Значение задержки таймера по умолчанию для дочернего класса такое же, как текущее значение задержки таймера родительского класса.

Свойства, которые не наследуются дочерним процессом

Ниже приведены некоторые свойства, которые не наследуются дочерним процессом:

  1. Блокировки памяти
  2. Ожидающий сигнал дочернего класса пуст.
  3. Блокировка связанной записи (fcntl ())
  4. Асинхронные операции ввода-вывода и содержимое ввода-вывода.
  5. Уведомления об изменении каталога.
  6. Таймеры, такие как alarm (), setitimer (), не наследуются дочерним классом.

fork () в C

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

#включать
#включать
#включать

При работе с fork (), может использоваться для типа pid_t для идентификаторов процессов, как pid_t, определен в .

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

Тип возвращаемого значения определен в и вызов fork () определен в . Следовательно, вам необходимо включить оба в свою программу, чтобы использовать системный вызов fork ().

Синтаксис fork ()

Синтаксис системного вызова fork () в Linux, Ubuntu следующий:

pid_t fork (недействительно);

В синтаксисе возвращаемый тип pid_t. Когда дочерний процесс успешно создан, PID дочернего процесса возвращается в родительском процессе, а 0 будет возвращен самому дочернему процессу.

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

В fork () не передаются аргументы. 

Пример 1: вызов fork ()

Рассмотрим следующий пример, в котором мы использовали системный вызов fork () для создания нового дочернего процесса:

КОД:

#включать
#включать
#включать
int main ()

вилка();
printf ("Использование системного вызова fork () \ n");
возврат 0;

ВЫХОД:

Использование системного вызова fork ()
Использование системного вызова fork ()

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

Поэтому, когда вызов fork () используется один раз, как указано выше (21 = 2) мы получим наш вывод 2 раза.

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

Рассмотрим следующий случай, когда fork () используется 4 раза:

КОД:

#включать
#включать
#включать
int main ()

вилка();
вилка();
вилка();
вилка();
printf ("Использование системного вызова fork ()");
возврат 0;

Выход:

Использование системного вызова fork () Использование системного вызова fork () Использование системного вызова fork () Использование системного вызова fork () Использование системного вызова fork () Использование системного вызова fork () Использование системного вызова fork () Использование системного вызова fork () Использование fork () системный вызов Использование системного вызова fork () Использование системного вызова fork () Использование системного вызова fork () Использование системного вызова fork () Использование системного вызова fork () Использование системного вызова fork () Использование системного вызова fork () 

Теперь общее количество созданных процессов равно 24 = 16, и наш оператор печати выполняется 16 раз.

Пример 2: Проверка успешности fork ()

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

КОД:

#включать
#включать
#включать
int main ()

pid_t p;
р = вилка ();
если (p == - 1)

printf ("Ошибка при вызове fork ()");

если (p == 0)

printf («Мы находимся в дочернем процессе»);

еще

printf («Мы находимся в родительском процессе»);

возврат 0;

ВЫХОД:

Мы находимся в родительском процессе
Мы находимся в дочернем процессе

В приведенном выше примере мы использовали тип pid_t, который будет хранить возвращаемое значение fork (). fork () вызывается в строке:

р = вилка ();

Таким образом, целочисленное значение, возвращаемое fork (), сохраняется в p, а затем p сравнивается, чтобы проверить, был ли наш вызов fork () успешным.

Когда используется вызов fork () и дочерний процесс успешно создан, идентификатор дочернего процесса будет возвращен родительскому процессу, а 0 будет возвращен дочернему процессу.Идентификатор дочернего процесса в родительском процессе не будет совпадать с идентификатором дочернего процесса в самом дочернем процессе. В дочернем процессе идентификатор дочернего процесса будет 0.

Из этого руководства вы узнаете, как начать работу с системным вызовом fork в Linux.

Как разработать игру в Linux
Десять лет назад не многие пользователи Linux могли бы предсказать, что их любимая операционная система однажды станет популярной игровой платформой д...
Порты коммерческих игровых движков с открытым исходным кодом
Бесплатные игры с открытым исходным кодом и кроссплатформенные версии игрового движка можно использовать для игры как в старые, так и в некоторые из с...
Лучшие игры с командной строкой для Linux
Командная строка - не только ваш главный союзник при использовании Linux - она ​​также может быть источником развлечений, потому что вы можете использ...