logo

fork() у C

Системний виклик Fork використовується для створення нового процесу в системах Linux і Unix, який називається дочірній процес , який виконується одночасно з процесом, який здійснює виклик fork() (батьківський процес). Після створення нового дочірнього процесу обидва процеси виконають наступну інструкцію після системного виклику fork().

Дочірній процес використовує той самий ПК (лічильник програм), ті самі регістри процесора та ті самі відкриті файли, які використовуються в батьківському процесі. Він не приймає параметрів і повертає ціле значення.



Нижче наведено різні значення, які повертає fork().

  • Від’ємне значення : Створення дочірнього процесу було невдалим.
  • Нуль : Повернуто до щойно створеного дочірнього процесу.
  • Позитивне значення : повертається до батьків або абонента. Значення містить ідентифікатор новоствореного дочірнього процесу.

створення процесу fork

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



Зауважте, що наведені вище програми не компілюються в середовищі Windows.

Приклад fork() у C

C




підключення java



#include> #include> #include> int> main()> {> > >// make two process which run same> >// program after this instruction> >pid_t p = fork();> >if>(p<0){> >perror>(>'fork fail'>);> >exit>(1);> >}> >printf>(>'Hello world!, process_id(pid) = %d '>,getpid());> >return> 0;> }>

>

>

Вихід

Hello world!, process_id(pid) = 31 Hello world!, process_id(pid) = 32>

Приклад 2: обчисліть кількість разів друку привітання.

C




#include> #include> #include> int> main()> {> >fork();> >fork();> >fork();> >printf>(>'hello '>);> >return> 0;> }>

>

>

Вихід

hello hello hello hello hello hello hello hello>

Пояснення

Кількість надрукованих «привіт» дорівнює кількості створених процесів. Загальна кількість процесів = 2п, де n – кількість системних викликів fork. Отже, тут n = 3, 23= 8 Давайте розмістимо деякі назви міток для трьох рядків:

fork (); // Line 1 fork (); // Line 2 fork (); // Line 3 L1 // There will be 1 child process /  // created by line 1. L2 L2 // There will be 2 child processes /  /  // created by line 2 L3 L3 L3 L3 // There will be 4 child processes // created by line 3>

Отже, загалом є вісім процесів (нові дочірні процеси та один оригінальний процес). Якщо ми хочемо представити зв’язок між процесами у вигляді ієрархії дерева, це буде наступним чином: Основний процес: P0 Процеси, створені 1-м форком: P1 Процеси, створені 2-м форком: P2, P3 Процеси, створені 3-м форком: P4, P5, P6, P7

 P0 / |  P1 P4 P2 /   P3 P6 P5 / P7>

Приклад 3: Прогнозуйте вихід наступної програми.

C




#include> #include> #include> #include> void> forkexample()> {> >pid_t p;> >p = fork();> >if>(p<0)> >{> >perror>(>'fork fail'>);> >exit>(1);> >}> >// child process because return value zero> >else> if> ( p == 0)> >printf>(>'Hello from Child! '>);> > >// parent process because return value non-zero.> >else> >printf>(>'Hello from Parent! '>);> }> int> main()> {> >forkexample();> >return> 0;> }>

>

>

Вихід

Hello from Parent! Hello from Child!>

Примітка: У наведеному вище коді створюється дочірній процес. fork() повертає 0 у дочірньому процесі та позитивне ціле число в батьківському процесі. Тут можливі два виходи, оскільки батьківський і дочірній процеси виконуються одночасно. Тож ми не знаємо, чи ОС спочатку передасть керування батьківському чи дочірньому процесу.

Батьківський і дочірній процеси запускають ту саму програму, але це не означає, що вони ідентичні. ОС виділяє різні дані та стани для цих двох процесів, і потік керування цими процесами може відрізнятися. Подивіться наступний приклад:

Приклад 4: Прогнозуйте вихід наступної програми.

C




gzip для Linux

#include> #include> #include> #include> > void> forkexample()> {> >int> x = 1;> >pid_t p = fork();> >if>(p<0){> >perror>(>'fork fail'>);> >exit>(1);> >}> >else> if> (p == 0)> >printf>(>'Child has x = %d '>, ++x);> >else> >printf>(>'Parent has x = %d '>, --x);> }> int> main()> {> >forkexample();> >return> 0;> }>

>

>

Вихід

Parent has x = 0 Child has x = 2>

або

Вихід

Child has x = 2 Parent has x = 0>

Тут зміна глобальної змінної в одному процесі не впливає на два інші процеси, оскільки дані/стан цих двох процесів різні. Батьківський і дочірній також запускаються одночасно, тому можливі два виходи.

fork() проти exec()

Системний виклик fork створює новий процес. Новий процес, створений fork(), є копією поточного процесу, за винятком повернутого значення. З іншого боку, системний виклик exec() замінює поточний процес новою програмою.

Проблеми на основі C fork()

1. Процес виконує наступний код

C

Команди ls linux




for> (i = 0; i fork();>

>

>

Загальна кількість створених дочірніх процесів становить (GATE-CS-2008)

(A) n
(B) 2^n – 1
(C) 2^n
(D) 2^(n+1) – 1

Перегляньте це рішення.

2. Розглянемо наступний фрагмент коду:

C




if> (fork() == 0) {> >a = a + 5;> >printf>(>'%d, %d '>, a, &a);> }> else> {> >a = a –5;> >printf>(>'%d, %d '>, a, &a);> }>

>

>

Нехай u, v — значення, надруковані батьківським процесом, а x, y — значення, надруковані дочірнім процесом. Що з наведеного ПРАВДИВО? (GATE-CS-2005)

(A) u = x + 10 і v = y
(B) u = x + 10 і v != y
(C) u + 10 = x і v = y
(D) u + 10 = x і v != y

Перегляньте це рішення.

3. Спрогнозуйте результат наведеної нижче програми.

C




#include> #include> int> main()> > >fork();> >fork() && fork()>

>

змінити назву каталогу linux

>

Перегляньте це рішення

Пов'язані статті:

  • Програма на C для демонстрації fork() і pipe()
  • Зомбі та орфанні процеси в C
  • fork() і створені за його допомогою ч/б процеси спільного використання пам’яті