plucky (2) clone.2.gz

Provided by: manpages-pl-dev_4.25.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⟩.