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   lub  nowszej.  Nie  przyjmuje  się  ŻADNEJ
       ODPOWIEDZIALNOŚCI.

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

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