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

Fork System Call C



Системный вызов fork () используется для создания дочерних процессов в программе C. fork () используется там, где в вашем приложении требуется параллельная обработка. Системная функция fork () определена в заголовках. sys / types.h а также unistd.h . В программе, в которой вы используете fork, вам также необходимо использовать системный вызов wait (). Системный вызов wait () используется для ожидания в родительском процессе завершения дочернего процесса. Для завершения дочернего процесса в дочернем процессе используется системный вызов exit (). Функция wait () определена в заголовке sys / wait.h а функция exit () определена в заголовке stdlib.h .

Рис. 1. Базовый рабочий процесс fork ()

Рис. 1. Базовый рабочий процесс fork ()







В этой статье я покажу вам, как использовать системный вызов fork () для создания дочерних процессов в C. Итак, приступим.



fork () Синтаксис и возвращаемое значение:

Синтаксис системной функции fork () следующий:



вилка pid_t(пустота);

Системная функция fork () не принимает никаких аргументов. Возвращает целое число типа pid_t .





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

Простой fork () Пример:

Ниже приведен простой пример fork ():



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

intглавный(пустота) {
pid_t pidзнак равновилка();

если(пид== 0) {
printf ('Дочерний => PPID:% d PID:% d п',Getppid(),Getpid());
выход (EXIT_SUCCESS);
}
еще если(пид> 0) {
printf ('Родитель => PID:% d п',Getpid());
printf ('Ожидание завершения дочернего процесса. п');
ждать(НУЛЕВОЙ);
printf ('Дочерний процесс завершен. п');
}
еще {
printf ('Невозможно создать дочерний процесс. п');
}

возвращениеEXIT_SUCCESS;
}

Здесь я использовал fork () для создания дочернего процесса из основного / родительского процесса. Затем я распечатал PID (идентификатор процесса) и PPID (идентификатор родительского процесса) из дочернего и родительского процессов. В родительском процессе wait (NULL) используется для ожидания завершения дочернего процесса. В дочернем процессе exit () используется для завершения дочернего процесса. Как видите, PID родительского процесса - это PPID дочернего процесса. Итак, дочерний процесс 24738 принадлежит родительскому процессу 24731 .

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

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

пустотаchildTask() {
printf ('Привет, мир п');
}

пустотаparentTask() {
printf ('Основная задача. п');
}

intглавный(пустота) {
pid_t pidзнак равновилка();

если(пид== 0) {
childTask();
выход (EXIT_SUCCESS);
}
еще если(пид> 0) {
ждать(НУЛЕВОЙ);
parentTask();
}
еще {
printf («Невозможно создать дочерний процесс».);
}

возвращениеEXIT_SUCCESS;
}

Вывод вышеуказанной программы:

Запуск нескольких дочерних процессов с помощью fork () и Loop:

Вы также можете использовать цикл, чтобы создать столько дочерних процессов, сколько вам нужно. В приведенном ниже примере я создал 5 дочерних процессов, используя цикл for. Я также распечатал PID и PPID из дочерних процессов.

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

intглавный(пустота) {
для(intязнак равно 1;я<= 5;я++) {
pid_t pidзнак равновилка();

если(пид== 0) {
printf ('Дочерний процесс => PPID =% d, PID =% d п',Getppid(),Getpid());
выход (0);
}
еще {
printf ('Родительский процесс => PID =% d п',Getpid());
printf ('Ожидание завершения дочерних процессов ... п');
ждать(НУЛЕВОЙ);
printf ('дочерний процесс завершен. п');
}
}

возвращениеEXIT_SUCCESS;
}

Как видите, ID родительского процесса одинаков для всех дочерних процессов. Итак, все они принадлежат одному родителю. Они также работают линейно. Один за другим. Управление дочерними процессами - сложная задача. Если вы узнаете больше о системном программировании Linux и о том, как оно работает, вы сможете управлять потоком этих процессов в любом случае.

Пример из реальной жизни:

Различные сложные математические вычисления, такие как генерация хэшей md5, sha256 и т. Д., Требуют большой вычислительной мощности. Вместо того, чтобы вычислять подобные вещи в том же процессе, что и основная программа, вы можете просто вычислить хэш дочернего процесса и вернуть хеш основному процессу.

В следующем примере я сгенерировал 4-значный PIN-код в дочернем процессе и отправил его родительскому процессу, основной программе. Затем я распечатал оттуда ПИН-код.

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

intgetPIN() {
// использовать PPID и PID в качестве начального числа
srand (Getpid() +Getppid());
intсекретзнак равно 1000 + ряд () % 9000;
возвращениесекрет;
}

intглавный(пустота) {
intfd[2];
трубка(fd);
pid_t pidзнак равновилка();

если(пид> 0) {
близко(0);
близко(fd[1]);
после(fd[0]);

intсекретное число;
size_treadBytesзнак равночитать(fd[0], &секретное число, размер(секретное число));

printf ('Ожидание PIN-кода ... п');
ждать(НУЛЕВОЙ);
printf ('Прочитано байтов:% ld п',readBytes);
printf (PIN-код:% d п',секретное число);
}
еще если(пид== 0) {
близко(1);
близко(fd[0]);
после(fd[1]);

intсекретзнак равноgetPIN();
записывать(fd[1], &секрет, размер(секрет));
выход (EXIT_SUCCESS);
}

возвращениеEXIT_SUCCESS;
}

Как видите, каждый раз, когда я запускаю программу, я получаю другой 4-значный PIN-код.

Итак, вот как вы в основном используете системный вызов fork () в Linux. Спасибо, что прочитали эту статью.