Provided by: manpages-pl-dev_4.23.1-1_all bug

NAZWA

       fork - tworzy proces potomny

BIBLIOTEKA

       Standardowa biblioteka C (libc, -lc)

SKŁADNIA

       #include <unistd.h>

       pid_t fork(void);

OPIS

       fork() tworzy nowy proces, duplikując proces wywołujący. Nowy proces jest nazywany procesem potomnym (lub
       dzieckiem). Proces wywołujący jest nazywany procesem macierzystym (lub rodzicem).

       Proces  potomny i proces macierzysty działają w oddzielnych rejonach pamięci. W momencie wykonania fork()
       oba rejony pamięci mają taką samą zawartość. Zapisy do pamięci, przypisywania (mmap(2))  i  odmapowywania
       (munmap(2)) pliku wykonane wobec jednego z procesów nie mają wpływu na drugi.

       Proces potomny jest dokładną kopią procesu macierzystego z wyłączeniem następujących punktów:

       •  Proces  potomny  ma  swój  unikatowy  identyfikator  procesu i nie pasuje ono do identyfikatora żadnej
          istniejącej sesji lub grupy (setpgid(2)) procesu.

       •  Identyfikator procesu macierzystego dla procesu potomnego jest  taki  sam  jak  identyfikator  procesu
          macierzystego.

       •  Proces potomny nie dziedziczy blokad pamięci swojego procesu macierzystego (mlock(2), mlockall(2)).

       •  Użycie  zasobów procesu (getrusage(2)) i liczniki czasu procesora (times(2)) są resetowane do zera dla
          procesu potomnego.

       •  Zestaw oczekujących sygnałów dla procesu potomnego jest początkowo pusty (sigpending(2)).

       •  Proces potomny nie dziedziczy dostosowań semaforów od procesu macierzystego (semop(2)).

       •  Proces potomny nie dziedziczy blokad rekordów związanych 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).

       •  Proces potomny nie dziedziczy czasomierzy od swojego procesu  macierzystego  (setitimer(2),  alarm(2),
          timer_create(2)).

       •  Proces  potomny  nie  dziedziczy  zaległych,  asynchronicznych  operacji  wejścia/wyjścia  od  procesu
          macierzystego (aio_read(3), aio_write(3)),  ani  nie  dziedziczy  żadnego  kontekstu  asynchronicznego
          wejścia/wyjścia od procesu macierzystego (zob. io_setup(2)).

       Atrybuty  procesu w powyższej liście są określone w normie POSIX.1. Proces macierzysty i potomny będą się
       różnić również w odniesieniu do następujących, typowo linuksowych atrybutów procesu:

       •  Proces potomny nie odziedziczy notyfikacji o zmianie katalogu (dnotify)  od  swojego  rodzica  (więcej
          informacji w opisie F_NOTIFY w podręczniku fcntl(2)).

       •  Ustawienie PR_SET_PDEATHSIG prctl(2) jest resetowane, dzięki czemu proces potomny nie otrzyma sygnału,
          gdy jego proces macierzysty ulegnie zakończeniu.

       •  Domyślna  wartość  luzu  czasomierza  jest  ustawiana  na  aktualną  wartość  luzu czasomierza procesu
          macierzystego. Więcej informacji w opisie PR_SET_TIMERSLACK w podręczniku prctl(2).

       •  Przypisania pamięci oznaczone  znacznikiem  MADV_DONTFORK  madvise(2),  nie  są  dziedziczone  poprzez
          fork().

       •  Pamięć  w przedziałach adresowych oznaczonych znacznikiem MADV_WIPEONFORK madvise(2) jest zerowana dla
          procesu potomnego, po  wykonaniu  fork()  (ustawienie  MADV_WIPEONFORK  nie  ulega  zmianie  dla  tych
          przedziałów adresowych, dla procesu potomnego).

       •  Sygnałem przerwania procesu potomnego jest zawsze SIGCHLD (zob. clone(2)).

       •  Bity  uprawnień  dostępu  do  portu  ustawione  za  pomocą  ioperm(2) nie są dziedziczone przez proces
          potomny; musi on sam włączyć wszystkie wymagane bity przy użyciu ioperm(2).

       Dalsze uwagi:

       •  Proces potomny jest tworzony jednym wątkiem — tym który  wywołał  fork().  Cała  wirtualna  przestrzeń
          adresowa  jest replikowana dla procesu potomnego; obejmuje to zatrzaski (muteksy), zmienne warunkowe i
          inne obiekty pthread; podręcznik pthread_atfork(3) może  okazać  się  przydatny  w  radzeniu  sobie  z
          problemami, jakie to może spowodować.

       •  W  programie wielowątkowym, po fork() proces potomny może bezpiecznie wykonać jedynie funkcje które są
          async-signal-safe (zob. signal-safety(7)) aż do momentu, gdy nie wywoła execve(2).

       •  Proces potomny dziedziczy kopie zestawu deskryptorów otwartego pliku. Każdy deskryptor  pliku  procesu
          potomnego  odnosi  się  do  tego  samego  opisu  otwartego  pliku  (OFD, zob. open(2)) jako deskryptor
          odpowiadającego pliku swego procesu  macierzystego.  Oznacza  to,  że  dwa  deskryptory  pliku  dzielą
          znaczniki statusu otwartego pliku, przesunięcia pliku oraz atrybuty wejście/wyjścia zasilane sygnałami
          (zob. opis F_SETOWN i F_SETSIG w fcntl(2)).

       •  Proces potomny dziedziczy zestaw deskryptorów otwartej kolejki komunikatów procesu macierzystego (zob.
          mq_overview(7)).  Każdy  deskryptor  w  procesie  potomnym  odnosi  się  do  tego samego opisu kolejki
          otwartego komunikatu, jak odpowiadający deskryptor pliku procesu macierzystego.  Oznacza  to,  że  dwa
          deskryptory pliku dzielą te same znaczniki (mq_flags).

       •  Proces  potomny  kopiuje  zestaw strumieni otwartego katalogu procesu macierzystego (zob. opendir(3)).
          POSIX.1 wskazuje, że odpowiadające strumienie katalogów procesu macierzystego i potomnego mogą dzielić
          pozycjonowanie strumienia katalogu, w Linuksie/glibc tak się nie dzieje.

WARTOŚĆ ZWRACANA

       Po pomyślnym zakończeniu, w procesie macierzystym zwracany jest  PID  procesu  potomnego,  a  w  procesie
       potomnym  zwracane  jest  0.  Po  błędzie  zwracane  jest  -1 do procesu macierzystego, nie jest tworzony
       procesie potomny i odpowiednio ustawiane jest errno wskazując błąd.

BŁĘDY

       EAGAIN Napotkano nałożony systemowo limit liczby wątków. Występuje wiele limitów, które mogą wyzwolić ten
              błąd:

              •  osiągnięto  miękki  limit  zasobów  RLIMIT_NPROC  (ustawiany  za  pomocą  setrlimit(2)),  który
                 ogranicza liczbę procesów i wątków dla rzeczywistego identyfikatora użytkownika;

              •  osiągnięto systemowy limit jądra na liczbę procesów i wątków /proc/sys/kernel/threads-max (zob.
                 proc(5));

              •  osiągnięto  maksymalną liczbę identyfikatorów procesów /proc/sys/kernel/pid_max (zob. proc(5));
                 albo

              •  osiągnięto limit identyfikatorów procesów (pids.max) nałożony przez  kontroler  cgroup  „liczba
                 procesów” (PID-ów).

       EAGAIN Wywołanie    działa    według    zasad   planisty   SCHED_DEADLINE   i   nie   posiada   znacznika
              zresetuj-przy-rozwidleniu. Zob. sched(7).

       ENOMEM fork() nie potrafił zaalokować niezbędnych struktur jądra z powodu niedostatecznej ilości pamięci.

       ENOMEM Próbowano utworzyć proces potomny w przestrzeni nazw PID, której proces „init” uległ  zakończeniu.
              Zob. pid_namespaces(7).

       ENOSYS fork() nie jest obsługiwane na tej platformie (np. sprzęt bez jednostki Memory-Management Unit).

       ERESTARTNOINTR (od Linuksa 2.6.17)
              Wywołanie  systemowe  przerwano  sygnałem  i  zostanie  ono  przeładowane  (widać  to  tylko  przy
              śledzeniu).

WERSJE

   Różnice biblioteki C/jądra
       Od glibc 2.3.3, zamiast przywoływać wywołanie systemowe jądra  fork(),  opakowanie  fork()  z  biblioteki
       glibc,   dostępne   jako  część  implementacji  wątkowania  NPTL,  przywołuje  clone(2)  ze  znacznikami,
       zapewniającymi taki sam efekt, jak tradycyjne  wywołanie  systemowe  (wywołanie  fork()  jest  równoważne
       wywołaniu  clone(2)  przy  określeniu  flags  jako  wyłącznie  SIGCHLD).  Opakowanie  z  biblioteki glibc
       przywołuje procedury obsługi rozwidlania, które ustanowiono za pomocą pthread_atfork(3).

STANDARDY

       POSIX.1-2008.

HISTORIA

       POSIX.1-2001, SVr4, 4.3BSD.

UWAGI

       Pod Linuksem fork() jest zaimplementowane za pomocą kopiowania stron pamięci przy zapisie, więc  jedynymi
       mankamentami  są  czas  i  pamięć  wymagane  do  powielenia  tablic  stron rodzica i utworzenia unikalnej
       struktury zadania dla potomka.

PRZYKŁADY

       Zob. pipe(2) i wait(2), aby obejrzeć więcej przykładów.

       #include <signal.h>
       #include <stdint.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <sys/types.h>
       #include <unistd.h>

       int
       main(void)
       {
           pid_t pid;

           if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) {
               perror("sygnał");
               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 TAKŻE

       clone(2), execve(2), exit(2), setrlimit(2), unshare(2), vfork(2), wait(2), daemon(3),  pthread_atfork(3),
       capabilities(7), credentials(7)

TŁUMACZENIE

       Autorami  polskiego  tłumaczenia  niniejszej  strony podręcznika są: Przemek Borys <pborys@dione.ids.pl>,
       Andrzej Krzysztofowicz <ankry@green.mf.pg.gda.pl> i Michał Kułach <michal.kulach@gmail.com>

       Niniejsze tłumaczenie jest wolną dokumentacją. Bliższe informacje  o  warunkach  licencji  można  uzyskać
       zapoznając   się   z   GNU General Public License w wersji 3   lub  nowszej.  Nie  przyjmuje  się  ŻADNEJ
       ODPOWIEDZIALNOŚCI.

       Błędy w  tłumaczeniu  strony  podręcznika  prosimy  zgłaszać  na  adres  listy  dyskusyjnej  manpages-pl-
       list@lists.sourceforge.net.

Linux man-pages 6.8                              2 maja 2024 r.                                          fork(2)