1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
|
.\" Copyright (c) 2020 by Michael Kerrisk <mtk.manpages@gmail.com>
.\"
.\" SPDX-License-Identifier: Linux-man-pages-copyleft
.\"
.\"
.TH time_namespaces 7 2024-05-02 "Linux man-pages (unreleased)"
.SH NAME
time_namespaces \- overview of Linux time namespaces
.SH DESCRIPTION
Time namespaces virtualize the values of two system clocks:
.IP \[bu] 3
.B CLOCK_MONOTONIC
(and likewise
.B CLOCK_MONOTONIC_COARSE
and
.BR CLOCK_MONOTONIC_RAW ),
a nonsettable clock that represents monotonic time since\[em]as
described by POSIX\[em]"some unspecified point in the past".
.IP \[bu]
.B CLOCK_BOOTTIME
(and likewise
.BR CLOCK_BOOTTIME_ALARM ),
a nonsettable clock that is identical to
.BR CLOCK_MONOTONIC ,
except that it also includes any time that the system is suspended.
.P
Thus, the processes in a time namespace share per-namespace values
for these clocks.
This affects various APIs that measure against these clocks, including:
.BR clock_gettime (2),
.BR clock_nanosleep (2),
.BR nanosleep (2),
.BR timer_settime (2),
.BR timerfd_settime (2),
and
.IR /proc/uptime .
.P
Currently, the only way to create a time namespace is by calling
.BR unshare (2)
with the
.B CLONE_NEWTIME
flag.
This call creates a new time namespace but does
.I 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
.IR /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
.BR setns (2)
in order to move into the namespace.)
.\"
.SS \fI/proc/\fPpid\fI/timens_offsets\fP
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
.IR /proc/ pid /timens_offsets .
Within this file,
the offsets are expressed as lines consisting of
three space-delimited fields:
.P
.in +4n
.EX
<clock-id> <offset-secs> <offset-nanosecs>
.EE
.in
.P
The
.I clock-id
is a string that identifies the clock whose offsets are being shown.
This field is either
.IR monotonic ,
for
.BR CLOCK_MONOTONIC ,
or
.IR boottime ,
for
.BR 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
.I offset-secs
value can be negative, subject to restrictions noted below;
.I offset-nanosecs
is an unsigned value.
.P
In the initial time namespace, the contents of the
.I timens_offsets
file are as follows:
.P
.in +4n
.EX
$ \fBcat /proc/self/timens_offsets\fP
monotonic 0 0
boottime 0 0
.EE
.in
.P
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
.I 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,
.BR write (2)s
on this file fail with the error
.BR EACCES .
In order to write to the
.I timens_offsets
file, a process must have the
.B CAP_SYS_TIME
capability in the user namespace that owns the time namespace.
.P
Writes to the
.I timens_offsets
file can fail with the following errors:
.TP
.B EINVAL
An
.I offset-nanosecs
value is greater than 999,999,999.
.TP
.B EINVAL
A
.I clock-id
value is not valid.
.TP
.B EPERM
The caller does not have the
.B CAP_SYS_TIME
capability.
.TP
.B ERANGE
An
.I offset-secs
value is out of range.
In particular;
.RS
.IP \[bu] 3
.I 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
.IP \[bu]
.I 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
.B KTIME_SEC_MAX
(this limits the clock value to a maximum of approximately 146 years).
.RE
.P
In a new time namespace created by
.BR unshare (2),
the contents of the
.I timens_offsets
file are inherited from the time namespace of the creating process.
.SH NOTES
Use of time namespaces requires a kernel that is configured with the
.B CONFIG_TIME_NS
option.
.P
Note that time namespaces do not virtualize the
.B CLOCK_REALTIME
clock.
Virtualization of this clock was avoided for reasons of complexity
and overhead within the kernel.
.P
For compatibility with the initial implementation, when writing a
.I clock-id
to the
.IR /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
.IR monotonic ,
and 7 instead of
.IR boottime .
For readability, the use of the symbolic names over the numbers is preferred.
.P
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.
.SH 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:
.P
.in +4n
.EX
$ \fBreadlink /proc/$$/ns/time\fP
time:[4026531834]
.EE
.in
.P
Continuing in the initial time namespace, we display the system uptime using
.BR uptime (1)
and use the
.I clock_times
example program shown in
.BR clock_getres (2)
to display the values of various clocks:
.P
.in +4n
.EX
$ \fBuptime \-\-pretty\fP
up 21 hours, 17 minutes
$ \fB./clock_times\fP
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)
.EE
.in
.P
We then use
.BR unshare (1)
to create a time namespace and execute a
.BR bash (1)
shell.
From the new shell, we use the built-in
.B echo
command to write records to the
.I timens_offsets
file adjusting the offset for the
.B CLOCK_MONOTONIC
clock forward 2 days
and the offset for the
.B CLOCK_BOOTTIME
clock forward 7 days:
.P
.in +4n
.EX
$ \fBPS1="ns2# " sudo unshare \-T \-\- bash \-\-norc\fP
ns2# \fBecho "monotonic $((2*24*60*60)) 0" > /proc/$$/timens_offsets\fP
ns2# \fBecho "boottime $((7*24*60*60)) 0" > /proc/$$/timens_offsets\fP
.EE
.in
.P
Above, we started the
.BR bash (1)
shell with the
.B \-\-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
.I timens_offsets
file.
.P
We then use
.BR cat (1)
to display the contents of the
.I timens_offsets
file.
The execution of
.BR cat (1)
creates the first process in the new time namespace,
after which further attempts to update the
.I timens_offsets
file produce an error.
.P
.in +4n
.EX
ns2# \fBcat /proc/$$/timens_offsets\fP
monotonic 172800 0
boottime 604800 0
ns2# \fBecho "boottime $((9*24*60*60)) 0" > /proc/$$/timens_offsets\fP
bash: echo: write error: Permission denied
.EE
.in
.P
Continuing in the new namespace, we execute
.BR uptime (1)
and the
.I clock_times
example program:
.P
.in +4n
.EX
ns2# \fBuptime \-\-pretty\fP
up 1 week, 21 hours, 18 minutes
ns2# \fB./clock_times\fP
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)
.EE
.in
.P
From the above output, we can see that the monotonic
and boot-time clocks have different values in the new time namespace.
.P
Examining the
.IR /proc/ pid /ns/time
and
.IR /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.
.P
.in +4n
.EX
ns2# \fBreadlink /proc/$$/ns/time\fP
time:[4026531834]
ns2# \fBreadlink /proc/$$/ns/time_for_children\fP
time:[4026532900]
ns2# \fBreadlink /proc/self/ns/time\fP # Creates a child process
time:[4026532900]
.EE
.in
.P
Returning to the shell in the initial time namespace,
we see that the monotonic and boot-time clocks
are unaffected by the
.I timens_offsets
changes that were made in the other time namespace:
.P
.in +4n
.EX
$ \fBuptime \-\-pretty\fP
up 21 hours, 19 minutes
$ \fB./clock_times\fP
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)
.EE
.in
.SH SEE ALSO
.BR nsenter (1),
.BR unshare (1),
.BR clock_settime (2),
.\" clone3() support for time namespaces is a work in progress
.\" .BR clone3 (2),
.BR setns (2),
.BR unshare (2),
.BR namespaces (7),
.BR time (7)
|