|
|
time_namespaces(7) Miscellaneous Information Manual time_namespaces(7)
time_namespaces - overview of Linux time namespaces
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.
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.
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)
nsenter(1), unshare(1), clock_settime(2), setns(2), unshare(2),
namespaces(7), time(7)
This page is part of the man-pages (Linux kernel and C library
user-space interface documentation) project. Information about
the project can be found at
⟨https://www.kernel.org/doc/man-pages/⟩. If you have a bug report
for this manual page, see
⟨https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/tree/CONTRIBUTING⟩.
This page was obtained from the tarball man-pages-6.15.tar.gz
fetched from
⟨https://mirrors.edge.kernel.org/pub/linux/docs/man-pages/⟩ on
2025-08-11. If you discover any rendering problems in this HTML
version of the page, or you believe there is a better or more up-
to-date source for the page, or you have corrections or
improvements to the information in this COLOPHON (which is not
part of the original manual page), send a mail to
[email protected]
Linux man-pages 6.15 2025-05-17 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)