plucky (2) fork.2.gz

Provided by: manpages-pl-dev_4.25.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  ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩  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⟩.