Fundamentals 40 min read

Understanding the Linux Time Subsystem: Architecture, APIs, and Implementation

This article provides a comprehensive overview of the Linux time subsystem, covering its hardware foundations, time concepts, user‑space and kernel APIs across multiple generations, timer implementations, scheduler tick interaction, and the overall design of the system clock.

Deepin Linux
Deepin Linux
Deepin Linux
Understanding the Linux Time Subsystem: Architecture, APIs, and Implementation

1. Overview of the Linux Time Subsystem

The Linux time subsystem manages both software and hardware components that keep accurate system time, schedule tasks, and provide timing services to user space and kernel modules. It includes clock drivers, interrupt handlers, time‑keeping programs, and synchronization protocols such as RTC (Real‑Time Clock).

2. Time Concepts

2.1 Time‑use Cases

Three basic needs are "knowing the time" (displaying current time), "timing" (measuring elapsed intervals), and "scheduling" (triggering actions at specific moments, either one‑shot or periodic).

2.2 Elements of a Time System

A time system consists of an epoch, a basic unit (seconds), and whether the flow can be paused. The universal epoch is 1970‑01‑01 00:00:00 UTC.

2.3 Representation Dimensions

Computers use a two‑level representation: seconds for intervals ≥ 1 s and nanoseconds for sub‑second precision, with 1 000 000 000 ns = 1 s.

2.4 Clocks and Ticking

Clocks (hardware or software) record the passage of time; "ticking" is the act of advancing the clock.

3. Hardware Foundations

3.1 Types of Clock Hardware

Three main hardware clocks exist in a computer: the Real‑Time Clock (RTC) that keeps time when the system is off, the Timer that generates periodic interrupts, and the Counter that increments a register for high‑precision interval measurement.

3.2 x86 Platform Clocks

On x86, the RTC is backed by a CMOS battery. Traditional timers include the PIT (Programmable Interval Timer) and, on SMP systems, the Local APIC timer, HPET (High Precision Event Timer), and TSC (Time Stamp Counter). Additional timers such as the ACPI Power Management Timer are also available.

3.3 ARM Platform Clocks

ARM platforms (e.g., S3C2440) use external crystal oscillators, PLLs (MPLL for CPU/AHB/APB clocks, UPLL for USB), and divided clock sources for timers. The boot sequence stabilises the crystal, configures PLLs, and then enables the CPU clock.

4. User‑Space APIs

4.1 "Know‑time" APIs

These retrieve the current time. Early APIs use #include <time.h> time_t time(time_t *tloc); int stime(const time_t *t); which work with seconds since the epoch. Later APIs add microsecond precision with #include <sys/time.h> int gettimeofday(struct timeval *tv, struct timezone *tz); int settimeofday(const struct timeval *tv, const struct timezone *tz); struct timeval { time_t tv_sec; suseconds_t tv_usec; }; . The third generation provides nanosecond precision and selectable clocks via #include <time.h> int clock_getres(clockid_t clockid, struct timespec *res); int clock_gettime(clockid_t clockid, struct timespec *tp); int clock_settime(clockid_t clockid, const struct timespec *tp); struct timespec { time_t tv_sec; long tv_nsec; }; . Clock IDs include CLOCK_REALTIME , CLOCK_MONOTONIC , CLOCK_BOOTTIME , CLOCK_TAI , and their coarse or raw variants, each defining a different epoch and behaviour regarding pauses and NTP adjustments. 4.2 Timer APIs Traditional alarm(unsigned int seconds) provides a one‑shot second‑resolution timer. The second generation introduces interval timers via #include <sys/time.h> int getitimer(int which, struct itimerval *curr); int setitimer(int which, const struct itimerval *new, struct itimerval *old); struct itimerval { struct timeval it_interval; struct timeval it_value; }; , supporting microsecond resolution and periodic operation. The third generation uses POSIX timers with explicit clock IDs: #include <signal.h> int timer_create(clockid_t clockid, struct sigevent *sevp, timer_t *timerid); int timer_settime(timer_t timerid, int flags, const struct itimerspec *new, struct itimerspec *old); int timer_gettime(timer_t timerid, struct itimerspec *curr); int timer_delete(timer_t timerid); . The fourth generation converts timers to file descriptors: #include <sys/timerfd.h> int timerfd_create(int clockid, int flags); int timerfd_settime(int fd, int flags, const struct itimerspec *new, struct itimerspec *old); int timerfd_gettime(int fd, struct itimerspec *curr); , allowing read‑style blocking until expiration. 5. Kernel Interfaces 5.1 Time‑Getting Interfaces Kernel functions return time in various forms and clocks, e.g. ktime_t ktime_get(void) (CLOCK_MONOTONIC), ktime_t ktime_get_boottime(void) (CLOCK_BOOTTIME), ktime_t ktime_get_real(void) (CLOCK_REALTIME), and their raw or TAI variants. Corresponding 64‑bit nanosecond functions ( u64 ktime_get_ns(void) , etc.) and timespec64 structures are also provided. 5.2 Timer Interfaces Low‑resolution timers use struct timer_list with expires (in jiffies) and a callback function, managed via add_timer , mod_timer , and del_timer . High‑resolution timers use struct hrtimer with nanosecond expiration, initialized with hrtimer_init and started with hrtimer_start or hrtimer_start_expires . Both families support one‑shot operation; periodic behaviour is achieved by re‑arming the timer in the callback. 5.3 Scheduler Tick and Timing The scheduler tick (configurable HZ = 100, 250, 300, 1000) drives low‑resolution timers and process pre‑emption. Modern kernels use dynamic (tickless) mode to pause ticks during idle, reducing power consumption. When high‑resolution timers are available, they drive the scheduler tick, allowing finer granularity while still supporting dynamic tick. 6. Software Framework 6.1 System Clock Design The system clock aims for accuracy, stability, and efficiency, providing a reliable time base for all kernel and user‑space operations. 6.2 System Clock Implementation Hardware sources (crystals, RTC, HPET, TSC) feed the kernel, which maintains time in seconds and nanoseconds, synchronises via NTP, and updates the clock continuously. 6.3 Dynamic Tick and Timers Low‑resolution timers are driven by the periodic scheduler tick; high‑resolution timers are one‑shot and can be used to implement a dynamic tick by programming the next expiration based on pending timers. 6.4 User‑Space API Implementation User‑space system calls (e.g., time , gettimeofday , clock_gettime , timerfd_create ) are implemented in kernel source files such as kernel/time/time.c , kernel/time/posix-timers.c , kernel/time/itimer.c , and fs/timerfd.c . Caching and careful validation are used to ensure performance and security. 7. Conclusion The Linux time subsystem is a critical component that combines diverse hardware clocks, layered software abstractions, and a rich set of user‑space and kernel APIs to provide precise, reliable timing for the entire operating system.

kernelSchedulerLinuxAPIRTCtimersTime Subsystem
Deepin Linux
Written by

Deepin Linux

Research areas: Windows & Linux platforms, C/C++ backend development, embedded systems and Linux kernel, etc.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.