fork(2) System Calls Manual fork(2) NAZWA fork - tworzy proces potomny BIBLIOTEKA Standardowa biblioteka C (libc, -lc) SKLADNIA #include pid_t fork(void); OPIS fork() tworzy nowy proces, duplikujac proces wywolujacy. Nowy proces jest nazywany procesem potomnym (lub dzieckiem). Proces wywolujacy jest nazywany procesem macierzystym (lub rodzicem). Proces potomny i proces macierzysty dzialaja w oddzielnych rejonach pamieci. W momencie wykonania fork() oba rejony pamieci maja taka sama zawartosc. Zapisy do pamieci, przypisywania (mmap(2)) i odmapowywania (munmap(2)) pliku wykonane wobec jednego z procesow nie maja wplywu na drugi. Proces potomny jest dokladna kopia procesu macierzystego z wylaczeniem nastepujacych punktow: o Proces potomny ma swoj unikatowy identyfikator procesu i nie pasuje ono do identyfikatora zadnej istniejacej sesji lub grupy (setpgid(2)) procesu. o Identyfikator procesu macierzystego dla procesu potomnego jest taki sam jak identyfikator procesu macierzystego. o Proces potomny nie dziedziczy blokad pamieci swojego procesu macierzystego (mlock(2), mlockall(2)). o Uzycie zasobow procesu (getrusage(2)) i liczniki czasu procesora (times(2)) sa resetowane do zera dla procesu potomnego. o Zestaw oczekujacych sygnalow dla procesu potomnego jest poczatkowo pusty (sigpending(2)). o Proces potomny nie dziedziczy dostosowan semaforow od procesu macierzystego (semop(2)). o Proces potomny nie dziedziczy blokad rekordow zwiazanych z procesem od swojego procesu macierzystego (fcntl(2)) (z drugiej strony dziedziczy blokady opisu otwartego pliku (OFD) fcntl(2) oraz blokady flock(2) od swojego procesu macierzystego). o Proces potomny nie dziedziczy czasomierzy od swojego procesu macierzystego (setitimer(2), alarm(2), timer_create(2)). o Proces potomny nie dziedziczy zaleglych, asynchronicznych operacji wejscia/wyjscia od procesu macierzystego (aio_read(3), aio_write(3)), ani nie dziedziczy zadnego kontekstu asynchronicznego wejscia/wyjscia od procesu macierzystego (zob. io_setup(2)). Atrybuty procesu w powyzszej liscie sa okreslone w normie POSIX.1. Proces macierzysty i potomny beda sie roznic rowniez w odniesieniu do nastepujacych, typowo linuksowych atrybutow procesu: o Proces potomny nie odziedziczy notyfikacji o zmianie katalogu (dnotify) od swojego rodzica (wiecej informacji w opisie F_NOTIFY w podreczniku fcntl(2)). o Ustawienie PR_SET_PDEATHSIG prctl(2) jest resetowane, dzieki czemu proces potomny nie otrzyma sygnalu, gdy jego proces macierzysty ulegnie zakonczeniu. o Domyslna wartosc luzu czasomierza jest ustawiana na aktualna wartosc luzu czasomierza procesu macierzystego. Wiecej informacji w opisie PR_SET_TIMERSLACK w podreczniku prctl(2). o Przypisania pamieci oznaczone znacznikiem MADV_DONTFORK madvise(2), nie sa dziedziczone poprzez fork(). o Pamiec w przedzialach adresowych oznaczonych znacznikiem MADV_WIPEONFORK madvise(2) jest zerowana dla procesu potomnego, po wykonaniu fork() (ustawienie MADV_WIPEONFORK nie ulega zmianie dla tych przedzialow adresowych, dla procesu potomnego). o Sygnalem przerwania procesu potomnego jest zawsze SIGCHLD (zob. clone(2)). o Bity uprawnien dostepu do portu ustawione za pomoca ioperm(2) nie sa dziedziczone przez proces potomny; musi on sam wlaczyc wszystkie wymagane bity przy uzyciu ioperm(2). Dalsze uwagi: o Proces potomny jest tworzony jednym watkiem -- tym ktory wywolal fork(). Cala wirtualna przestrzen adresowa jest replikowana dla procesu potomnego; obejmuje to zatrzaski (muteksy), zmienne warunkowe i inne obiekty pthread; podrecznik pthread_atfork(3) moze okazac sie przydatny w radzeniu sobie z problemami, jakie to moze spowodowac. o W programie wielowatkowym, po fork() proces potomny moze bezpiecznie wykonac jedynie funkcje ktore sa async-signal-safe (zob. signal-safety(7)) az do momentu, gdy nie wywola execve(2). o Proces potomny dziedziczy kopie zestawu deskryptorow otwartego pliku. Kazdy deskryptor pliku procesu potomnego odnosi sie do tego samego opisu otwartego pliku (OFD, zob. open(2)) jako deskryptor odpowiadajacego pliku swego procesu macierzystego. Oznacza to, ze dwa deskryptory pliku dziela znaczniki statusu otwartego pliku, przesuniecia pliku oraz atrybuty wejscie/wyjscia zasilane sygnalami (zob. opis F_SETOWN i F_SETSIG w fcntl(2)). o Proces potomny dziedziczy zestaw deskryptorow otwartej kolejki komunikatow procesu macierzystego (zob. mq_overview(7)). Kazdy deskryptor w procesie potomnym odnosi sie do tego samego opisu kolejki otwartego komunikatu, jak odpowiadajacy deskryptor pliku procesu macierzystego. Oznacza to, ze dwa deskryptory pliku dziela te same znaczniki (mq_flags). o Proces potomny kopiuje zestaw strumieni otwartego katalogu procesu macierzystego (zob. opendir(3)). POSIX.1 wskazuje, ze odpowiadajace strumienie katalogow procesu macierzystego i potomnego moga dzielic pozycjonowanie strumienia katalogu, w Linuksie/glibc tak sie nie dzieje. WARTOSC ZWRACANA Po pomyslnym zakonczeniu, w procesie macierzystym zwracany jest PID procesu potomnego, a w procesie potomnym zwracane jest 0. Po bledzie zwracane jest -1 do procesu macierzystego, nie jest tworzony procesie potomny i odpowiednio ustawiane jest errno wskazujac blad. BLEDY EAGAIN Napotkano nalozony systemowo limit liczby watkow. Wystepuje wiele limitow, ktore moga wyzwolic ten blad: o osiagnieto miekki limit zasobow RLIMIT_NPROC (ustawiany za pomoca setrlimit(2)), ktory ogranicza liczbe procesow i watkow dla rzeczywistego identyfikatora uzytkownika; o osiagnieto systemowy limit jadra na liczbe procesow i watkow /proc/sys/kernel/threads-max (zob. proc(5)); o osiagnieto maksymalna liczbe identyfikatorow procesow /proc/sys/kernel/pid_max (zob. proc(5)); albo o osiagnieto limit identyfikatorow procesow (pids.max) nalozony przez kontroler cgroup ,,liczba procesow" (PID-ow). EAGAIN Wywolanie dziala wedlug zasad planisty SCHED_DEADLINE i nie posiada znacznika zresetuj-przy-rozwidleniu. Zob. sched(7). ENOMEM fork() nie potrafil zaalokowac niezbednych struktur jadra z powodu niedostatecznej ilosci pamieci. ENOMEM Probowano utworzyc proces potomny w przestrzeni nazw PID, ktorej proces ,,init" ulegl zakonczeniu. Zob. pid_namespaces(7). ENOSYS fork() nie jest obslugiwane na tej platformie (np. sprzet bez jednostki Memory-Management Unit). ERESTARTNOINTR (od Linuksa 2.6.17) Wywolanie systemowe przerwano sygnalem i zostanie ono przeladowane (widac to tylko przy sledzeniu). WERSJE Roznice biblioteki C/jadra Od glibc 2.3.3, zamiast przywolywac wywolanie systemowe jadra fork(), opakowanie fork() z biblioteki glibc, dostepne jako czesc implementacji watkowania NPTL, przywoluje clone(2) ze znacznikami, zapewniajacymi taki sam efekt, jak tradycyjne wywolanie systemowe (wywolanie fork() jest rownowazne wywolaniu clone(2) przy okresleniu flags jako wylacznie SIGCHLD). Opakowanie z biblioteki glibc przywoluje procedury obslugi rozwidlania, ktore ustanowiono za pomoca pthread_atfork(3). STANDARDY POSIX.1-2008. HISTORIA POSIX.1-2001, SVr4, 4.3BSD. UWAGI Pod Linuksem fork() jest zaimplementowane za pomoca kopiowania stron pamieci przy zapisie, wiec jedynymi mankamentami sa czas i pamiec wymagane do powielenia tablic stron rodzica i utworzenia unikalnej struktury zadania dla potomka. PRZYKLADY Zob. pipe(2) i wait(2), aby obejrzec wiecej przykladow. #include #include #include #include #include int main(void) { pid_t pid; if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) { perror("sygnal"); exit(EXIT_FAILURE); } pid = fork(); switch (pid) { case -1: perror("fork"); exit(EXIT_FAILURE); case 0: puts("Proces potomny wychodzi."); exit(EXIT_SUCCESS); default: printf("Proces potomny ma PID %jd\n", (intmax_t) pid); puts("Proces macierzysty wychodzi."); exit(EXIT_SUCCESS); } } ZOBACZ TAKZE clone(2), execve(2), exit(2), setrlimit(2), unshare(2), vfork(2), wait(2), daemon(3), pthread_atfork(3), capabilities(7), credentials(7) TLUMACZENIE Autorami polskiego tlumaczenia niniejszej strony podrecznika sa: Przemek Borys , Andrzej Krzysztofowicz i Michal Kulach Niniejsze tlumaczenie jest wolna dokumentacja. Blizsze informacje o warunkach licencji mozna uzyskac zapoznajac sie z GNU General Public License w wersji 3 lub nowszej. Nie przyjmuje sie ZADNEJ ODPOWIEDZIALNOSCI. Bledy w tlumaczeniu strony podrecznika prosimy zglaszac na adres listy dyskusyjnej . Linux man-pages 6.06 31 pazdziernika 2023 r. fork(2)