time_namespaces(7)

NUME
time_namespaces - prezentare generală a spațiilor de nume de timp Linux

DESCRIERE
Spațiile de nume de timp virtualizează valorile a două ceasuri de sistem:

•   CLOCK_MONOTONIC (și, de asemenea, CLOCK_MONOTONIC_COARSE și CLOCK_MONOTONIC_RAW), un ceas care nu poate fi reglat și care reprezintă timpul monoton de la - așa cum este descris de POSIX - „un punct nespecificat din trecut”.

•   CLOCK_BOOTTIME (și, de asemenea, CLOCK_BOOTTIME_ALARM), un ceas nereglabil care este identic cu CLOCK_MONOTONIC, cu excepția faptului că include, de asemenea, orice timp în care sistemul este suspendat.

Astfel, procesele dintr-un spațiu de nume de timp împart valorile pentru fiecare spațiu de nume pentru aceste ceasuri. Acest lucru afectează diverse API-uri care măsoară în funcție de aceste ceasuri, inclusiv: clock_gettime(2), clock_nanosleep(2), nanosleep(2), timer_settime(2), timerfd_settime(2) și /proc/uptime.

În prezent, singura modalitate de a crea un spațiu de nume de timp este prin apelarea unshare(2) cu fanionul CLONE_NEWTIME. Acest apel creează un nou spațiu de nume de timp, dar nu plasează procesul apelant în noul spațiu de nume. În schimb, copiii procesului de apelare creați ulterior sunt plasați în noul spațiu de nume. Acest lucru permite ca decalajele de ceas (a se vedea mai jos) pentru noul spațiu de nume să fie stabilite înainte ca primul proces să fie plasat în spațiul de nume. Legătura simbolică /proc/pid/ns/time_for_children arată spațiul de nume temporal în care vor fi creați copiii unui proces; (un proces poate utiliza un descriptor de fișier deschis pe această legătură simbolică într-un apel la setns(2) pentru a se muta în spațiul de nume).

  /proc/pid/timens_offsets
Fiecărui spațiu de nume de timp îi sunt asociate decalaje, exprimate în raport cu spațiul de nume de timp inițial, care definesc valorile ceasurilor monotonice și de pornire din acel spațiu de nume. Aceste decalaje sunt expuse prin intermediul fișierului /proc/pid/timens_offsets. În cadrul acestui fișier, decalajele sunt exprimate ca linii formate din trei câmpuri delimitate prin spații:

    <clock-id> <offset-secs> <offset-nanosecs>

clock-id este un șir de caractere care identifică ceasul ale cărui decalaje sunt afișate. Acest câmp este fie monotonic, pentru CLOCK_MONOTONIC, fie boottime, pentru CLOCK_BOOTTIME. Câmpurile rămase exprimă decalajul (secunde plus nanosecunde) pentru ceasul din acest spațiu de nume de timp. Aceste decalaje sunt exprimate în raport cu valorile ceasului din spațiul de nume de timp inițial. Valoarea offset-secs poate fi negativă, sub rezerva restricțiilor menționate mai jos; offset-nanosecs este o valoare fără semn.

În spațiul de nume al timpului inițial, conținutul fișierului timens_offsets este următorul:

    $ cat /proc/self/timens_offsets
    monotonic           0         0
    boottime            0         0

Într-un nou spațiu de nume de timp care nu a avut niciun proces membru, decalajele ceasului pot fi modificate prin scrierea de înregistrări cu terminație de linie nouă de aceeași formă în fișierul timens_offsets. Fișierul poate fi scris de mai multe ori, dar după ce primul proces a fost creat în spațiul de nume sau a intrat în spațiul de nume, scrierea write(2) pe acest fișier eșuează cu eroarea EACCES. Pentru a putea scrie în fișierul timens_offsets, un proces trebuie să aibă capacitatea CAP_SYS_TIME în spațiul de nume al utilizatorului care deține spațiul de nume al timpului.

Scrierile în fișierul timens_offsets pot eșua cu următoarele erori:

EINVAL
    O valoare offset-nanosecs este mai mare de 999,999,999.

EINVAL
    O valoare clock-id nu este validă.

EPERM
    Apelantul nu dispune de capacitatea CAP_SYS_TIME.

ERANGE
    O valoare offset-secs este în afara intervalului. În particular;

    •   offset-secs nu poate fi fixat la o valoare care ar face ca ora curentă a ceasului corespunzător din interiorul spațiului de nume să fie o valoare negativă; și

    •   offset-secs nu poate fi fixat la o valoare astfel încât ora ceasului corespunzător din interiorul spațiului de nume să depășească jumătate din valoarea constantei KTIME_SEC_MAX a nucleului (aceasta limitează valoarea ceasului la un maxim de aproximativ 146 de ani).

Într-un nou spațiu de nume de timp creat de unshare(2), conținutul fișierului timens_offsets este moștenit de la spațiul de nume de timp al procesului de creare.

NOTE
Utilizarea spațiilor de nume de timp necesită un nucleu care este configurat cu opțiunea CONFIG_TIME_NS.

Rețineți că spațiile de nume de timp nu virtualizează ceasul CLOCK_REALTIME. Virtualizarea acestui ceas a fost evitată din motive de complexitate și de suprasolicitare în cadrul nucleului.

Pentru compatibilitate cu implementarea inițială, atunci când se scrie un clock-id în fișierul /proc/pid/timens_offsets, valorile numerice ale ID-urilor pot fi scrise în locul numelor simbolice prezentate mai sus; de exemplu, 1 în loc de monotonic și 7 în loc de boottime. Pentru ușurința de citire, se preferă utilizarea numelor simbolice în locul celor numerice.

Motivația pentru adăugarea de spații de nume de timp a fost aceea de a permite ceasurilor monotonice și de pornire să mențină valori consecvente în timpul migrării containerului și al punctului de verificare/restaurare.

EXEMPLE
Următoarea sesiune shell demonstrează funcționarea spațiilor de nume de timp. Începem prin afișarea numărului nodului-i al spațiului de nume de timp al unui shell în spațiul de nume de timp inițial:

    $ readlink /proc/$$/ns/time
    time:[4026531834]

Continuând în spațiul de nume al timpului inițial, vom afișa timpul de funcționare a sistemului folosind uptime(1) și vom folosi programul de exemplu clock_times prezentat în clock_getres(2) pentru a afișa valorile diferitelor ceasuri:

    $ uptime --pretty
    up 21 hours, 17 minutes
    $ ./clock_times
    CLOCK_REALTIME : 1585989401.971 (18356 days +  8h 36m 41s)
    CLOCK_TAI      : 1585989438.972 (18356 days +  8h 37m 18s)
    CLOCK_MONOTONIC:      56338.247 (15h 38m 58s)
    CLOCK_BOOTTIME :      76633.544 (21h 17m 13s)

Apoi folosim unshare(1) pentru a crea un spațiu de nume de timp și pentru a executa un shell bash(1). Din noul shell, folosim comanda încorporată echo pentru a scrie înregistrări în fișierul timens_offsets, ajustând decalajul pentru ceasul CLOCK_MONOTONIC înainte cu 2 zile și decalajul pentru ceasul CLOCK_BOOTTIME înainte cu 7 zile:

    $ PS1=ns2# sudo unshare -T -- bash --norc
    ns2# echo monotonic$((2*24*60*60))0">/proc/$$/timens_offsets"
    ns2# echo boottime$((7*24*60*60))0">/proc/$$/timens_offsets"

Mai sus, am pornit shell-ul bash(1) cu opțiunea --norc, astfel încât să nu fie executat niciun script de pornire. Acest lucru asigură faptul că niciun proces-copil nu este creat din shell înainte de a avea șansa de a actualiza fișierul timens_offsets.

Apoi folosim cat(1) pentru a afișa conținutul fișierului timens_offsets. Executarea lui cat(1) creează primul proces în noul spațiu de nume de timp, după care alte încercări de actualizare a fișierului timens_offsets produc o eroare.

    ns2# cat /proc/$$/timens_offsets
    monotonic      172800         0
    boottime       604800         0
    ns2# echo "boottime $((9*24*60*60)) 0" > /proc/$$/timens_offsets
    bash: echo: eroare de scriere: Permisiune refuzată

Continuând în noul spațiu de nume, vom executa uptime(1) și programul de exemplu clock_times:

    ns2# uptime --pretty
    up 1 week, 21 hours, 18 minutes
    ns2# ./clock_times
    CLOCK_REALTIME : 1585989457.056 (18356 days +  8h 37m 37s)
    CLOCK_TAI      : 1585989494.057 (18356 days +  8h 38m 14s)
    CLOCK_MONOTONIC:     229193.332 (2 days + 15h 39m 53s)
    CLOCK_BOOTTIME :     681488.629 (7 days + 21h 18m  8s)

Din rezultatul de mai sus, putem vedea că ceasurile monotonic și de pornire au valori diferite în noul spațiu de nume al timpului.

Examinând legăturile simbolice /proc/pid/ns/time și /proc/pid/ns/time_for_children, vedem că shell-ul este membru al spațiului de nume timp inițial, dar copiii săi sunt creați în noul spațiu de nume.

    ns2# readlink /proc/$$/ns/time
    time:[4026531834]
    ns2# readlink /proc/$$/ns/time_for_children
    time:[4026532900]
    ns2# readlink /proc/self/ns/time  # Creează un proces-copil
    time:[4026532900]

Revenind la shell-ul din spațiul de nume de timp inițial, vedem că ceasurile monotonic și de pornire nu sunt afectate de modificările timens_offsets care au fost făcute în celălalt spațiu de nume de timp:

    $ uptime --pretty
    up 21 hours, 19 minutes
    $ ./clock_times
    CLOCK_REALTIME : 1585989401.971 (18356 days +  8h 38m 51s)
    CLOCK_TAI      : 1585989438.972 (18356 days +  8h 39m 28s)
    CLOCK_MONOTONIC:      56338.247 (15h 41m  8s)
    CLOCK_BOOTTIME :      76633.544 (21h 19m 23s)

CONSULTAȚI ȘI
nsenter(1), unshare(1), clock_settime(2), setns(2), unshare(2), namespaces(7), time(7)

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 (https://www.gnu.org/licenses/gpl-3.0.html) 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.