time_namespaces(7)

NAMN
time_namespaces — översikt över Linux tidnamnrymder

BESKRIVNING
Tidnamnrymder virtualiserar värden för två systemklockor:

•   CLOCK_MONOTONIC (och likaledes CLOCK_MONOTONIC_COARSE och CLOCK_MONOTONIC_RAW), en inte inställbar klocka som representerar monoton tid sedan — såsom beskrivs av POSIX — ”någon ospecificerad punkt i det förgångna”.

•   CLOCK_BOOTTIME (och likaledes CLOCK_BOOTTIME_ALARM), en inte inställbar klocka som är identisk med CLOCK_MONOTONIC, förutom att den även inkluderar eventuell tid som systemet har varit vilande.

Alltså delar processerna i en tidnamnrymd värden per namnrymd för dessa klockor. Detta påverkar diverse API:er som mäter mot dessa klockor, inklusive: clock_gettime(2), clock_nanosleep(2), nanosleep(2), timer_settime(2), timerfd_settime(2) och /proc/uptime.

För närvarande är det enda sättet att skapa en tidnamnrymd genom att anropa unshare(2) med flaggan CLONE_NEWTIME. Detta anrop skapar en ny tidnamnrymd men placerar inte den anropande processen i den nya namnrymden. Istället placeras den anropande processens sedermera skapade barn i den nya namnrymden. Detta gör att klockavstånd (se nedan) för den nya namnrymden kan sättas före den första processen placeras i namnrymden. Den symboliska länken /proc/pid/ns/time_for_children visar tidnamnrymden i vilken barnen till en process kommer skapas. (En process kan använda en filbeskrivare som öppnas mot denna symboliska länk i ett anrop av setns(2) för att flytta in i namnrymden.)

  /proc/pid/timens_offsets
Associerat med varje tidnamnrymd finns avstånd, uttryckta med avseende på den initiala tidnamnrymden, som definierar värdena för den monotona klockan och starttidsklockan i den namnrymden. Dessa avstånd visas via filen /proc/pid/timens_offsets. Inom denna fil uttrycks avstånden som rader som består av tre blankavgränsade fält:

    <klock-id> <avstånd-sek> <avstånd-nanosek>

Klock-id är en sträng som identifierar klockan vars avstånd visas. Detta fält är antingen monotonic, för CLOCK_MONOTONIC, eller boottime, för CLOCK_BOOTTIME. De återstående fälten uttrycker avståndet (sekunder plus nanosekunder) för klockan i denna tidnamnrymd. Dessa avstånd uttrycks relativt klockvärdena i den initiala tidnamnrymden. Värdet avstånd-sek kan vara negativt, föremål för begränsningarna som anges nedan; avstånd-nanosek är ett teckenlöst värde.

I den initiala tidnamnrymden är innehållet i filen timens_offsets som följer:

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

I en ny tidnamnrymd som inte har haft några medlemsprocesser kan klockavstånden ändras genom att skriva nyradsavslutade poster med samma format till filen timens_offsets. Det går att skriva till filen flera gånger, men efter att den första processen har skapats i eller gått in i namnrymden kommer write(2) till denna fil att misslyckas med felet EACCES. För att skriva till filen timens_offsets måste en process ha förmågan CAP_SYS_TIME i användarnamnrymden som äger tidnamnrymden.

Skrivningar till filen timens_offsets kan misslyckas med följande fel:

EINVAL
    Ett värde på avstånd-nanosek större än 999 999 999.

EINVAL
    Ett värde på klock-id som inte är giltigt.

EPERM
    Anroparen har inte förmågan CAP_SYS_TIME.

ERANGE
    Ett värde på avstånd-sek är utanför intervallet. Speciellt;

    •   kan avstånd-sek inte sättas till ett värde vilket skulle ge den aktuella tiden på motsvarande klocka inuti namnrymden ett negativt värde; vidare

    •   kan avstånd-sek inte sättas till ett värde så att tiden på motsvarande klocka inuti namnrymden skulle överskrida halva värdet på kärnkonstanten KTIME_SEC_MAX (detta begränsar klockvärdet till ett maximum av ungefär 146 år).

I en ny tidnamnrymd skapad med unshare(2) ärvs innehållet i filen timens_offsets från tidnamnrymden hos den skapande processen.

NOTERINGAR
Användning av cgroup-namnrymder kräver en kärna som är konfigurerad med alternativet CONFIG_TIME_NS.

Observera att tidnamnrymder inte virtualiserar klockan CLOCK_REALTIME. Virtualisering av denna klocka undveks på grund av komplexitet och overhead inom kärnan.

För kompatibilitet med den ursprungliga implementationen kan, när man skriver ett klock-id till filen /proc/pid/timens_offsets, de numeriska värdena av ID:n skrivas istället för de symboliska namnen som visas ovan; d.v.s., 1 istället för monotonic, och 7 istället för boottime. För bästa läsbarhet rekommenderas det att man använder symboliska namn hellre än nummer.

Motivationen för att lägga till tidnamnrymder var för att göra det möjligt att låta den monotona klockan och starttidsklockan behålla konsistenta värden under migrering av behållare och checkpunkt/återställning.

EXEMPEL
Följande skalsession demonstrerar funktionen hos tidnamnrymder. Vi börjar med att visa inodsnumret för tidnamnrymden för ett skal i den initiala tidnamnrymden:

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

Fortfarande i den initiala tidnamnrymden visar vi systemets uppetid med uptime(1) och använder exempelprogrammet clock_times som visas i clock_getres(2) för att visa värdet på olika klockor:

    $ 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)

Vi använder sedan unshare(1) för att skapa en tidnamnrymd och köra ett skal bash(1). Från det nya skalet använder vi det inbyggda kommandot echo för att skriva poster till filen timens_offsets och justera avståndet för klockan CLOCK_MONOTONIC framåt 2 dagar och avståndet för klockan CLOCK_BOOTTIME framåt 7 dagar:

    $ 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

Ovan startar vi skalet bash(1) med flaggan --norc så att inga uppstartsskript körs. Detta säkerställer att inga barnprocesser skapas från skalet före vi har haft en chans att uppdatera filen timens_offsets.

Vi använder sedan cat(1) för att visa innehållet i filen timens_offsets. Att cat(1) körs skapar den första processen i den nya tidnamnrymden, varefter vidare försök att uppdatera filen timens_offsets ger ett fel.

    ns2# cat /proc/$$/timens_offsets
    monotonic      172800         0
    boottime       604800         0
    ns2# echo "boottime $((9*24*60*60)) 0" > /proc/$$/timens_offsets
    bash: echo: skrivfel: Åtkomst nekas

Fortfarande i den nya namnrymden kör vi uptime(1) och exempelprogrammet 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)

Från ovanstående utskrift kan vi se att den monotona klockan och starttidsklockan har andra värden i den nya tidnamnrymden.

Genom att undersöka de symboliska länkarna /proc/pid/ns/time och /proc/pid/ns/time_for_children ser vi att skalet är medlem av den initiala tidnamnrymden, men dess barn skapas i den nya namnrymden.

    ns2# readlink /proc/$$/ns/time
    time:[4026531834]
    ns2# readlink /proc/$$/ns/time_for_children
    time:[4026532900]
    ns2# readlink /proc/self/ns/time   # Skapar en barnprocess
    time:[4026532900]

Efter att ha återvänt till skalet i den initiala namnrymden ser vi att den monotona klockan och starttidsklockan är opåverkade av ändringarna av timens_offsets som gjordes i den andra tidnamnrymden:

    $ 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)

SE ÄVEN
nsenter(1), unshare(1), clock_settime(2), setns(2), unshare(2), namespaces(7), time(7)

ÖVERSÄTTNING
Den svenska översättningen av denna manualsida skapades av Göran Uddeborg <goeran@uddeborg.se>

Denna översättning är fri dokumentation; läs GNU General Public License Version 3 (https://www.gnu.org/licenses/gpl-3.0.html) eller senare för upphovsrättsvillkor. Vi tar INGET ANSVAR.

Om du hittar fel i översättningen av denna manualsida, skicka ett mail till Tp-sv@listor.tp-sv.se.