Основы многозадачности в Linux


Концепция развилки: fork()



бет7/15
Дата16.11.2022
өлшемі472,04 Kb.
#158456
1   2   3   4   5   6   7   8   9   10   ...   15
Байланысты:
5-6 лаб раб (1)

Концепция развилки: fork()
Для порождения нового процесса предназначен системный вызов fork(), объявленный в заголовочном файле unistd.h следующим образом:
pid_t fork (void);
Системный вызов fork() порождает процесс методом "клонирования". Это значит, что новый процесс является точной копией своего родителя и выполняет ту же самую программу. Это звучит странно, но попробуем разобраться во всем по порядку. Рассмотрим сначала небольшой пример (листинг 10.1)
Листинг 10.1. Пример fork1.c
#include
#include
int main (void)
{
fork ();
printf ("Hello World\n");
sleep (15);
return 0;
}
Вот что получилось:


$ gcc -o fork1 fork1.c
$ ./fork1 > output &
[1] 4272
$ ps
PID TTY TIME CMD
3325 pts/1 00:00:00 bash
4272 pts/1 00:00:00 fork1
4273 pts/1 00:00:00 fork1
4274 pts/1 00:00:00 ps
$ cat output
Hello World
Hello World
[1]+ Done ./fork1 >output

Программа fork1 породила новый процесс, о чем свидетельствует вывод программы ps. Сразу после вызова fork() каждый процесс продолжил самостоятельно выполнять одну и ту же программу fork1. Этим и объясняется наличие двух приветствий "Hello World" в файле output


Чтобы в контексте программы отделить один процесс от другого, достаточно знать, что системный вызов fork() возвращает в текущем процессе PID порожденного потомка (или –1 в случае ошибки). А в новый процесс fork() возвращает 0.


Рассмотрим пример (листинг 10.2), в котором родительский и дочерний процессы выполняют разные действия.
Листинг 10.2. Пример fork2.c
#include
#include
#include
int main (void)
{
pid_t result = fork();
if (result == -1) {
fprintf (stderr, "Error\n");
return 1;
}
if (result == 0)
printf ("I'm child with PID=%d\n", getpid ());
else
printf ("I'm parent with PID=%d\n", getpid ());
return 0;
}
Получилось следующее:
$ ./fork2
I'm child with PID=19414
I'm parent with PID=19413
В приведенном примере сообщение родителя могло бы появиться первым. Дело в том, что процессы в Linux работают на самом деле не одновременно. Ядро периодически дает возможность каждому процессу передать свой исполняемый код процессору (или процессорам, если их несколько). Эти переключения обычно происходят настолько быстро, что у нас создается иллюзия одновременной работы нескольких программ.
За переключение процессов отвечают специальные алгоритмы, находящиеся в ядре
Linux. Считается, что пользователи и программисты должны условно считать алгоритмы переключения процессов непредсказуемыми. Иными словами, процессы в
Linux работают независимо друг от друга. Подобная договоренность позволяет ядру Linux "интеллектуально" распределять системные ресурсы между процессами, повышая производительность системы в целом.
Рассмотрим пример (листинг 10.3), демонстрирующий "непредсказуемость" переключения процессов в Linux.


Достарыңызбен бөлісу:
1   2   3   4   5   6   7   8   9   10   ...   15




©engime.org 2024
әкімшілігінің қараңыз

    Басты бет