Updating the Linux System Clock

Updating the Linux System Clock
Chapter 10 Series — Part 8: settimeofday() and adjtime()
CAP_SYS_TIME
Privilege Required
Gradual
Preferred Approach
NTP
Real-World Usage

Why Would a Program Need to Set the Clock?

In most systems, the clock is managed automatically by the NTP (Network Time Protocol) daemon. But understanding the underlying system calls — settimeofday() and adjtime() — is important for embedded systems engineers, where NTP may not be available, or when you need to synchronise time from a custom hardware source (GPS, RTC chip, etc.).

Keywords in This Post

settimeofday() adjtime() CAP_SYS_TIME NTP Monotonic Clock Clock Slewing adjtimex()

🕐 settimeofday() — Immediate Clock Change

settimeofday() sets the system clock to an exact time you specify. It is the write counterpart to gettimeofday(). Requires the CAP_SYS_TIME capability (root or equivalent).

#define _BSD_SOURCE
#include <sys/time.h>

int settimeofday(const struct timeval *tv, const struct timezone *tz);
/* Returns 0 on success, -1 on error */
/* tz should always be NULL (historical, obsolete argument) */
#define _BSD_SOURCE
#include <sys/time.h>
#include <stdio.h>

int main(void)
{
    struct timeval tv;

    /* Set clock to: 15 May 2025, 10:30:00 UTC */
    /* (In a real program, compute this from reliable external source) */
    tv.tv_sec  = 1747267800;   /* seconds since Epoch */
    tv.tv_usec = 0;

    if (settimeofday(&tv, NULL) == -1) {
        perror("settimeofday");
        /* Will fail with EPERM unless running as root or with CAP_SYS_TIME */
        return 1;
    }
    printf("System clock updated successfully.\n");
    return 0;
}

The hidden danger of jumping the clock:
When you use settimeofday() to jump the clock forward or backward by several seconds, programs that depend on the clock behaving continuously can break:
make uses file timestamps to decide what to recompile — a clock jump can cause it to skip necessary rebuilds or redo everything.
• Database systems using timestamps for transaction ordering may produce inconsistent results.
• Log files may have entries appearing “out of order” or in the future.
This is why adjtime() is almost always preferred.

⏰ adjtime() — Gradual Clock Correction

Instead of jumping the clock, adjtime() slews it — it speeds up or slows down the clock slightly until the desired correction is achieved. The clock always moves forward; it just moves at a slightly different rate for a while.

Analogy: You set your wall clock 2 minutes fast. Rather than ripping it off the wall and resetting it, you simply make it tick a tiny bit slower for the next hour until it catches up to the correct time. Everything observing the clock sees a smooth, continuous progression.

#define _BSD_SOURCE
#include <sys/time.h>

int adjtime(struct timeval *delta, struct timeval *olddelta);
/* delta    = how much to adjust (positive = speed up, negative = slow down) */
/* olddelta = returns remaining unapplied correction from a prior call (or NULL) */
/* Returns 0 on success, -1 on error */
#define _BSD_SOURCE
#include <sys/time.h>
#include <stdio.h>

int main(void)
{
    struct timeval delta;
    struct timeval pending;

    /* Correct clock: add 2 seconds gradually */
    delta.tv_sec  = 2;
    delta.tv_usec = 0;

    if (adjtime(&delta, &pending) == -1) {
        perror("adjtime");
        return 1;
    }

    printf("Adjustment requested: +%ld.%06ld s\n",
           (long)delta.tv_sec, (long)delta.tv_usec);
    printf("Pending from last call: %ld.%06ld s\n",
           (long)pending.tv_sec, (long)pending.tv_usec);

    return 0;
}

Scenario What adjtime() does
Clock is 2 seconds slow (delta = +2s) Speeds clock up by 500 µs/s. Takes 4000 s (≈ 1.1 hours) to add 2 seconds.
Clock is 1 second fast (delta = -1s) Slows clock down by 500 µs/s. Takes 2000 s (≈ 33 minutes) to lose 1 second.
New adjtime() call while correction is pending The remaining correction is returned in olddelta; the new delta replaces it.

📋 settimeofday() vs adjtime() — When to Use Each
Scenario Recommended function Reason
System just booted, clock is far off (minutes/hours) settimeofday() No running apps to break; need immediate correction
Running system, clock is a few seconds off adjtime() Maintains monotonic clock; avoids breaking apps
Continuous NTP-style synchronisation adjtimex() More precise kernel-level interface used by ntpd

Embedded systems context: If your board has an RTC (real-time clock) chip and reads it at boot via I2C, you would call settimeofday() once at startup (before any user processes start) to set the kernel clock. If your system has periodic GPS pulse synchronisation, you would use adjtime() for continuous small corrections to keep the kernel clock accurate without disrupting running processes.

Up Next in This Series

Part 9 covers the Software Clock (Jiffies), Process Time, and the times() / clock() functions — measuring how much CPU your program actually used.

Next: Jiffies & Process Time → All Linux Posts

Leave a Reply

Your email address will not be published. Required fields are marked *