Scroll to navigation

pid_namespaces(7) Miscellaneous Information Manual pid_namespaces(7)

NUME

pid_namespaces - vedere de ansamblu a spațiilor de nume PID Linux

DESCRIERE

Pentru o descriere generală a spațiilor de nume, consultați namespaces(7).

Spațiile de nume PID izolează spațiul numerelor ID ale proceselor, ceea ce înseamnă că procesele din diferite spații de nume PID pot avea același PID. Spațiile de nume PID permit containerelor să ofere funcționalități precum suspendarea/reluarea setului de procese din container și migrarea containerului către o nouă gazdă, în timp ce procesele din container păstrează aceleași PID-uri.

PID-urile dintr-un nou spațiu de nume PID încep de la 1, oarecum ca într-un sistem autonom, iar apelurile la fork(2), vfork(2) sau clone(2) vor produce procese cu PID-uri unice în spațiul de nume.

Utilizarea spațiilor de nume PID necesită un nucleu care este configurat cu opțiunea CONFIG_PID_NS.

Procesul de inițiere (init) a spațiului de nume

Primul proces creat într-un spațiu de nume nou (de exemplu, procesul creat folosind clone(2) cu fanionul CLONE_NEWPID sau primul copil creat de un proces după un apel la unshare(2) folosind fanionul CLONE_NEWPID) are PID-ul 1 și este procesul „init” pentru spațiul de nume (a se vedea init(1)). Acest proces devine părintele oricărui proces copil rămas orfan din cauza încetării unui proces care se află în acest spațiu de nume PID (a se vedea mai jos pentru detalii suplimentare).

Dacă procesul „init” al unui spațiu de nume PID se încheie, nucleul încheie toate procesele din spațiul de nume prin intermediul unui semnal SIGKILL. Acest comportament reflectă faptul că procesul „init” este esențial pentru funcționarea corectă a unui spațiu de nume PID. În acest caz, un fork(2) ulterior în acest spațiu de nume PID eșuează cu eroarea ENOMEM; nu este posibilă crearea unui proces nou într-un spațiu de nume PID al cărui proces „init” s-a încheiat. Astfel de scenarii pot apărea atunci când, de exemplu, un proces utilizează un descriptor de fișier deschis pentru un fișier /proc/pid/ns/pid corespunzător unui proces care se afla într-un spațiu de nume pentru a setns(2) în acel spațiu de nume după ce procesul „init” s-a încheiat. Un alt scenariu posibil poate apărea după un apel la unshare(2): dacă primul copil creat ulterior de un fork(2) se termină, atunci apelurile ulterioare la fork(2) eșuează cu ENOMEM.

Doar semnalele pentru care procesul „init” a stabilit un gestionar de semnale pot fi trimise procesului „init” de către alți membri ai spațiului de nume PID. Această restricție se aplică chiar și proceselor privilegiate și previne omorârea accidentală a procesului „init” de către alți membri ai spațiului de nume PID.

De asemenea, un proces dintr-un spațiu de nume antecesor poate trimite semnale către procesul „init” al unui spațiu de nume PID copil numai dacă procesul „init” a stabilit un gestionar pentru semnalul respectiv -- sub rezerva verificărilor obișnuite ale permisiunilor descrise în kill(2) --; (în cadrul gestionarului, câmpul siginfo_t si_pid descris în sigaction(2) va fi zero). SIGKILL sau SIGSTOP sunt tratate în mod excepțional: aceste semnale sunt livrate forțat atunci când sunt trimise dintr-un spațiu de nume PID antecesor. Niciunul dintre aceste semnale nu poate fi capturat de procesul „init” și, prin urmare, va duce la acțiunile obișnuite asociate acestor semnale (respectiv, terminarea și oprirea procesului).

Începând cu Linux 3.4, apelul de sistem reboot(2) face ca un semnal să fie trimis către procesul „init” din spațiul de nume. Consultați reboot(2) pentru mai multe detalii.

Imbricarea spațiilor de nume PID

Spațiile de nume PID pot fi imbricate: fiecare spațiu de nume PID are un părinte, cu excepția spațiului de nume PID inițial („rădăcină”). Părintele unui spațiu de nume PID este spațiul de nume PID al procesului care a creat spațiul de nume utilizând clone(2) sau unshare(2). Spațiile de nume PID formează astfel un arbore, toate spațiile de nume urmându-și strămoșii până la spațiul de nume rădăcină. Începând cu Linux 3.7, nucleul limitează la 32 adâncimea maximă de imbricare pentru spațiile de nume PID.

Un proces este vizibil pentru alte procese din spațiul său de nume PID și pentru procesele din fiecare spațiu de nume PID ancestru direct până la spațiul de nume PID rădăcină. În acest context, „vizibil” înseamnă că un proces poate fi ținta operațiilor unui alt proces care utilizează apeluri sistem care specifică un ID de proces. Invers, procesele dintr-un spațiu de nume PID copil nu pot vedea procesele din spațiul de nume părinte și din spațiile de nume ancestru mai îndepărtate. Mai succint: un proces poate vedea (de exemplu, poate trimite semnale cu kill(2), poate stabili valori de curtoazie (nice) cu setpriority(2) etc.) numai proceselor conținute în propriul său spațiu de nume PID și în descendenții acestui spațiu de nume.

Un proces are un ID de proces în fiecare dintre straturile ierarhiei spațiului de nume PID în care este vizibil și se deplasează înapoi prin fiecare spațiu de nume ancestru direct până la spațiul de nume PID rădăcină. Apelurile sistemului care operează asupra ID-urilor de proces operează întotdeauna folosind ID-ul de proces care este vizibil în spațiul de nume PID al apelantului. Un apel la getpid(2) returnează întotdeauna PID-ul asociat cu spațiul de nume în care a fost creat procesul.

Unele procese dintr-un spațiu de nume PID pot avea părinți care sunt în afara spațiului de nume. De exemplu, părintele procesului inițial din spațiul de nume (și anume, procesul init(1) cu PID 1) se află în mod necesar într-un alt spațiu de nume. De asemenea, copiii direcți ai unui proces care utilizează setns(2) pentru a determina copiii săi să se alăture unui spațiu de nume PID se află într-un spațiu de nume PID diferit de cel care apelează setns(2). Apelurile la getppid(2) pentru astfel de procese returnează 0.

În timp ce procesele pot coborî liber în spațiile de nume PID copil (de exemplu, utilizând setns(2) cu un descriptor de fișier de spațiu de nume PID), acestea nu se pot deplasa în direcția opusă. Cu alte cuvinte, procesele nu pot intra în niciun spațiu de nume ancestru (părinte, bunic etc.). Schimbarea spațiilor de nume PID este o operație unidirecțională.

Operația NS_GET_PARENT ioctl(2) poate fi utilizată pentru a descoperi relația parentală dintre spațiile de nume PID; a se vedea ioctl_ns(2).

Semanticele setns(2) și unshare(2)

Apelurile la setns(2) care specifică un descriptor de fișier al spațiului de nume PID și apelurile la unshare(2) cu fanionul CLONE_NEWPID determină ca procesele-copil create ulterior de apelant să fie plasate într-un spațiu de nume PID diferit de cel al apelantului; (începând cu Linux 4.12, acel spațiu de nume PID este indicat prin intermediul fișierului /proc/pid/ns/pid_for_children, așa cum este descris în namespaces(7)). Cu toate acestea, aceste apeluri nu modifică spațiul de nume PID al procesului apelant, deoarece acest lucru ar schimba ideea apelantului despre propriul său PID (așa cum este raportat de getpid()), ceea ce ar rupe multe aplicații și biblioteci.

Altfel spus: apartenența unui proces la spațiul de nume PID este determinată la crearea procesului și nu poate fi modificată ulterior. Printre altele, aceasta înseamnă că relația parentală dintre procese reflectă relația parentală dintre spațiile de nume PID: părintele unui proces fie se află în același spațiu de nume, fie se află în spațiul de nume PID al părintelui imediat.

Un proces poate apela unshare(2) cu fanionul CLONE_NEWPID o singură dată. După ce a efectuat această operație, legătura sa simbolică /proc/pid/ns/pid_for_children va fi goală până când primul proces-copil este creat în spațiul de nume.

Adoptarea proceselor-copil orfane

Când un proces-copil devine orfan, acesta este transferat către procesul „init” din spațiul de nume PID al părintelui său (cu excepția cazului în care unul dintre strămoșii mai apropiați ai părintelui a utilizat comanda prctl(2) PR_SET_CHILD_SUBREAPER pentru a se marca drept colector al proceselor descendente orfane). Rețineți că, din cauza semanticii setns(2) și unshare(2) descrise mai sus, acesta poate fi procesul „init” din spațiul de nume PID care este părintele spațiului de nume PID al copilului, mai degrabă decât procesul „init” din propriul spațiu de nume PID al procesului-copil.

Compatibilitatea CLONE_NEWPID cu alte fanioane CLONE_*

În versiunile curente de Linux, CLONE_NEWPID nu poate fi combinat cu CLONE_THREAD. Firele trebuie să se afle în același spațiu de nume PID, astfel încât firele dintr-un proces să își poată trimite semnale între ele. În mod similar, trebuie să fie posibil să se vadă toate firele unui proces în sistemul de fișiere proc(5). În plus, dacă două fire de execuție se află în spații de nume PID diferite, ID-ul procesului care trimite un semnal nu poate fi codificat în mod semnificativ atunci când se trimite un semnal (a se vedea descrierea tipului siginfo_t în sigaction(2)). Deoarece acesta este calculat atunci când un semnal este pus la coadă, o coadă de semnale partajată de procese în mai multe spații de nume PID ar împiedica acest lucru.

În versiunile anterioare de Linux, CLONE_NEWPID era în plus interzis (eșuând cu eroarea EINVAL) în combinație cu CLONE_SIGHAND (înainte de Linux 4.3), precum și cu CLONE_VM (înainte de Linux 3.12). Modificările care au eliminat aceste restricții au fost, de asemenea, adaptate la nucleele stabile anterioare.

/proc și spațiile de nume PID

Un sistem de fișiere /proc afișează (în directoarele /proc/pid) numai procesele vizibile în spațiul de nume PID al procesului care a efectuat montarea, chiar dacă sistemul de fișiere /proc este vizualizat de procese din alte spații de nume.

După crearea unui nou spațiu de nume PID, este util pentru procesul-copil să își schimbe directorul rădăcină și să monteze o nouă instanță «procfs» la /proc, astfel încât instrumente precum ps(1) să funcționeze corect. Dacă un nou spațiu de nume de montare este creat simultan prin includerea CLONE_NEWNS în argumentul fanioane al clone(2) sau unshare(2), atunci nu este necesar să se schimbe directorul rădăcină: o nouă instanță «procfs» poate fi montată direct pe /proc.

Dintr-un shell, comanda pentru a monta /proc este:


$ mount -t proc proc /proc

Apelarea readlink(2) pe ruta /proc/self produce ID-ul procesului apelantului în spațiul de nume PID al montării «procfs» (adică spațiul de nume PID al procesului care a montat „procfs”). Acest lucru poate fi util în scopuri de introspecție, atunci când un proces dorește să își descopere PID-ul în alte spații de nume.

Fișiere /proc

/proc/sys/kernel/ns_last_pid (începând cu Linux 3.3)
Acest fișier (care este virtualizat pentru fiecare spațiu de nume PID) afișează ultimul PID care a fost alocat în acest spațiu de nume PID. Atunci când următorul PID este alocat, nucleul va căuta cel mai mic PID nealocat care este mai mare decât această valoare, iar atunci când acest fișier este citit ulterior, va afișa acel PID.
Acest fișier poate fi scris de către un proces care are capacitatea CAP_SYS_ADMIN sau (începând cu Linux 5.9) CAP_CHECKPOINT_RESTORE în spațiul de nume al utilizatorului care deține spațiul de nume PID. Acest lucru face posibilă determinarea PID-ului care este alocat următorului proces care este creat în acest spațiu de nume PID.

Diverse

Atunci când un ID de proces este transmis printr-un soclu de domeniu UNIX unui proces dintr-un spațiu de nume PID diferit (a se vedea descrierea SCM_CREDENTIALS în unix(7)), acesta este tradus în valoarea PID corespunzătoare în spațiul de nume PID al procesului receptor.

STANDARDE

Spațiile de nume sunt o caracteristică specifică Linux.

EXEMPLE

A se vedea user_namespaces(7).

CONSULTAȚI ȘI

clone(2), reboot(2), setns(2), unshare(2), proc(5), capabilities(7), credentials(7), mount_namespaces(7), namespaces(7), user_namespaces(7), switch_root(8)

TRADUCERE

Traducerea în limba română a acestui manual a fost făcută de Remus-Gabriel Chelu <remusgabriel.chelu@disroot.org>

Această traducere este documentație gratuită; citiți Licența publică generală GNU Versiunea 3 sau o versiune ulterioară cu privire la condiții privind drepturile de autor. NU se asumă NICIO RESPONSABILITATE.

Dacă găsiți erori în traducerea acestui manual, vă rugăm să trimiteți un e-mail la translation-team-ro@lists.sourceforge.net.

5 februarie 2023 Pagini de manual de Linux 6.03