fork to wywołanie systemowe (fork()), które tworzy nowy proces przez sklonowanie procesu wywołującego. Proces uruchamiający fork() nazywamy rodzicem (parent), a nowo powstały to dziecko (child). Dziecko dostaje niemal identyczną kopię pamięci, deskryptorów plików i stanu wykonania rodzica — to fundamentalny mechanizm, dzięki któremu w systemach uniksowych jeden proces potrafi „rozmnożyć” inny.
Jak to działa
Najciekawsze w fork() jest to, że wywołujesz go raz, a wraca dwa razy: osobno w rodzicu i osobno w dziecku. Rozróżniasz je po wartości zwracanej. W dziecku fork() zwraca 0, w rodzicu zwraca PID (identyfikator) świeżo utworzonego dziecka, a -1 oznacza błąd (np. wyczerpany limit procesów). Na tej jednej liczbie opiera się cała logika — to po niej decydujesz, który fragment kodu wykona dziecko, a który rodzic.
Nowoczesne jądra nie kopiują od razu całej pamięci. Stosują copy-on-write: rodzic i dziecko współdzielą te same strony pamięci, a fizyczna kopia powstaje dopiero wtedy, gdy któryś z nich coś zapisze. Dzięki temu fork() jest tani, nawet gdy proces zajmuje gigabajty RAM. Samo fork() nie uruchamia nowego programu — żeby dziecko zaczęło robić coś innego niż rodzic, łączysz je zwykle z rodziną wywołań exec (np. execvp()), która podmienia obraz procesu na nowy program.
Przykład z praktyki
Ten wzorzec fork() + exec() + wait() to dokładnie to, co robi Twój shell (bash, zsh) za każdym razem, gdy wpiszesz komendę. Gdy wpisujesz ls -la, shell robi fork(), w dziecku woła execvp("ls", ...), a sam (rodzic) czeka na wait(), aż dziecko skończy. W kodzie C wygląda to mniej więcej tak:
pid_t pid = fork();if (pid == 0) { execvp(...); }— to gałąź dzieckaelse { wait(NULL); }— rodzic czeka na potomka
Ten sam mechanizm widać po fork() w serwerach (klasyczny model „fork per connection”) czy w demonach uniksowych.
Na co uważać
Najczęstszy błąd to brak wait() w rodzicu. Gdy dziecko się kończy, a rodzic nie odbierze jego statusu, zostaje proces zombie (stan Z w ps). Druga pułapka to fork bomb — proces, który rekurencyjnie forkuje sam siebie, aż zapcha tablicę procesów (stąd legendarny :(){ :|:& };:). Pamiętaj też, że dziecko dziedziczy otwarte deskryptory plików, co bywa źródłem subtelnych wycieków, jeśli o tym zapomnisz.
Pojęcia powiązane: exec, wait, PID, proces zombie, copy-on-write, vfork, posix_spawn, sygnał SIGCHLD, demon (daemon).