Procesy

Algorytm Fork

Autor: Bartłomiej Kijanka


1.0 Interfejs programisty

1.1 Funkcja systemowa fork()

Fork jest jedną z najważniejszych funkcji systemowych. Jej zadaniem jest stworzenie nowego procesu, potomka procesu wywołującego. Interfejs to:

Zwracaną wartością jest PID potomka w procesie macierzystym i 0 w procesie potomnym (proces potomny rozpoczyna się, jakby sam wywołał forka i czekał na rezultat) bądź -1 w przypadku niepowodzenia. Proces potomny dziedziczy cały kontekst (np. tablicę deskryptorów, procedury obsługi sygnałów itd.) z procesu macierzystego. Typowym przykładem użycia tej funkcji jest:

Wywołanie fork jest jedynie interfejsem do funkcji do_fork, zadeklarowanej w module kernel/fork.c; w niej odbywa się cała praca.

1.2 Funkcja systemowa vfork()

Podobnie jak funkcja fork(), vfork tworzy proces potomny. Jednak w wyniku działania tej funkcji proces macierzysty zostaje zawieszony do chwili wywołania przez syna _exit() albo execve(). Syn stworzony przez vfork operuje na stronach pamięci rodzica. Podobnie jak fork(), vfork wywołuje funkcję wewnętrzną do_fork, ale w odróżnieniu od forka przekazuje w clone_flags parametry CLONE_VFORK i CLONE_VM.

1.3 Funkcja systemowa clone()

Funkcja ta jest rozszerzeniem forka o możliwość dzielenia zasobów procesu, czyli udostępnienia synowi takich zasobów ojca jak segmenty pamięci, tablice deskryptorów plików i obsługi sygnałów. Funkcja clone przyjmuje jako argumenty min. flagi klonowania, określające rozdział zasobów pomiędzy rodzicem a procesem potomnym.

Funkcje fork i vfork są jedynie szczególnymi przypadkami funkcji clone - pierwsza nie uzywa żadnych flag klonowania, druga korzysta z flagi dzielenia przestrzeni adresowej CLONE_VM.

Opis flag klonowania poniżej.


2.0 Implementacja: funkcja do_fork()

Funkcje systemowe istnieją wewnątrz jądra jako zwykłe funkcje C, z tym, że ich nazwy poprzedzone są prefiksem "sys_". Takie funkcje dla fork , clone i vfork zadeklarowane są w module process.c . Ich zadaniem jest wywołanie funkcji do_fork z odpowiednimi parametrami. Najważniejszym z nich są flagi klonowania.

2.1 Flagi klonowania

Mogą się składać z następujących wartości:


3.0 Algorytm do_fork

1) Sprawdzenie i ustawienie wartości struktury task_struct na czas forkowania :

2) Inicjalizacja 'własciwych' danych w task_struct:

3) Skopiowanie kontekstu procesu macierzystego; wywoływane są funkcje:

Gdy którakolwiek z tych funkcji zwróci błąd, funkcja do_fork wychodzi z błędem.

4) Kluczowe miejsce algorytmu fork: fizyczne rozdzielenie procesów macierzystego i potomnego. Zajmuje się tym funkcja copy_thread:

Od tego miejsca istnieją już dwa osobne procesy: ojciec, który kontynuuje wykonanie funkcji i potomek, który będzie miał złudzenie, że sam właśnie wykonał forka. Funkcja ta zadba, żeby potomek otrzymał z tego 'wywołania' wartość 0. Funkcja copy_thread zdefiniowana jest w pliku process.c i działa bezpośrednio na rejestrach komputera.

5) Kończenie ustawień pól i wstawienie nowego procesu do struktur systemowych:

6) Jeśli jedną z flag była CLONE_VFORK - np w wyniku wywołania vfork(), to proces macierzysty zostaje w tym momencie wstrzymany do chwili wywołania przez potomka mm_release. (zwolnienia przestrzeni adresowej)


7) Zwracamy wartość (PID nowego procesu)