fork() v C
Systémové volání Fork se používá pro vytvoření nového procesu v systémech Linux a Unix, který se nazývá dětský proces , který běží souběžně s procesem, který volá fork() (nadřazený proces). Po vytvoření nového podřízeného procesu oba procesy provedou další instrukci následující po systémovém volání fork().
Podřízený proces používá stejný počítač (počítadlo programů), stejné registry CPU a stejné otevřené soubory, které používá nadřazený proces. Nepotřebuje žádné parametry a vrací celočíselnou hodnotu.
Níže jsou uvedeny různé hodnoty vrácené fork().
- Záporná hodnota : Vytvoření podřízeného procesu bylo neúspěšné.
- Nula : Návrat k nově vytvořenému podřízenému procesu.
- Pozitivní hodnota : Vráceno rodiči nebo volajícímu. Hodnota obsahuje ID procesu nově vytvořeného podřízeného procesu.
Poznámka: fork() je funkce založená na vláknech, pro získání správného výstupu spusťte program na místním systému.
Vezměte prosím na vědomí, že výše uvedené programy se nekompilují v prostředí Windows.
Příklad fork() v C
C
#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;> }> |
Výstup
Hello world!, process_id(pid) = 31 Hello world!, process_id(pid) = 32
Příklad 2: Vypočítejte, kolikrát se vytiskne ahoj.
C
#include> #include> #include> int> main()> {> > fork();> > fork();> > fork();> > printf> (> 'hello
'> );> > return> 0;> }> |
Výstup
hello hello hello hello hello hello hello hello
Vysvětlení
Počet vytištění „ahoj“ se rovná počtu vytvořených procesů. Celkový počet procesů = 2 n , kde n je počet systémových volání rozvětvení. Takže zde n = 3, 2 3 = 8 Uveďme nějaké názvy štítků pro tři řádky:
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
Existuje tedy celkem osm procesů (nové podřízené procesy a jeden původní proces). Pokud bychom chtěli vztah mezi procesy znázornit jako stromovou hierarchii, bylo by to následující: Hlavní proces: P0 Procesy vytvořené 1. rozvětvením: P1 Procesy vytvořené 2. rozvětvením: P2, P3 Procesy vytvořené 3. rozvětvením: P4, P5, P6, P7
P0 / | P1 P4 P2 / P3 P6 P5 / P7
Příklad 3: Předpovězte výstup následujícího programu.
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;> }> |
Výstup
Hello from Parent! Hello from Child!
Poznámka: Ve výše uvedeném kódu je vytvořen podřízený proces. fork() vrací 0 v podřízeném procesu a kladné celé číslo v nadřazeném procesu. Zde jsou možné dva výstupy, protože nadřazený proces a podřízený proces běží souběžně. Nevíme tedy, zda OS nejprve poskytne kontrolu nadřazenému procesu nebo podřízenému procesu.
Nadřazený proces a podřízený proces běží na stejném programu, ale to neznamená, že jsou totožné. OS těmto dvěma procesům přiděluje různá data a stavy a tok řízení těchto procesů může být odlišný. Viz následující příklad:
Příklad 4: Předpovězte výstup následujícího programu.
C
#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;> }> |
Výstup
Parent has x = 0 Child has x = 2
nebo
Výstup
Child has x = 2 Parent has x = 0
Zde změna globální proměnné v jednom procesu neovlivňuje dva další procesy, protože data/stav těchto dvou procesů se liší. A také rodič a dítě běží současně, takže jsou možné dva výstupy.
fork() vs exec()
Systémové volání fork vytvoří nový proces. Nový proces vytvořený fork() je kopií aktuálního procesu s výjimkou vrácené hodnoty. Na druhou stranu systémové volání exec() nahradí aktuální proces novým programem.
Problémy založené na C fork()
1. Proces spustí následující kód
C
for> (i = 0; i fork();> |
Celkový počet vytvořených podřízených procesů je (GATE-CS-2008)
(A) n
(B) 2^n – 1
(C) 2^n
(D) 2^(n+1) – 1
Podívejte se na řešení.
2. Zvažte následující fragment kódu:
C
if> (fork() == 0) {> > a = a + 5;> > printf> (> '%d, %d
'> , a, &a);> }> else> {> > a = a –5;> > printf> (> '%d, %d
'> , a, &a);> }> |
Nechť u, v jsou hodnoty vytištěné nadřazeným procesem a x, y jsou hodnoty vytištěné podřízeným procesem. Která z následujících možností je PRAVDA? (GATE-CS-2005)
(A) u = x + 10 a v = y
(B) u = x + 10 a v! = y
(C) u + 10 = x a v = y
(D) u + 10 = x a v! = y
Podívejte se na řešení.
3. Předpovězte výstup níže uvedeného programu.
C
#include> #include> int> main()> > > fork();> > fork() && fork()> |
Řešení viz toto
Související články:
- C program pro demonstraci fork() a pipe()
- Zombie a osiřelé procesy v C
- fork() a pomocí něj vytvořené černobílé procesy sdílené v paměti