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

NAZWA

       clone, __clone2, clone3 - tworzy proces potomny

BIBLIOTEKA

       Standardowa biblioteka C (libc, -lc)

SKŁADNIA

       /* Prototyp funkcji opakowującej z glibc */

       #define _GNU_SOURCE
       #include <sched.h>

       int clone(int (*fn)(void *_Nullable), void *stack, int flags,
                 void *_Nullable arg, ...  /* pid_t *_Nullable parent_tid,
                                              void *_Nullable tls,
                                              pid_t *_Nullable child_tid */ );

       /* Zob. UWAGI dot. prototypu surowego wywołania syst. clone() */

       #include <linux/sched.h>    /* Definicja struct clone_args */
       #include <sched.h>          /* Definicja stałych CLONE_* */
       #include <sys/syscall.h>    /* Definicja stałych SYS_* */
       #include <unistd.h>

       long syscall(SYS_clone3, struct clone_args *cl_args, size_t size);

       Uwaga: glibc nie udostępnia opakowania do clone3(), zatem wymagane jest użycie syscall(2).

OPIS

       Niniejsze wywołania systemowe tworzą nowy proces („potomny”), w sposób podobny do fork(2).

       W przeciwieństwie do fork(2), te wywołania systemowe udostępniają precyzyjniejszą kontrolę
       wobec kontekstu wykonania, który jest dzielony  między  procesem  wywołującym  a  procesem
       potomnym.   Przykładowo,  za  pomocą  niniejszych  wywołań  systemowych,  wywołujący  może
       kontrolować czy oba procesy dzielą wirtualną  przestrzeń  adresową,  tablicę  deskryptorów
       pliku  i  tablicę  procedur obsługi sygnałów. Te wywołania systemowego umożliwiają również
       umieszczenie procesu potomnego w oddzielnych przestrzeniach nazw (zob. namespaces(7)).

       Proszę zauważyć, że w niniejszym  podręczniku  systemowym  „proces  wywołujący”  odpowiada
       zwykle   „procesowy   macierzystemu”.   Proszę   jednak  sprawdzić  opisy  CLONE_PARENT  i
       CLONE_THREAD niżej.

       Niniejsza strona podręcznika opisuje następujące interfejsy:

       •  Funkcję opakowującą clone() z glibc i podległe wywołanie systemowe, w oparciu  o  które
          działa.  Główna  część  podręcznika  opisuje funkcję opakowującą; różnice w stosunku do
          surowego wywołania systemowego opisano bliżej końca.

       •  Nowsze wywołanie systemowe clone3().

       W pozostałej treści niniejszego podręcznika,  pojęcie  „wywołanie  clone”  lub  „wywołanie
       klonowania”  używane  jest  przy  opisywaniu szczegółów odnoszących się do wszystkich tych
       interfejsów.

   Funkcja opakowująca clone()
       Gdy proces potomny tworzony jest za pomocą funkcji  opakowującej  clone(),  rozpoczyna  on
       wykonanie  od  wywołania  funkcji, na którą wskazuje argument fn (różni się to od fork(2),
       gdzie proces potomny kontynuuje wykonanie od miejsca wywołania fork(2)). Argument arg jest
       przekazywany jako argument do funkcji fn.

       Gdy  funkcja  fn(arg)  powróci, proces potomny kończy działanie. Liczba całkowita zwrócona
       przez fn  jest  statusem  zakończenia  procesu  potomnego.  Proces  potomny  może  również
       zakończyć się jawnie wołając exit(2) lub po otrzymaniu krytycznego sygnału.

       Argument  stack określa położenie stosu używanego przez proces potomny. Ponieważ potomek i
       proces wywołujący mogą współdzielić pamięć, nie jest możliwe, aby proces potomny korzystał
       z  tego samego stosu, co proces wywołujący. Proces wywołujący musi więc przydzielić obszar
       pamięci przeznaczony na stos potomka i przekazać wskaźnik do tego obszaru w  clone.  Stosy
       rosną  w dół na wszystkich procesorach, na których działa Linux (z wyjątkiem procesorów HP
       PA), więc stack zazwyczaj wskazuje na najwyższy adres obszaru pamięci  zarezerwowanego  na
       stos  potomka.  Proszę  zauważyć,  że clone() nie zapewnia mechanizmu, w którym wywołujący
       mógłby poinformować jądro o wielkości obszaru stosu.

       Pozostałe argumenty clone() opisano poniżej.

   clone3()
       Wywołanie  systemowe  clone3()  udostępnia  nadzbiór   funkcjonalności   wobec   starszego
       interfejsu  clone().  Zawiera  również  wiele usprawnień API m.in: przestrzeń na dodatkowe
       bity znaczników,  przejrzystszy  podział  stosowania  różnych  argumentów  oraz  możliwość
       określenia rozmiaru przestrzeni stosu procesu potomnego.

       Podobnie  jak  fork(2),  clone3() powraca zarówno w procesie macierzystym, jak i potomnym.
       Zwraca 0 do procesu  potomnego,  natomiast  procesowi  macierzystemu  zwraca  PID  procesu
       potomnego.

       Argumentem cl_args clone3() jest struktura w następującej postaci:

           struct clone_args {
               u64 flags;        /* Maska bitowa znaczników */
               u64 pidfd;        /* Gdzie przechowywać deskryptor pliku PID
                                    (int *) */
               u64 child_tid;    /* Gdzie przechowywać TID p. potomnego,
                                    w pamięci p. potomnego (pid_t *) */
               u64 parent_tid;   /* Gdzie przechowywać TID, w pamięci
                                    procesu macierzystego (pid_t *) */
               u64 exit_signal;  /* Sygnał do dostarcz. przy zakończeniu
                                    procesu potomnego */
               u64 stack;        /* Wskaźnik do najniższych bajtów stosu */
               u64 stack_size;   /* Rozmiar stosu */
               u64 tls;          /* Położenie nowego TLS */
               u64 set_tid;      /* Wskaźnik do tablicy pid_t
                                    (od Linuksa 5.5) */
               u64 set_tid_size; /* Liczba elementów w set_tid
                                    (od Linuksa 5.5) */
               u64 cgroup;       /* Deskryptor pliku docelowej gr. kontr.
                                    procesu potomnego (od Linuksa 5.7) */
           };

       Argument  size dostarczany do clone3() powinien być zainicjowany z rozmiarem tej struktury
       (obecność argumentu size pozwala na przyszłe poszerzanie struktury clone_args).

       Stos procesu potomnego podaje się za pomocą cl_args.stack,  które  wskazuje  na  najniższe
       bajty w przestrzeni stosu oraz za pomocą cl_args.stack_size, które określa rozmiar stosu w
       bajtach. W przypadku gdy poda się znacznik CLONE_VM (zob. niżej),  stos  musi  być  jawnie
       zaalokowany i określony. W przeciwnym przypadku, te dwa pola można podać jako NULL i 0, co
       powoduje używanie przez proces potomny tej samej  przestrzeni  stosu,  z  jakiej  korzysta
       proces macierzysty (we własnej wirtualnej przestrzeni adresowej procesu potomnego).

       Pozostałe pola argumentu cl_args opisano niżej.

   Równoważność pomiędzy argumentami clone() i clone3()
       W   odróżnieniu  do  starszego  interfejsu  clone(),  którego  argumenty  są  przekazywane
       pojedynczo, w nowszym interfejsie clone3() argumenty są łączone  w  strukturze  clone_args
       pokazanej  wyżej. Struktura pozwala na przekazanie nadzbioru informacji, przekazywanych za
       pomocą argumentów clone().

       Poniższa tabela ukazuje równoważność pomiędzy argumentami clone() i  polami  w  argumencie
       clone_args przekazywanym clone3():

           clone()         clone3()       Uwagi
                           pole cl_args
           flags & ~0xff   flags          Do    większości    znaczników;
                                          szczegóły niżej
           parent_tid      pidfd          Zob. CLONE_PIDFD
           child_tid       child_tid      Zob. CLONE_CHILD_SETTID
           parent_tid      parent_tid     Zob. CLONE_PARENT_SETTID
           flags & 0xff    exit_signal
           stack           stack
           ---             stack_size
           tls             tls            Zob. CLONE_SETTLS
           ---             set_tid        Zob. niżej aby poznać szczegóły
           ---             set_tid_size
           ---             cgroup         Zob. CLONE_INTO_CGROUP

   Sygnał zakończenia potomka
       Gdy proces potomny zostanie  zakończony,  do  rodzica  może  być  wysłany  sygnał.  Sygnał
       zakończenia   jest  określany  niższym  bajtem  flags  (clone())  lub  cl_args.exit_signal
       (clone3()). Jeśli określono inny sygnał niż SIGCHLD,  to  proces  macierzysty  musi  podać
       opcję __WALL lub __WCLONE czekając na potomka w wait(2). Gdy sygnał nie zostanie określony
       (tj. podano zero), to proces macierzysty nie zostanie  zawiadomiony  o  zakończeniu  pracy
       potomka.

   Tablica set_tid
       Domyślnie,  jądro wybiera następny numer PID dla nowego procesu, w każdej przestrzeni nazw
       PID, w której jest on obecny. Przy tworzeniu procesu za pomocą clone3(),  tablicę  set_tid
       (dostępną  od  Linuksa  5.5) można użyć do wybrania konkretnych PID-ów w niektórych lub we
       wszystkich przestrzeniach nazw PID, w których jest on obecny. Jeśli  PID  nowo  tworzonego
       procesu  ma  być  ustawiony  tylko  w  bieżącej  przestrzeni nazw PID lub w nowo tworzonej
       przestrzeni nazw PID (jeśli flags zawiera CLONE_NEWPID), to pierwszym elementem w  tablicy
       set_tid musi być żądany PID, a set_tid_size musi wynosić 1.

       Jeśli  PID  nowo  tworzonego procesu ma mieć określoną wartość w wielu przestrzeniach nazw
       PID,  to  tablica  set_tid  może  zawierać  wiele  wpisów.  Pierwszy  wpis  definiuje  PID
       najbardziej   zagnieżdżonej   przestrzeni   nazw  PID,  a  każdy  kolejny  zawiera  PID  w
       odpowiadającej przestrzeni nazw PID przodka. Liczba przestrzeni nazw PID, w której PID  ma
       być  ustawiony,  jest definiowana przez set_tid_size, które nie może być większe od liczby
       aktualnie zagnieżdżonych przestrzeni nazw.

       Aby utworzyć proces z następującymi PID-ami w hierarchii przestrzeni nazw PID:

           Poziom zagn. PID   Żądany PID   Uwagi
           0                  31496        Najbardziej zewnętrzna p. n. PID
           1                  42
           2                  7            Najbardziej wewnętrzna p. n. PID

       Należy ustawić tablicę na

           set_tid[0] = 7;
           set_tid[1] = 42;
           set_tid[2] = 31496;
           set_tid_size = 3;

       Jeśli mają być określone jedynie PID-y w  dwóch  najbardziej  wewnętrznych  przestrzeniach
       nazw PID, należy ustawić tablicę na:

           set_tid[0] = 7;
           set_tid[1] = 42;
           set_tid_size = 2;

       PID  w  przestrzeni  nazw  PID poza dwoma najbardziej wewnętrznymi przestrzeniami nazw PID
       jest wybierany w ten sam sposób, jak inne PID-y.

       Funkcja set_tid wymaga przywileju (ang. capability) CAP_SYS_ADMIN  lub  (od  Linuksa  5.9)
       CAP_CHECKPOINT_RESTORE  we  wszystkich  posiadanych  przestrzeniach  nazw  użytkownika,  w
       których PID ma być zmieniany.

       Wywołujący mogą wybrać PID większy od 1 jedynie, gdy w danej przestrzeni nazw PID istnieje
       już proces init (tj. proces z PID 1). W przeciwnym przypadku, wpis PID dla tej przestrzeni
       nazw musi wynosić 1.

   Maska znaczników
       clone() i clone3() umożliwiają użycie  maski  bitowej  znaczników,  które  modyfikują  ich
       zachowanie i pozwalają wywołującemu na określenie tego, co ma być dzielone między procesem
       wywołującym a potomnym. Maska bitowa —  argument  flags  clone()  lub  pole  cl_args.flags
       przekazywane do clone3() — jest nazywana w pozostałem części niniejszego podręcznika maską
       flags.

       Maskę flags można podać jako sumę bitową (OR) zera lub więcej z poniższych zmiennych. Poza
       wskazanymi  wyjątkami, znaczniki te są dostępne (i mają takie samo zastosowanie) w clone()
       i clone3().

       CLONE_CHILD_CLEARTID (od Linuksa 2.5.49)
              Czyści (zeruje) identyfikator  wątku  potomnego  w  położeniu,  na  które  wskazuje
              child_tid (clone()) lub cl_args.child_tid (clone3()) w pamięci potomka, gdy potomek
              istnieje i wybudza zatrzask (mutex) pod tym adresem. Adres można zmienić wywołaniem
              systemowym set_tid_address(2). Używane przez biblioteki związane z wątkami.

       CLONE_CHILD_SETTID (od Linuksa 2.5.49)
              Przechowuje  identyfikator wątku potomnego w położeniu, na które wskazuje child_tid
              (clone()) lub cl_args.child_tid (clone3()) w pamięci potomka. Operacja przechowania
              kończy   się  przed  zwróceniem  kontroli  przez  wywołanie  clone  do  przestrzeni
              użytkownika w procesie potomnym (proszę zauważyć, że operacja przechowania może nie
              zakończyć  się przed powrotem przez wywołanie clone do procesu macierzystego, co ma
              znaczenie, jeśli używa się również znacznika CLONE_VM).

       CLONE_CLEAR_SIGHAND (od Linuksa 5.5)
              Domyślnie,  dyspozycje  sygnału  w  wątku  potomnym  są  takie  same  jak  w  wątku
              macierzystym.  Przy podaniu tego znacznika, wszystkie sygnały, które są obsługiwane
              przez wątek macierzysty (i  nie  ustawione  na  SIG_IGN)  są  resetowane  do  swych
              domyślnych dyspozycji (SIG_DFL) w potomku.

              Podanie tego znacznika razem z CLONE_SIGHAND jest bezsensowne i niedozwolone.

       CLONE_DETACHED (historyczny)
              Przez  pewien  czas  (w  trakcie  serii  rozwojowej  Linuksa  2.5) istniał znacznik
              CLONE_DETACHED,  który  powodował  nieotrzymywanie  przez  rodzica   sygnału   przy
              przerwaniu  potomka. Ostatecznie, efekt tego znacznika został włączony do znacznika
              CLONE_THREAD i  w  momencie  wydania  Linuksa  2.6.0,  znacznik  już  nie  działał.
              Począwszy  od Linuksa 2.6.2, potrzeba podawania tego znacznika razem z CLONE_THREAD
              zanikła.

              Znacznik jest wciąż zdefiniowany, lecz z reguły jest  ignorowany  przy  wywoływaniu
              clone(). Pewne wyjątki opisano przy znaczniku CLONE_PIDFD.

       CLONE_FILES (od Linuksa 2.0)
              Jeśli  CLONE_FILES  będzie  ustawione,  to  proces wywołujący i proces potomny będą
              współdzielić tablicę deskryptorów plików. Dowolny deskryptor pliku utworzony  przez
              proces wywołujący, jak też przez proces potomny będzie obowiązywać również w drugim
              procesie. Podobnie, jeśli jeden z procesów  zamknie  deskryptor  pliku  lub  zmieni
              stowarzyszone  z  nim  znaczniki  (za  pomocą operacji F_SETFD fcntl(2)), będzie to
              obowiązywać również w drugim procesie. Jeśli proces dzielący  tablicę  deskryptorów
              pliku  wywoła  execve(2),  to jego tablica deskryptorów pliku zostanie zduplikowana
              (przestanie być współdzielona).

              Jeśli CLONE_FILES nie zostanie  ustawione,  to  proces  potomny  odziedziczy  kopię
              wszystkich deskryptorów plików otwartych w procesie macierzystym w chwili wywołania
              klonowania.   Kolejne  operacja  otwierające  lub  zamykające   deskryptory   pliku
              przeprowadzone  później  przez  proces wywołujący lub przez proces potomny nie będą
              miały wpływu na drugi proces. Proszę jednak zauważyć, że  zduplikowane  deskryptory
              pliku   w  potomku  odnoszą  się  tych  samym  opisów  otwartego  pliku  (ODF)  jak
              odpowiadające im deskryptory pliku  w  procesie  wywołującym;  będą  zatem  dzielić
              przesunięcie pliku i znaczniki statusu pliku (zob. open(2)).

       CLONE_FS (od Linuksa 2.0)
              Jeśli  ustawione  będzie CLONE_FS, to wywołujący i proces potomny będą współdzielić
              informacje o systemie plików. Informacje te obejmują katalog główny systemu plików,
              bieżący  katalog  roboczy  i  umaskę.  Dowolne  z  wywołań  chroot(2), chdir(2) lub
              umask(2) wykonane przez proces wywołujący lub proces potomny będzie wpływać również
              na drugi proces.

              Jeśli  CLONE_FS  nie zostanie ustawione, to proces potomny będzie pracować na kopii
              informacji o systemie plików procesu wywołującego z  chwili  wywołania  klonowania.
              Wywołania  chroot(2), chdir(2) lub umask(2) wykonane później przez jeden z procesów
              nie będą mieć wpływu na drugi proces.

       CLONE_INTO_CGROUP (od Linuksa 5.7)
              Domyślnie, proces potomny jest umieszczany w tej samej grupie kontrolnej (cgroup) w
              wersji  2,  jak  rodzic.  Znacznik  CLONE_INTO_CGROUP pozwala na utworzenie procesu
              potomnego  w  innej  grupie  kontrolnej   w   wersji   2   (proszę   zauważyć,   że
              CLONE_INTO_CGROUP dotyczy tylko grup kontrolnych w wersji 2).

              Aby   umieścić  proces  potomny  w  innej  grupie  kontrolnej,  wywołujący  określa
              CLONE_INTO_CGROUP w cl_args.flags i przekazuje deskryptor pliku, który  odnosi  się
              do  grupy  kontrolnej  w wersji 2 w polu cl_args.cgroup (ten deskryptor pliku można
              uzyskać otwierając katalog grupy kontrolnej v2, za pomocą  znacznika  O_RDONLY  lub
              O_PATH).   Proszę   zauważyć,   że  obowiązują  wszystkie  zwykłe  ograniczenia  na
              umieszczanie procesu w grupie kontrolnej w wersji 2 (opisane w cgroups(7)).

              Pośród możliwych zastosowań CLONE_INTO_CGROUP są następujące:

              •  Utworzenie procesu w  grupie  kontrolnej  innej  niż  grupa  kontrolna  rodzica,
                 umożliwia  menedżerowi  usług  bezpośrednie tworzenie nowych usług w oddzielnych
                 grupach kontrolnych. Eliminuje  się  w  ten  sposób  narzut  księgowania,  który
                 spowodowany  byłby  tworzeniem  procesu  potomnego pierwotnie w tej samej grupie
                 kontrolnej co rodzic, a dopiero  później  przenoszenie  go  do  docelowej  grupy
                 kontrolnej.  Co  więcej,  tworzenie procesu potomnego od razu w docelowej grupie
                 kontrolnej jest zdecydowanie  tańsze,  niż  przenoszenie  procesu  potomnego  do
                 docelowej grupy kontrolnej dopiero po utworzeniu.

              •  Znacznik  CLONE_INTO_CGROUP  pozwala  również  na utworzenie zamrożonego procesu
                 potomnego, przez utworzenie go w zamrożonej grupie kontrolnej  (zob.  cgroups(7)
                 aby dowiedzieć się więcej o kontrolerze freezer).

              •  W  przypadku  aplikacji korzystających z wątków (lub choćby implementacji wątków
                 korzystających z grup kontrolnych do limitowania poszczególnych wątków), da  się
                 ustanowić  ustalony  schemat  grupy  kontrolnej, przed utworzeniem każdego wątku
                 bezpośrednio w jego docelowej grupie kontrolnej.

       CLONE_IO (od Linuksa 2.6.25)
              Jeśli CLONE_IO jest ustawiony, to nowy proces  dzieli  kontekst  wejścia/wyjścia  z
              procesem wywołującym. Jeśli znacznik nie jest ustawiony, to (jak przy fork(2)) nowy
              proces posiada swój kontekst wejścia/wyjścia.

              Kontekst wejścia/wyjścia (we/wy) jest zakresem we/wy planisty dysku  (tj.  tym,  co
              planista  we/wy  używa  do  planowania we/wy procesu). Jeśli procesy dzielą ten sam
              kontekst we/wy, to są traktowane jako jedność przez  planistę  we/wy.  Muszą  zatem
              dzielić  czas  dysku. W przypadku pewnych planistów we/wy, jeśli dwa procesy dzielą
              kontekst we/wy, to pozwala się im na przeplatanie dostępu  do  dysku.  Jeśli  wiele
              wątków  korzysta  z  we/wy  w  imieniu  jakiegoś  procesu (np. aio_read(3)), to aby
              uzyskać lepszą wydajność wejścia/wyjścia, powinny korzystać z CLONE_IO.

              Jeśli jądra nie skonfigurowano z opcją  CONFIG_BLOCK,  to  ten  znacznik  nie  daje
              żadnego efektu.

       CLONE_NEWCGROUP (od Linuksa 4.6)
              Tworzy  proces  w  nowej przestrzeni nazw cgroup. Jeśli znacznik nie jest ustawiony
              (jak w przypadku fork(2)), to proces jest tworzony w  tej  samej  przestrzeni  nazw
              cgroup, co proces wywołujący.

              Więcej   informacji  o  przestrzeniach  nazw  cgroup  znajduje  się  w  podręczniku
              cgroup_namespaces(7).

              Jedynie proces uprzywilejowany (CAP_SYS_ADMIN) może użyć CLONE_NEWCGROUP.

       CLONE_NEWIPC (od Linuksa 2.6.19)
              Jeśli CLONE_NEWIPC jest ustawiony, to proces jest tworzony w nowej przestrzeni nazw
              IPC.  Jeśli  znacznik  nie jest ustawiony (jak w przypadku fork(2)), to proces jest
              tworzony w tej samej przestrzeni nazw IPC, co proces wywołujący.

              Więcej  informacji  o  przestrzeniach  nazw  IPC   znajduje   się   w   podręczniku
              ipc_namespaces(7).

              Jedynie  proces  uprzywilejowany  (CAP_SYS_ADMIN) może użyć CLONE_NEWIPC. Niniejszy
              znacznik nie może być podany razem z CLONE_SYSVSEM.

       CLONE_NEWNET (od Linuksa 2.6.24)
              (Implementacja tej flagi została ukończona dopiero w okolicy Linuksa 2.6.29).

              Jest CLONE_NEWNET jest ustawiony, to proces jest tworzony w nowej przestrzeni  nazw
              sieci.  Jeśli znacznik nie jest ustawiony (jak w przypadku fork(2)), to proces jest
              tworzony w tej samej przestrzeni nazw sieci, co proces wywołujący.

              Więcej  informacji  o  przestrzeniach  nazw  sieci  znajduje  się   w   podręczniku
              network_namespaces(7).

              Jedynie proces uprzywilejowany (CAP_SYS_ADMIN) może użyć CLONE_NEWNET.

       CLONE_NEWNS (od Linuksa 2.4.19)
              Jeśli   ustawiono   CLONE_NEWNS,   sklonowany  potomek  jest  uruchamiany  w  nowej
              przestrzeni nazw montowań, inicjowanej jako kopia przestrzeni nazw  rodzica.  Jeśli
              nie  ustawiono  CLONE_NEWNS,  to  potomek  istnieje  w  tej  samej przestrzeni nazw
              montowań, co rodzic.

              Więcej informacji o przestrzeniach  nazw  montowań  znajduje  się  w  podręcznikach
              namespaces(7) i mount_namespaces(7).

              Znacznik  CLONE_NEWNS  może  zostać  użyty  jedynie  przez  proces  uprzywilejowany
              (CAP_SYS_ADMIN). Zabronione jest podanie w tym samym wywołaniu  klonowania  zarówno
              CLONE_NEWNS, jak i CLONE_FS.

       CLONE_NEWPID (od Linuksa 2.6.24)
              Jest  CLONE_NEWPID jest ustawiony, to proces jest tworzony w nowej przestrzeni nazw
              PID. Jeśli znacznik nie jest ustawiony (jak w przypadku fork(2)),  to  proces  jest
              tworzony w tej samej przestrzeni nazw PID, co proces wywołujący.

              Więcej   informacji   o  przestrzeniach  nazw  PID  znajduje  się  w  podręcznikach
              namespaces(7) i pid_namespaces(7).

              CLONE_NEWPID   może   zostać   użyty   jedynie   przez    proces    uprzywilejowany
              (CAP_SYS_ADMIN). Nie można podać tego znacznika razem z CLONE_THREAD.

       CLONE_NEWUSER
              (Flaga  ta  nabrała  znaczenia  dla  clone()  w  Linuksie 2.6.23, bieżąca semantyka
              clone()  pojawiła  się  w  Linuksie  3.5,  a   ostatnie   elementy   dające   pełną
              funkcjonalność przestrzeni nazw użytkownika ukończono w Linuksie 3.8).

              Jest CLONE_NEWUSER jest ustawiony, to proces jest tworzony w nowej przestrzeni nazw
              użytkownika. Jeśli znacznik nie jest ustawiony (jak w przypadku fork(2)), to proces
              jest tworzony w tej samej przestrzeni nazw użytkownika, co proces wywołujący.

              Więcej  informacji  o  przestrzeniach nazw użytkownika znajduje się w podręcznikach
              namespaces(7) i user_namespaces(7).

              Przed Linuksem 3.8, użycie CLONE_NEWUSER  wymagało  posiadania  trzech  przywilejów
              (ang.  capabilities) przez wywołującego: CAP_SYS_ADMIN, CAP_SETUID i CAP_SETGID. Od
              Linuksa 3.8, do utworzenia przestrzeni nazw użytkownika nie są wymagane przywileje.

              Znacznika tego nie można podać razem z CLONE_THREAD lub CLONE_PARENT.  Ze  względów
              bezpieczeństwa, CLONE_NEWUSER nie można podać razem z CLONE_FS.

       CLONE_NEWUTS (od Linuksa 2.6.19)
              Jest  CLONE_NEWUTS jest ustawiony, to proces jest tworzony w nowej przestrzeni nazw
              UTS, której identyfikatory są  inicjowane  przez  zduplikowanie  identyfikatorów  z
              przestrzeni nazw UTS procesu wywołującego. Jeśli znacznik nie jest ustawiony (jak w
              przypadku fork(2)), to proces jest tworzony w tej samej przestrzeni  nazw  UTS,  co
              proces wywołujący.

              Więcej   informacji   o   przestrzeniach   nazw  UTS  znajduje  się  w  podręczniku
              uts_namespaces(7).

              Jedynie proces uprzywilejowany (CAP_SYS_ADMIN) może użyć CLONE_NEWUTS.

       CLONE_PARENT (od Linuksa 2.3.12)
              Jeśli CLONE_PARENT będzie ustawione, to rodzic nowego procesu  potomnego  (zwrócony
              przez getppid(2)) będzie ten sam, co dla procesu wywołującego.

              Jeśli  CLONE_PARENT  nie  zostanie ustawione, to (jak dla fork(2)) rodzicem potomka
              będzie proces wywołujący.

              Należy zauważyć, że to proces  macierzysty,  zwracany  przez  getppid(2),  zostanie
              powiadomiony  o  zakończeniu  pracy  przez  potomka, więc jeśli CLONE_PARENT będzie
              ustawione, to zawiadomiony zostanie rodzic procesu wywołującego, a nie  sam  proces
              wywołujący.

              Znacznika  CLONE_PARENT  nie  można  użyć  w  wywołaniach klonowania przez globalny
              proces init (o PID 1 w pierwotnej przestrzeni nazw PID) oraz procesy init w  innych
              przestrzeniach nazw PID. To ograniczenie zapobiega tworzeniu zakorzenionych w wielu
              miejscach drzew procesów oraz  tworzeniu  zombie  w  pierwotnej  przestrzeni  nazw,
              których nie da się dorżnąć (unreapable).

       CLONE_PARENT_SETTID (od Linuksa 2.5.49)
              Przechowuje  identyfikator  wątku potomka w położeniu, na które wskazuje parent_tid
              (clone())  lub  cl_args.parent_tid  (clone3())  w  pamięci  rodzica   (w   Linuksie
              2.5.32-2.5.48  istniał  znacznik  CLONE_SETTID,  który  działał  w ten sam sposób).
              Operacja  przechowania  kończy  się,  przed  zwróceniem  kontroli  do   przestrzeni
              użytkownika przez wywołanie klonowania.

       CLONE_PID (od Linuksa 2.0 do Linuksa 2.5.15)
              Jeśli  CLONE_PID  jest  ustawiony,  to  proces  potomny  jest  tworzony z tym samym
              identyfikatorem jak proces wywołujący. Trudno wymyślić jego przydatne zastosowanie,
              poza  hakowaniem  systemu.  Od  Linuksa  2.3.21, ten znacznik mógł być podany tylko
              przez systemowy proces rozruchu (PID 0). Znacznik zupełnie zniknął ze źródeł  jądra
              w  Linuksie  2.5.16.  Następnie jądro po cichu ignorowało ten bit, gdy był podany w
              masce flags. Znacznie później, ten sam bit użyto do znacznika CLONE_PIDFD.

       CLONE_PIDFD (od Linuksa 5.2)
              Jeśli znacznik jest podany, to deskryptor pliku  PID  odnoszącego  się  do  procesu
              potomnego  jest  alokowany i umieszczany w określonym położeniu pamięci rodzica. Na
              tym  nowym  deskryptorze  pliku  ustawiany  jest  znacznik  zamknij-przy-wykonaniu.
              Deskryptory   pliku   PID  można  wykorzystać  w  celach  opisanych  w  podręczniku
              pidfd_open(2).

              •  Jeśli korzysta się z clone3(),  to  deskryptor  pliku  PID  jest  umieszczany  w
                 położeniu, na które wskazuje cl_args.pidfd.

              •  Jeśli  korzysta  się  z  clone(),  to  deskryptor  pliku  PID jest umieszczany w
                 położeniu, na które  wskazuje  parent_tid.  Ponieważ  argument  parent_tid  jest
                 używany  do  zwrócenia deskryptora pliku PID, nie można użyć CLONE_PIDFD razem z
                 CLONE_PARENT_SETTID przy wywoływaniu clone().

              Nie da się obecnie korzystać z tego znacznika razem z CLONE_THREAD. Oznacza to,  że
              proces  identyfikowany  przez  deskryptor  pliku  PID  będzie  zawsze liderem grupy
              wątków.

              Jeśli przestarzały znacznik  CLONE_DETACHED  poda  się  razem  z  CLONE_PIDFD  przy
              wywoływaniu  clone(),  to zwracany jest błąd. Błąd występuje również jeśli poda się
              CLONE_DETACHED  przy  wywoływaniu  clone3().  Zwracanie  błędu  zapewnia,  że   bit
              odnoszący się do CLONE_DETACHED może być w przyszłości użyty ponownie do następnych
              funkcji deskryptora pliku PID.

       CLONE_PTRACE (od Linuksa 2.2)
              Jeśli zostanie  podane  CLONE_PTRACE,  a  proces  wywołujący  będzie  śledzony,  to
              śledzenie obejmie również potomka (zobacz ptrace(2)).

       CLONE_SETTLS (od Linuksa 2.5.32)
              Deskryptor TLS (Thread Local Storage — pamięć lokalna wątku) jest ustawiony na tls.

              Interpretacja  tls  i  jego  skutek  zależy  od  architektury.  Na  x86,  tls  jest
              interpretowane jako struct user_desc * (zob. set_thread_area(2)). Na x86-64 jest to
              nowa  wartość,  jaka  ma  być  ustawiona  w  bazowym  rejestrze  %fs (zob. argument
              ARCH_SET_FS do arch_prctl(2)). Na architekturach ze specjalnym rejestrem TLS,  jest
              to nowa wartość tego rejestru.

              Znacznik  ten  wymaga  szczegółowej  wiedzy i zwykle nie powinno się go używać poza
              bibliotekami implementującymi wątkowanie.

       CLONE_SIGHAND (od Linuksa 2.0)
              Jeśli CLONE_SIGHAND będzie ustawione, to proces wywołujący i procesy  potomne  będą
              współdzielić tablicę programów obsługi sygnałów. Jeśli proces wywołujący lub proces
              potomny  wywoła  sigaction(2),  aby  zmienić  zachowanie  towarzyszące   sygnałowi,
              zachowanie  to  zostanie  zmienione  również  w  drugim  procesie. Jednakże, proces
              wywołujący i proces potomny wciąż będą posiadać osobne  maski  sygnałów  i  zestawy
              sygnałów  oczekujących.  Zatem jeden z nich może zablokować lub odblokować niektóre
              sygnały za pomocą sigprocmask(2) nie wpływając na drugi proces.

              Jeśli CLONE_SIGHAND nie zostanie ustawione, to  proces  potomny  odziedziczy  kopię
              programów  obsługi  sygnałów od procesu wywołującego z chwili wywołania klonowania.
              Wywołania sigaction(2) przeprowadzone później przez jeden z procesów nie będą  mieć
              wpływu na drugi proces.

              Od  Linuksa  2.6.0,  maska  flags  musi  również  zawierać  CLONE_VM,  jeśli podano
              CLONE_SIGHAND.

       CLONE_STOPPED (od Linuksa 2.6.0)
              Jeśli CLONE_STOPPED jest ustawione, to potomek jest  początkowo  zatrzymany  (jakby
              otrzymał sygnał SIGSTOP) i musi być wznowiony sygnałem SIGCONT.

              Znacznik  był  oznaczony  jako  przestarzały  od  Linuksa  2.6.25 i został zupełnie
              usunięty w Linuksie 2.6.38. Od tego czasu jądro po cichu ignoruje go, nie wypisując
              błędu. Od Linuksa 4.6, ten sam bit służy znacznikowi CLONE_NEWCGROUP.

       CLONE_SYSVSEM (od Linuksa 2.5.10)
              Jeśli  ustawiony  jest  CLONE_SYSVSEM  to  potomek i proces wywołujący dzielą jedną
              listę wartości dostosowań semaforów  Systemu  V  (semadj;  zob.  semop(2)).  W  tym
              przypadku  wspólna  lista  zbiera wartości semadj ze wszystkich procesów dzielących
              listę, a dostosowania semaforów są wykonywane tylko  gdy  ostatni  proces  dzielący
              listę  zostanie  zakończony  (lub  przestanie dzielić listę, za pomocą unshare(2)).
              Jeśli znacznik ten nie jest ustawiony, to potomek posiada oddzielną  listę  semadj,
              która początkowo jest pusta.

       CLONE_THREAD (od Linuksa 2.4.0)
              Jeśli  ustawiony  jest  CLONE_THREAD to potomek jest umieszczany w tej samej grupie
              wątków, co proces wywołujący. Aby dalsza część  opisu  CLONE_THREAD  była  bardziej
              przejrzysta, termin „wątek” oznaczać będzie tu procesy w grupie wątków.

              Grupy  wątków  zostały  dodane  w  Linuksie  2.4 do obsługi wątków POSIX dla zbioru
              procesów współdzielących ten sam  PID.  Wewnętrznie,  ten  wspólny  PID  jest  tzw.
              identyfikatorem  grupy  wątków  (ang.  thread group ID — TGID) dla grupy wątków. Od
              Linuksa 2.4 wywołania getpid(2) zwracają TGID wywołującego.

              Wątki wewnątrz grupy  można  rozróżnić  za  pomocą  ich  unikatowego  (w  systemie)
              identyfikatora  wątku  (ang.  thread ID — TID). TID nowego wątku jest dostępny jako
              wynik funkcji zwracany do wywołującego, a sam wątek może uzyskać swój TID za pomocą
              gettid(2).

              Gdy  wywołanie  clone  ma  miejsce bez podania CLONE_THREAD, to wynikowy wątek jest
              umieszczany w nowej grupie wątków, której TGID jest taki sam jak TID  wątku.  Wątek
              ten staje się liderem nowej grupy wątków.

              Nowy  wątek  utworzony  przy podaniu CLONE_THREAD ma ten sam proces macierzysty jak
              proces, który  wykonał  wywołanie  klonowania  (tj.  jak  CLONE_PARENT),  tak  więc
              wywołanie  getppid(2) zwróci tę samą wartość dla wszystkich wątków w grupie wątków.
              Gdy wątek z CLONE_THREAD zostanie zakończony, wątek który go utworzył nie otrzymuje
              sygnału  SIGCHLD  (ani innego sygnału przerwania); statusu takiego wątku nie da się
              również pozyskać za pomocą wait(2) (taki wątek jest  nazywany  oddzielonym  —  ang.
              detached).

              Po  tym, jak wszystkie wątki w grupie wątków zakończą się, proces macierzysty grupy
              wątków otrzymuje sygnał SIGCHLD (lub inny sygnał przerwania).

              Jeśli któryś z wątków w grupie wątków wykona execve(2),  to  wszystkie  wątki  poza
              liderem  grupy  wątków  są  zakańczane  i nowy program wykonywany jest przez lidera
              grupy wątków.

              Jeśli jeden z wątków w grupie wątków tworzy potomka za  pomocą  fork(2),  to  każdy
              wątek w grupie może czekać (wait(2)) na tego potomka.

              Od  Linuksa  2.5.35,  maska  flags musi zawierać również CLONE_SIGHAND jeśli podano
              CLONE_THREAD (i proszę zauważyć, że od Linuksa 2.6.0, CLONE_SIGHAND wymaga  również
              zamieszczenia CLONE_VM).

              Akcje  i  dyspozycje  sygnałów  mają  znaczenie  dla całego procesu: jeśli do wątku
              dostarczony zostanie  nieobsłużony  sygnał,  to  dotknie  on  (przerwie,  zatrzyma,
              wznowi, ustawi ignorowanie) wszystkich członków grupy wątków.

              Każdy wątek ma swoją maskę sygnałów, jak ustawianą przez sigprocmask(2).

              Sygnał  może  być  kierowany do procesu lub kierowany do wątku. Sygnał kierowany do
              procesu jest przeznaczony do grupy wątku (tj. TGID) i jest dostarczany do  dowolnie
              wybranego  wątku spośród tych, które nie blokują sygnału. Sygnał może być kierowany
              do procesu, ponieważ został wygenerowany przez jądro z powodów innych  niż  wyjątek
              sprzętowy,  albo  ponieważ został wysłany za pomocą kill(2) lub sigqueue(3). Sygnał
              kierowany do wątku jest przeznaczony (tj. dostarczany) do określonego wątku. Sygnał
              może  być  kierowany  do  wątku,  ponieważ  został  wysłany za pomocą tgkill(2) lub
              pthread_sigqueue(3), albo ponieważ wątek  wykonał  instrukcję  języka  maszynowego,
              która  wyzwoliła wyjątek sprzętowy (np. nieprawidłowy dostęp do pamięci wyzwalający
              SIGSEGV lub wyjątek zmiennoprzecinkowy wyzwalający SIGFPE).

              Wywołanie do sigpending(2) zwraca sygnał, który jest ustawiany na sumę oczekującego
              sygnału  skierowanego  do  procesu  oraz  sygnałów  które  są  oczekujące dla wątku
              wywołującego.

              Jeśli sygnał kierowany do procesu zostanie dostarczony do grupy wątków, a grupa  ta
              ma  zainstalowaną  procedurę  obsługi  sygnału,  to jest ona wywoływana w dokładnie
              jednym, dowolnie wybranym członku grupy wątków, który nie zablokował sygnału. Jeśli
              na zaakceptowanie tego samego sygnału za pomocą sigwaitinfo(2) czeka wiele wątków w
              grupie, to jądro wybierze w sposób dowolny jeden z wątków, który otrzyma sygnał.

       CLONE_UNTRACED (od Linuksa 2.5.46)
              Jeśli podano CLONE_UNTRACED, to proces śledzący nie może  wymusić  CLONE_PTRACE  na
              tym procesie potomnym.

       CLONE_VFORK (od Linuksa 2.2)
              Jeśli  CLONE_VFORK  będzie  ustawione,  wykonywanie  procesu  wywołującego zostanie
              wstrzymane do chwili, gdy potomek zwolni swoją pamięć wirtualną za pomocą execve(2)
              lub _exit(2) (jak w przypadku vfork(2)).

              Jeśli  CLONE_VFORK  nie  zostanie ustawione, wtedy zarówno proces wywołujący, jak i
              potomny podlegają po wywołaniu  clone  szeregowaniu  zadań  i  aplikacja  nie  może
              zakładać, że ich wykonywanie będzie się odbywać w określonej kolejności.

       CLONE_VM (od Linuksa 2.0)
              Jeśli  CLONE_VM będzie ustawione, to proces wywołujący i potomny będą działać w tym
              samym obszarze pamięci. W szczególności, zapisy do pamięci wykonywane przez  proces
              wywołujący lub przez proces potomny będą widoczne dla drugiego z procesów. Ponadto,
              dowolne mapowania pamięci i usunięcia mapowań wykonane przez jeden z tych  procesów
              za pomocą mmap(2) lub munmap(2) będą dotyczyć również drugiego procesu.

              Jeśli  CLONE_VM  nie  zostanie  ustawione, to proces potomny będzie działać w kopii
              obszaru pamięci procesu wywołującego,  wykonanej  w  chwili  wywołania  klonowania.
              Zapisy  do  pamięci  oraz mapowania i usunięcia mapowań wykonane przez jeden z tych
              procesów nie będą dotyczyć drugiego z nich, tak jak w przypadku fork(2).

              Jeśli podano znacznik CLONE_VM, a nie podano  znacznika  CLONE_VFORK  to  wszystkie
              alternatywne  stosy  sygnałów  ustanowione  przez  sigaltstack(2)  są  czyszczone w
              procesie potomnym.

WARTOŚĆ ZWRACANA

       Po pomyślnym zakończeniu, w wątku rodzica zwracany jest  identyfikator  wątku  potomka.  W
       wypadku  błędu,  w  kontekście procesu wywołującego zwracane jest -1, a proces potomny nie
       jest tworzony i ustawiane jest errno wskazując błąd.

BŁĘDY

       EACCES (tylko clone3())
              W cl_args.flags podano CLONE_INTO_CGROUP, nie  spełniono  ograniczeń  (opisanych  w
              cgroups(7)),  w  odniesieniu  do  cl_args.cgroup,  dotyczących umieszczania procesu
              potomnego w grupie kontrolnej w wersji 2.

       EAGAIN Działa już zbyt wiele procesów; zob. fork(2).

       EBUSY (tylko clone3())
              W  cl_args.flags  podano  CLONE_INTO_CGROUP,  lecz  deskryptor   pliku   podany   w
              cl_args.cgroup  odnosi  się  do grupy kontrolnej w wersji 2, w której włączony jest
              kontroler domeny.

       EEXIST (tylko clone3())
              Jeden (lub więcej) PID podany w set_tid już  istnieje  w  odpowiedniej  przestrzeni
              nazw PID.

       EINVAL W masce flags podano jednocześnie CLONE_SIGHAND i CLONE_CLEAR_SIGHAND.

       EINVAL W masce flags podano CLONE_SIGHAND, lecz nie podano CLONE_VM (od Linuksa 2.6.0).

       EINVAL W  masce  flags  podano  CLONE_THREAD,  lecz  nie  podano CLONE_SIGHAND (od Linuksa
              2.5.35).

       EINVAL W masce flags podano CLONE_THREAD, lecz bieżący proces użył uprzednio unshare(2) ze
              znacznikiem   CLONE_NEWPID   lub   użył  setns(2)  do  ponownego  związania  się  z
              przestrzenią nazw PID.

       EINVAL W masce flags podano jednocześnie CLONE_FS i CLONE_NEWNS.

       EINVAL (od Linuksa 3.9)
              W masce flags podano jednocześnie CLONE_NEWUSER i CLONE_FS.

       EINVAL W masce flags podano jednocześnie CLONE_NEWIPC i CLONE_SYSVSEM.

       EINVAL W masce flags podano jednocześnie CLONE_FS i CLONE_NEWNS.

       EINVAL W masce flags podano jednocześnie CLONE_FS i CLONE_NEWNS.

       EINVAL (od Linuksa 2.6.32)
              Podano CLONE_PARENT, a wywołujący jest procesem init.

       EINVAL Zwracane przez funkcję opakowującą clone() z glibc, gdy fn lub stack określono jako
              NULL.

       EINVAL W  masce flags podano CLONE_NEWIPC, lecz jądro nie zostało skonfigurowane z opcjami
              CONFIG_SYSVIPC i CONFIG_IPC_NS.

       EINVAL W masce flags podano CLONE_NEWNET, lecz jądro nie zostało  skonfigurowane  z  opcją
              CONFIG_NET_NS.

       EINVAL W  masce  flags  podano CLONE_NEWPID, lecz jądro nie zostało skonfigurowane z opcją
              CONFIG_PID_NS.

       EINVAL W masce flags podano CLONE_NEWUSER, lecz jądro nie zostało skonfigurowane  z  opcją
              CONFIG_USER_NS.

       EINVAL W  masce  flags  podano CLONE_NEWUTS, lecz jądro nie zostało skonfigurowane z opcją
              CONFIG_UTS_NS.

       EINVAL Stos stack nie  jest  wyrównany  do  odpowiedniej  granicy  na  tej  architekturze.
              Przykładowo na aarch64, stack musi być wielokrotnością 16.

       EINVAL (tylko clone3())
              W masce flags podano CLONE_DETACHED.

       EINVAL (tylko clone())
              W masce flags podano CLONE_PIDFD jednocześnie z CLONE_DETACHED.

       EINVAL W masce flags podano CLONE_PIDFD jednocześnie z CLONE_THREAD.

       EINVAL (tylko clone())
              W masce flags podano CLONE_PIDFD jednocześnie z CLONE_PARENT_SETTID.

       EINVAL (tylko clone3())
              set_tid_size jest większy od liczby zagnieżdżonych przestrzeni nazw PID.

       EINVAL (tylko clone3())
              Jeden z PID-ów podanych w set_tid był nieprawidłowy.

       EINVAL (tylko clone3())
              W  masce  flags  podano CLONE_THREAD lub CLONE_PARENT, lecz w exit_signal określono
              sygnał.

       EINVAL (tylko AArch64, Linux 4.6 i wcześniejsze)
              stack nie był wyrównany do granicy 128-bitów.

       ENOMEM Za mało pamięci aby przydzielić strukturę zadania dla procesu  potomnego,  lub  aby
              skopiować niezbędne fragmenty kontekstu procesu wywołującego.

       ENOSPC (od Linuksa 3.7)
              W  masce  flags podano CLONE_NEWPID, lecz zostałby przekroczony limit zagnieżdżenia
              przestrzeni nazw PID; zob. pid_namespaces(7).

       ENOSPC (od Linuksa 4.9; wcześniej EUSERS)
              W masce  flags  podano  CLONE_NEWUSER,  a  wywołanie  przekroczyłoby  limit  liczby
              zagnieżdżonych przestrzeni nazw użytkownika. Zob. user_namespaces(7).

              Od Linuksa 3.11 do Linuksa 4.8, diagnozowanym w tym przypadku błędem był EUSERS.

       ENOSPC (od Linuksa 4.9)
              Jedna  z  wartości  w  masce  flags  określiła  utworzenie  nowej  przestrzeni nazw
              użytkownika,   lecz   uczynienie   tego,   spowodowałoby    przekroczenie    limitu
              zdefiniowanego  przez  odpowiedni plik w /proc/sys/user. Więcej informacji znajduje
              się w podręczniku namespaces(7).

       EOPNOTSUPP (tylko clone3())
              W  cl_args.flags  podano  CLONE_INTO_CGROUP,  lecz  deskryptor   pliku   podany   w
              cl_args.cgroup  odnosi  się  do  grupy  kontrolnej  w wersji 2, która jest w stanie
              domain invalid.

       EPERM  CLONE_NEWCGROUP,  CLONE_NEWIPC,   CLONE_NEWNET,   CLONE_NEWNS,   CLONE_NEWPID   lub
              CLONE_NEWUTS  były określone przez proces nieuprzywilejowany (proces bez przywileju
              CAP_SYS_ADMIN).

       EPERM  CLONE_PID został podany przez proces inny niż proces 0 (błąd ten występował jedynie
              do Linuksa 2.5.15).

       EPERM  W  masce  flags podano CLONE_NEWUSER, lecz ani efektywny identyfikator użytkownika,
              ani efektywny identyfikator grupy wywołującego nie jest przypisany  do  przestrzeni
              nazw rodzica (zob. user_namespaces(7)).

       EPERM (od Linuksa 3.9)
              W  masce  flags podano CLONE_NEWUSER, a wywołujący znajduje się w środowisku chroot
              (tj. główny katalog wywołującego  nie  jest  głównym  katalogiem  przestrzeni  nazw
              montowań, w której rezyduje).

       EPERM (tylko clone3())
              set_tid_size  był  większy niż zero, a wywołujący nie ma przywileju CAP_SYS_ADMIN w
              jednej  lub  większej  liczbie  przestrzeni  nazw  użytkownika,   które   posiadają
              odpowiednie przestrzenie nazw PID.

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

       EUSERS (od Linuksa 3.11 do Linuksa 4.8)
              W masce flags podano CLONE_NEWUSER, a przekroczono by limit  liczby  zagnieżdżonych
              przestrzeni nazw użytkownika. Zob. opis błędu ENOSPC powyżej.

WERSJE

       Funkcja  opakowująca  clone()  z  biblioteki  glibc czyni pewne zmiany w pamięci, na którą
       wskazuje stack (zmiany wymagane do prawidłowego ustawienia stosu w  stosunku  do  potomka)
       przed przywołaniem wywołania systemowego clone(). Dlatego, w przypadkach gdy clone() służy
       do rekurencyjnego tworzenia potomków, nie należy używać  bufora  w  stosie  rodzica,  jako
       stosu potomka.

       Na  i386,  nie  należy  wywoływać  clone()  za  pomocą  vsyscall;  powinno  się  to  robić
       bezpośrednio, poprzez int $0x80.

   Różnice biblioteki C/jądra
       Surowe wywołanie systemowe clone() jest bliższe  fork(2)  w  tym  zakresie,  że  wykonanie
       procesu  potomnego  jest  kontynuowane  od  miejsca  wywołania. Dlatego argumenty fn i arg
       funkcji opakowującej clone() są pominięte.

       W odróżnienie od opakowania z glibc, surowe  wywołanie  systemowe  clone()  jako  argument
       stack  akceptuje  NULL  (a  clone3() podobnie pozwala, aby cl_args.stack wynosiło NULL). W
       takim przypadku, potomek używa duplikatu stosu  rodzica  (jest  to  dokonywane  za  pomocą
       kopiowania-przy-zapisie,  co  zapewnia,  że potomek otrzyma odrębne kopie stron stosu, gdy
       jeden z procesów zmodyfikuje stos). W tym przypadku, aby zapewnić poprawne działanie,  nie
       powinno się podawać opcji CLONE_VM (jeśli potomek współdzieli pamięć z rodzicem ze względu
       na  znacznik  CLONE_VM,  to  nie  zachodzi  duplikacja  z   kopiowaniem-przy-zapisie,   co
       prawdopodobnie doprowadzi do chaotycznych rezultatów).

       Kolejność  argumentów  również  różni  się w surowym wywołaniu systemowym, występuje także
       zmienność argumentów w zależności od architektury, zgodnie z poniższym opisem.

       Interfejsem surowego wywołania systemowego na x86-64 i niektórych innych architekturach (w
       tym sh, tile i alpha) jest:

           long clone(unsigned long flags, void *stack,
                      int *parent_tid, int *child_tid,
                      unsigned long tls);

       Na  x86-32  i  wielu innych popularnych architekturach (w tym score, ARM, ARM 64, PA-RISC,
       arc, Power PC, xtensa i MIPS), kolejność dwóch ostatnich argumentów jest zamieniona:

           long clone(unsigned long flags, void *stack,
                     int *parent_tid, unsigned long tls,
                     int *child_tid);

       Na architekturach cris i s390, kolejność pierwszych dwóch argumentów jest zamieniona:

           long clone(void *stack, unsigned long flags,
                      int *parent_tid, int *child_tid,
                      unsigned long tls);

       Na architekturze microblaze występuje dodatkowy argument:

           long clone(unsigned long flags, void *stack,
                      int stack_size,         /* Rozmiar stosu */
                      int *parent_tid, int *child_tid,
                      unsigned long tls);

   blackfin, m68k i sparc
       Konwencje przekazywania argumentów na blackfin, m68k i sparc  są  odmienne  od  powyższych
       opisów. Więcej szczegółów w źródle jądra (i glibc).

   ia64
       Na ia64 używany jest inny interfejs:

           int __clone2(int (*fn)(void *),
                        void *stack_base, size_t stack_size,
                        int flags, void *arg, ...
                     /* pid_t *parent_tid, struct user_desc *tls,
                        pid_t *child_tid */ );

       Powyższy  prototyp  jest  do  funkcji  opakowującej z glibc; jeśli chodzi o samo wywołanie
       systemowe, jego prototyp może  być  opisany  w  sposób  następujący  (jest  identyczny  do
       prototypu clone() na microblaze):

           long clone2(unsigned long flags, void *stack_base,
                       int stack_size,         /* Rozmiar stosu */
                       int *parent_tid, int *child_tid,
                       unsigned long tls);

       __clone2()  działa  w ten sam sposób co clone() z tym wyjątkiem, że stack_base wskazuje na
       najniższy adres przestrzeni stosu potomka, a stack_size określa rozmiar  stosu,  na  który
       wskazuje stack_base.

STANDARDY

       Linux.

HISTORIA

       clone3()
              Linux 5.3.

   Linux 2.4 i wcześniejsze
       W  serii  Linuksa  2.4.x,  CLONE_THREAD  zwykle  nie czyniło rodzicem nowego wątku rodzica
       procesu wywołującego. Jednak od Linuksa 2.4.7  do  Linuksa  2.4.18  znacznik  CLONE_THREAD
       implikował znacznik CLONE_PARENT (jak ma to miejsce od Linuksa 2.6.0).

       W  Linuksie  2.4  i  wcześniejszych clone() nie przyjmowało argumentów parent_tid, tls ani
       child_tid.

UWAGI

       Jednym z zastosowań  tych  wywołań  systemowych  jest  implementacja  wątków:  zarządzanie
       wieloma  przepływami  kontroli  w  programie,  które działają równolegle we współdzielonej
       przestrzeni adresowej.

       Wywołanie systemowe kcmp(2) może posłużyć do  sprawdzenia,  czy  dwa  procesy  współdzielą
       różne  zasoby,  takie jak tablica deskryptorów pliku, operacje cofnięć semaforów Systemu V
       lub wirtualną przestrzeń adresową.

       Uchwyty zarejestrowane przy pomocy pthread_atfork(3)  nie  są  wykonywane  przy  wywołaniu
       klonowania.

USTERKI

       Biblioteka  GNU  C  w  wersjach  od  2.3.4 do 2.24 włącznie, zawierała funkcję opakowującą
       getpid(2), która przeprowadzała buforowanie PID-ów. To  buforowanie  zależało  od  obsługi
       opakowania  clone()  z  glibc,  jednak  ograniczenia  w  implementacji  powodowały,  że  w
       niektórych przypadkach bufor ten nie był  aktualny.  W  szczególności,  jeśli  do  potomka
       dostarczano  sygnał  od  razu  po  wywołaniu  clone(), to wywołanie getpid(2) w procedurze
       obsługi sygnału mogło zwrócić PID procesu wywołującego („rodzica”), jeśli opakowanie clone
       nie miało jeszcze szansy zaktualizowania bufora PID w potomku (ten opis ignoruje sytuację,
       gdy potomka utworzono za pomocą CLONE_THREAD; wówczas getpid(2) powinno  zwracać  tę  samą
       wartość  w  potomku  jak  w  procesie  wywołującym  clone(), ponieważ wywołujący i potomek
       znajdują się w tej  samej  grupie  wątków.  Problem  nieaktualnego  bufora  nie  występuje
       również, gdy argument flags zawiera CLONE_VM). Do dotarcia do prawdziwego PID, trzeba było
       czasem użyć kodu takiego jak poniższy:

           #include <syscall.h>

           pid_t mypid;

           mypid = syscall(SYS_getpid);

       Ze względu na  kłopot  z  nieaktualnym  buforem  i  inne  problemy  opisane  w  getpid(2),
       funkcjonalność buforowania PID-ów usunięto w glibc 2.25.

PRZYKŁADY

       Poniższy  program  demonstruje  użycie  clone()  do  utworzenia  procesu  potomnego, który
       wykonuje się w oddzielnej przestrzeni nazw UTS. Potomek  zmienia  nazwę  stacji  w  swojej
       przestrzeni nazw UTS. Rodzic i potomek wyświetlają następnie systemową nazwę stacji, przez
       co widać, że różni się ona w przestrzeniach nazw UTS rodzica i  potomka.  Przykład  użycia
       tego programu znajduje się w podręczniku setns(2).

       W  programie  przykładowym  pamięć,  która  ma być użyta do stosu potomka, przydzielamy za
       pomocą mmap(2), zamiast malloc(3), z następujących powodów:

       •  mmap(2)  przydziela  blok  pamięci  zaczynający  się  na  granicy   strony   i   będący
          wielokrotnością  rozmiaru  strony.  Przydaje  się to, gdy chcemy ustawić ochronę strony
          (stronę z ochroną PROT_NONE) na końcu stosu, za pomocą mprotect(2).

       •  Możemy podać znacznik MAP_STACK, aby  zażądać  mapowania,  które  jest  odpowiednie  do
          stosu.  W tej chwili znacznik ten nie daje efektu na Linuksie, ale istnieje i działa na
          niektórych innych systemach, dlatego należy go podać ze względu na przenośność.

   Kod źródłowy programu
       #define _GNU_SOURCE
       #include <err.h>
       #include <sched.h>
       #include <signal.h>
       #include <stdint.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <string.h>
       #include <sys/mman.h>
       #include <sys/types.h>
       #include <sys/utsname.h>
       #include <sys/wait.h>
       #include <unistd.h>

       static int              /* Początek funkcje klonowanego potomka */
       childFunc(void *arg)
       {
           struct utsname uts;

           /* Zmiana nazwy stacji w przestrzeni nazw UTS potomka. */

           if (sethostname(arg, strlen(arg)) == -1)
               err(EXIT_FAILURE, "sethostname");

           /* Pobranie i wyświetlenie nazwy stacji. */

           if (uname(&uts) == -1)
               err(EXIT_FAILURE, "uname");
           printf("uts.nodename u potomka:  %s\n", uts.nodename);

           /* Utrzymuje przestrzeń nazw otwartą przez chwilę, śpiąc.
              Daje to pole do eksperymentów - do przestrzeni nazw
              może np. dołączyć inny proces. */

           sleep(200);

           return 0;           /* Potomek ulega zakończeniu */
       }

       #define STACK_SIZE (1024 * 1024)    /* Rozmiar stosu klon. potomka */

       int
       main(int argc, char *argv[])
       {
           char            *stack;         /* Początek bufora stosu */
           char            *stackTop;      /* Koniec bufora stosu */
           pid_t           pid;
           struct utsname  uts;

           if (argc < 2) {
               fprintf(stderr, "Użycie: %s <child-hostname>\n", argv[0]);
               exit(EXIT_SUCCESS);
           }

           /* Przydzielenie pamięci na stos potomka. */

           stack = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE,
                        MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
           if (stack == MAP_FAILED)
               err(EXIT_FAILURE, "mmap");

           stackTop = stack + STACK_SIZE;  /* Założenie: stos rośnie w dół */

           /* Utworzenie potomka z własną przestrzenią nazw UTS;
              potomek rozpoczyna wykonanie w childFunc(). */

           pid = clone(childFunc, stackTop, CLONE_NEWUTS | SIGCHLD, argv[1]);
           if (pid == -1)
               err(EXIT_FAILURE, "clone");
           printf("clone() zwróciło %jd\n", (intmax_t) pid);

           /* Rodzic przechodzi tutaj */

           sleep(1);           /* Czas na zmianę nazwy stacji przez potomka */

           /* Wyświetla nazwę stacji w przestrzeni nazw UTS rodzica. Będzie
              inna, od nazwy stacji w przestrzeni nazw UTS potomka. */

           if (uname(&uts) == -1)
               err(EXIT_FAILURE, "uname");
           printf("uts.nodename u rodzica: %s\n", uts.nodename);

           if (waitpid(pid, NULL, 0) == -1)    /* Czekanie na potomka */
               err(EXIT_FAILURE, "waitpid");
           printf("potomek zakończył działanie\n");

           exit(EXIT_SUCCESS);
       }

ZOBACZ TAKŻE

       fork(2),   futex(2),    getpid(2),    gettid(2),    kcmp(2),    mmap(2),    pidfd_open(2),
       set_thread_area(2),   set_tid_address(2),   setns(2),   tkill(2),   unshare(2),   wait(2),
       capabilities(7), namespaces(7), pthreads(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⟩.