# time_namespaces

## NAME



           time_namespaces - overview of Linux time namespaces
    


## DESCRIPTION



           Time namespaces virtualize the values of two system clocks:
    
           •  **CLOCK_MONOTONIC**(and likewise **CLOCK_MONOTONIC_COARSE** and
              **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.)
    
       [1m/proc/[24mpid _/timens_offsets_
           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
           errors:
    
           **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



           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



           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**
               time:[4026531834]
    
           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**
               time:[4026531834]
               ns2# **readlink /proc/$$/ns/time_for_children**
               time:[4026532900]
               ns2# **readlink /proc/self/ns/time** # Creates a child process
               time:[4026532900]
    
           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 namespace:
    
               $ **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)
    


* * *