POSIX Time APIs

Last update: 2023-08-09 17:37:46 +0800 +0800
tags: Linux | Posix | Time
Available translations: 日本語 / 中文(简体) / 中文(繁體)

Time APIs answer different questions: civil time names an instant, monotonic time measures an interval, and CPU clocks measure execution consumed by work. Selecting the wrong clock makes timeouts react to wall-clock corrections or makes I/O waits disappear from measurements.

Clock Selection #

clock_gettime reads a clockid_t into struct timespec, whose tv_sec and tv_nsec fields represent seconds and nanoseconds. POSIX requires CLOCK_REALTIME, the system civil clock measured from the Epoch, and CLOCK_MONOTONIC, whose origin is unspecified and cannot be set. Use realtime for timestamps and monotonic time for elapsed durations and deadlines.

When supported, CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID measure CPU execution consumed by a process or one thread. They exclude time blocked in I/O or descheduled. Linux also provides CLOCK_BOOTTIME, which includes suspended time; it is a Linux extension rather than a portable POSIX choice.

c
struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start);
/* operation */
clock_gettime(CLOCK_MONOTONIC, &end);

clock_getres reports the implementation’s resolution, not a promise that consecutive reads differ. Scheduling latency, timer coalescing, and hardware affect when code runs. Calls can fail with EOVERFLOW where an instant cannot fit in time_t; validate tv_nsec, normalize arithmetic across second boundaries, and do not assume time_t has a fixed width.

Sleeping and Timers #

nanosleep supplies a relative delay. A signal can interrupt it with EINTR and report a remainder, but restarting from that remainder still accumulates work and scheduling delay in periodic code. Compute one absolute monotonic deadline per period and wait with clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, ...); an already-passed deadline returns immediately, so the caller must choose whether to skip work or catch up.

POSIX timers use timer_create and timer_settime; TIMER_ABSTIME makes the requested expiration an absolute time on the timer’s chosen clock. A notification can be a signal or a thread notification, each with different queuing and lifetime implications. Linux timerfd_create is non-POSIX but integrates timer expiration with poll, select, and epoll. alarm and setitimer are legacy signal-oriented interfaces.

Relative waits are insulated from a later CLOCK_REALTIME adjustment, while absolute realtime deadlines move with that clock. Therefore, express timeout deadlines on a monotonic clock unless the product requirement is explicitly “at this civil-time instant.”

Civil Time and Time Zones #

time_t is a scalar time value; struct tm is broken-down calendar time. gmtime_r converts to UTC and localtime_r converts using the process time-zone rules. Their non-_r counterparts use reusable static storage. mktime interprets a struct tm as local civil time; setting tm_isdst to -1 lets it determine daylight-saving status. timegm is a useful GNU extension for interpreting broken-down UTC, not a POSIX interface.

TZ and tzset control the process’s timezone state. A local time in the autumn daylight-saving transition may name two instants; a local time skipped in spring may name none. Store instants in UTC or as time_t, and carry an explicit zone or offset when a human-facing value must preserve its civil-time meaning.

POSIX time does not model leap seconds as a distinct scalar-time second. Systems may step or smear the realtime clock when synchronizing; therefore, neither time_t arithmetic nor a UTC conversion API alone is a complete leap-second representation.

The POSIX clock specification and clock_nanosleep(3) define the portable and Linux-specific details.

Comments

Read or comment on GitHub (sign-in required to comment)