Книга: Основы программирования в Linux
Дублирование образа процесса
Дублирование образа процесса
Для применения процессов, выполняющих несколько функций одновременно, можно либо использовать потоки, обсуждаемые в главе 12, либо создавать в программе полностью отдельный процесс, как делает init
, вместо замещения текущего потока исполнения, как в случае применения функции exec
.
Создать новый процесс можно с помощью вызова fork
. Системный вызов дублирует текущий процесс, создавая новый элемент в таблице процессов с множеством атрибутов, таких же как у текущего процесса. Новый процесс почти идентичен исходному, выполняет тот же программный код, но в своем пространстве данных, окружении и со своими файловыми дескрипторами. В комбинации с функциями exec
вызов fork
— все, что вам нужно для создания новых процессов.
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
Как видно из рис. 11.2, вызов fork
возвращает в родительский процесс PID нового дочернего процесса. Новый процесс продолжает выполнение так же, как и исходный, за исключением того, что в дочерний процесс вызов fork
возвращает 0. Это позволяет родительскому и дочернему процессам определить, "кто есть кто".
Рис. 11.2
Если вызов fork
завершается аварийно, он возвращает -1. Обычно это происходит из-за ограничения числа дочерних процессов, которые может иметь родительский процесс (CHILD_MAX
), в этом случае переменной errno
будет присвоено значение EAGAIN
. Если для элемента таблицы процессов недостаточно места или не хватает виртуальной памяти, переменная errno
получит значение ENOMEM
.
Далее приведен фрагмент типичного программного кода, использующего вызов fork
:
pid_t new_pid;
new_pid = fork();
switch(new_pid) {
case -1:
/* Ошибка */
break;
case 0:
/* Мы — дочерний процесс */
break;
default:
/* Мы — родительский процесс */
break;
}
Выполните упражнение 11.3.
Упражнение 11.3. Системный вызов fork
Давайте рассмотрим простой пример fork1.с:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
pid_t pid;
char* message;
int n;
printf("fork program startingn");
pid = fork();
switch(pid) {
case -1:
perror("fork failed");
exit(1);
case 0:
message = "This is the child";
n = 5;
break;
default:
message = "This is the parent";
n = 3;
break;
}
for (; n > 0; n--) {
puts(message);
sleep(1);
}
exit(0);
}
Эта программа выполняет два процесса. Дочерний процесс создается и выводит пять раз сообщение. Исходный процесс (родитель) выводит сообщение только три раза. Родительский процесс завершается до того, как дочерний процесс выведет все свои сообщения, поэтому в вывод попадает очередное приглашение командной оболочки.
$ ./fork1
fork program starting
This is the child
This is the parent
This is the parent
This is the child
This is the parent
This is the child
$ This is the child
This is the child
Как это работает
Когда вызывается fork
, эта программа делится на два отдельных процесса. Родительский процесс идентифицируется ненулевым возвращаемым из fork
значением и используется для задания количества сообщений, выводимых с интервалом в одну секунду.
- Как возникает дублирование?
- Сущность процесса миграции
- V Совершенствование процесса
- Использование сервера Yaffil внутри процесса
- 4. Стадии бизнес-процесса взаимодействия с клиентами
- 2.2.2.2 Состояния процесса
- 1.2 Процесс, контекст процесса и потоки
- Вытеснение процесса
- При выключении не дождался конца процесса и отключил питание. Теперь при запуске компьютер начинает бесконечно обращатьс...
- Как просмотреть историю процесса загрузки Windows?
- 5. Организация процесса регистрации посетителей
- 9.1. Окружение процесса