time_namespaces(7) — Linux manual page


time_namespaces(7)  Miscellaneous Information Manual  time_namespaces(7)

NAME         top

       time_namespaces - overview of Linux time namespaces

DESCRIPTION         top

       Time namespaces virtualize the values of two system clocks:

          CLOCK_MONOTONIC_RAW), a nonsettable clock that represents
          monotonic time  since—as described  by  POSIX—"some
          unspecified  point in the past".

       •  CLOCK_BOOTTIME (and likewise CLOCK_BOOTTIME_ALARM), a
          nonsettable clock that is identical to CLOCK_MONOTONIC, except
          that it also includes any time that the system is suspended.

       Thus, the processes in a time namespace share per-namespace
       values for these clocks.  This affects various APIs that measure
       against these clocks, including: clock_gettime(2),
       clock_nanosleep(2), nanosleep(2), timer_settime(2),
       timerfd_settime(2), and /proc/uptime.

       Currently, the only way to create a time namespace is by calling
       unshare(2) with the CLONE_NEWTIME flag.  This call creates a new
       time namespace but does not place the calling process in the new
       namespace.  Instead, the calling process's subsequently created
       children are placed in the new namespace.  This allows clock
       offsets (see below) for the new namespace to be set before the
       first process is placed in the namespace.  The
       /proc/pid/ns/time_for_children symbolic link shows the time
       namespace in which the children of a process will be created.  (A
       process can use a file descriptor opened on this symbolic link in
       a call to setns(2) in order to move into the namespace.)

       Associated with each time namespace are offsets, expressed with
       respect to the initial time namespace, that define the values of
       the monotonic and boot-time clocks in that namespace.  These
       offsets are exposed via the file /proc/pid/timens_offsets.
       Within this file, the offsets are expressed as lines consisting
       of three space-delimited fields:

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

       The clock-id is a string that identifies the clock whose offsets
       are being shown.  This field is either monotonic, for
       CLOCK_MONOTONIC, or boottime, for CLOCK_BOOTTIME.  The remaining
       fields express the offset (seconds plus nanoseconds) for the
       clock in this time namespace.  These offsets are expressed
       relative to the clock values in the initial time namespace.  The
       offset-secs value can be negative, subject to restrictions noted
       below; offset-nanosecs is an unsigned value.

       In the initial time namespace, the contents of the timens_offsets
       file are as follows:

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

       In a new time namespace that has had no member processes, the
       clock offsets can be modified by writing newline-terminated
       records of the same form to the timens_offsets file.  The file
       can be written to multiple times, but after the first process has
       been created in or has entered the namespace, write(2)s on this
       file fail with the error EACCES.  In order to write to the
       timens_offsets file, a process must have the CAP_SYS_TIME
       capability in the user namespace that owns the time namespace.

       Writes to the timens_offsets file can fail with the following

       EINVAL An offset-nanosecs value is greater than 999,999,999.

       EINVAL A clock-id value is not valid.

       EPERM  The caller does not have the CAP_SYS_TIME capability.

       ERANGE An offset-secs value is out of range.  In particular;

              •  offset-secs can't be set to a value which would make
                 the current time on the corresponding clock inside the
                 namespace a negative value; and

              •  offset-secs can't be set to a value such that the time
                 on the corresponding clock inside the namespace would
                 exceed half of the value of the kernel constant
                 KTIME_SEC_MAX (this limits the clock value to a maximum
                 of approximately 146 years).

       In a new time namespace created by unshare(2), the contents of
       the timens_offsets file are inherited from the time namespace of
       the creating process.

NOTES         top

       Use of time namespaces requires a kernel that is configured with
       the CONFIG_TIME_NS option.

       Note that time namespaces do not virtualize the CLOCK_REALTIME
       clock.  Virtualization of this clock was avoided for reasons of
       complexity and overhead within the kernel.

       For compatibility with the initial implementation, when writing a
       clock-id to the /proc/pid/timens_offsets file, the numerical
       values of the IDs can be written instead of the symbolic names
       show above; i.e., 1 instead of monotonic, and 7 instead of
       boottime.  For readability, the use of the symbolic names over
       the numbers is preferred.

       The motivation for adding time namespaces was to allow the
       monotonic and boot-time clocks to maintain consistent values
       during container migration and checkpoint/restore.

EXAMPLES         top

       The following shell session demonstrates the operation of time
       namespaces.  We begin by displaying the inode number of the time
       namespace of a shell in the initial time namespace:

           $ readlink /proc/$$/ns/time

       Continuing in the initial time namespace, we display the system
       uptime using uptime(1) and use the clock_times example program
       shown in clock_getres(2) to display the values of various clocks:

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

       We then use unshare(1) to create a time namespace and execute a
       bash(1) shell.  From the new shell, we use the built-in echo
       command to write records to the timens_offsets file adjusting the
       offset for the CLOCK_MONOTONIC clock forward 2 days and the
       offset for the CLOCK_BOOTTIME clock forward 7 days:

           $ 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

       Above, we started the bash(1) shell with the --norc option so
       that no start-up scripts were executed.  This ensures that no
       child processes are created from the shell before we have a
       chance to update the timens_offsets file.

       We then use cat(1) to display the contents of the timens_offsets
       file.  The execution of cat(1) creates the first process in the
       new time namespace, after which further attempts to update the
       timens_offsets file produce an error.

           ns2# cat /proc/$$/timens_offsets
           monotonic      172800         0
           boottime       604800         0
           ns2# echo "boottime $((9*24*60*60)) 0" > /proc/$$/timens_offsets
           bash: echo: write error: Permission denied

       Continuing in the new namespace, we execute uptime(1) and the
       clock_times example program:

           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)

       From the above output, we can see that the monotonic and boot-
       time clocks have different values in the new time namespace.

       Examining the /proc/pid/ns/time and
       /proc/pid/ns/time_for_children symbolic links, we see that the
       shell is a member of the initial time namespace, but its children
       are created in the new namespace.

           ns2# readlink /proc/$$/ns/time
           ns2# readlink /proc/$$/ns/time_for_children
           ns2# readlink /proc/self/ns/time   # Creates a child process

       Returning to the shell in the initial time namespace, we see that
       the monotonic and boot-time clocks are unaffected by the
       timens_offsets changes that were made in the other time

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

SEE ALSO         top

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

Linux man-pages (unreleased)   2024-05-02             time_namespaces(7)

Pages that refer to this page: nsenter(1)unshare(1)clock_getres(2)unshare(2)lttng-ust(3)namespaces(7)time(7)