Nanoseconds
-lrt
POSIX.1b
Why POSIX Clocks?
The traditional gettimeofday() gives microsecond resolution. POSIX.1b clocks give nanosecond resolution and provide multiple clock types for different use cases โ wall time, monotonic time, and per-process/per-thread CPU time.
All programs using this API must be compiled with -lrt (realtime library).
| Clock ID | What it Measures | Settable? | Use Case |
|---|---|---|---|
| CLOCK_REALTIME | System-wide wall-clock time (since Epoch) | โ Yes (root) | Timestamps, log times |
| CLOCK_MONOTONIC | Time since system boot โ never goes backward | โ No | Measuring elapsed time, timeouts |
| CLOCK_PROCESS_CPUTIME_ID | CPU time consumed by calling process | Read-only (Linux) | Profiling, CPU budgets |
| CLOCK_THREAD_CPUTIME_ID | CPU time consumed by calling thread | Read-only (Linux) | Per-thread profiling |
| CLOCK_MONOTONIC_RAW | Like MONOTONIC but unaffected by NTP | โ No | Clock synchronization apps |
CLOCK_MONOTONIC โ it never jumps backward due to NTP or manual clock changes.T=1: 1001s (normal)
T=2: 999s โ NTP jump back!
T=3: 1000s (normal)
elapsed = 999-1000 = -1s ???
T=1: 5001s (always increases)
T=2: 5002s (NTP can’t affect it)
T=3: 5003s
elapsed = always correct โ
#define _POSIX_C_SOURCE 199309
#include <time.h>
/* Read the current value of a clock */
int clock_gettime(clockid_t clockid,
struct timespec *tp);
/* Set a clock value (requires CAP_SYS_TIME for CLOCK_REALTIME) */
int clock_settime(clockid_t clockid,
const struct timespec *tp);
/* Get the resolution (granularity) of a clock */
int clock_getres(clockid_t clockid,
struct timespec *res);
/* All return 0 on success, -1 on error */
/* Get CPU-time clock ID for a process */
#include <time.h>
int clock_getcpuclockid(pid_t pid, clockid_t *clockid);
/* Get CPU-time clock ID for a thread */
#include <pthread.h>
#include <time.h>
int pthread_getcpuclockid(pthread_t thread,
clockid_t *clockid);
/* Both return 0 on success, positive error on failure */
/* Compile with: gcc prog.c -o prog -lrt */
#define _POSIX_C_SOURCE 199309
#include <stdio.h>
#include <time.h>
void print_clock(const char *name, clockid_t cid) {
struct timespec ts;
if (clock_gettime(cid, &ts) == -1) {
perror(name);
return;
}
printf("%-30s : %ld.%09ld s\n", name, ts.tv_sec, ts.tv_nsec);
}
int main(void) {
print_clock("CLOCK_REALTIME", CLOCK_REALTIME);
print_clock("CLOCK_MONOTONIC", CLOCK_MONOTONIC);
print_clock("CLOCK_PROCESS_CPUTIME_ID", CLOCK_PROCESS_CPUTIME_ID);
print_clock("CLOCK_THREAD_CPUTIME_ID", CLOCK_THREAD_CPUTIME_ID);
return 0;
}
/* Compile: gcc -o clocks clocks.c -lrt
Sample output:
CLOCK_REALTIME : 1750000000.123456789 s
CLOCK_MONOTONIC : 12345.678901234 s
CLOCK_PROCESS_CPUTIME_ID : 0.000456789 s
CLOCK_THREAD_CPUTIME_ID : 0.000456789 s
*/
Use CLOCK_MONOTONIC to accurately measure how long a function takes.
#define _POSIX_C_SOURCE 199309
#include <stdio.h>
#include <time.h>
#include <unistd.h>
/* Calculate difference between two timespec values in milliseconds */
double timespec_diff_ms(struct timespec *start,
struct timespec *end) {
return (double)(end->tv_sec - start->tv_sec) * 1000.0
+ (double)(end->tv_nsec - start->tv_nsec) / 1000000.0;
}
/* Some work to measure */
void do_work(void) {
volatile long x = 0;
for (long i = 0; i < 100000000L; i++)
x += i;
}
int main(void) {
struct timespec t_start, t_end;
/* Start timer */
clock_gettime(CLOCK_MONOTONIC, &t_start);
do_work();
/* Stop timer */
clock_gettime(CLOCK_MONOTONIC, &t_end);
printf("do_work() took %.3f ms\n",
timespec_diff_ms(&t_start, &t_end));
/* Also measure CPU time specifically */
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t_start);
sleep(1); /* Sleep does NOT consume CPU time */
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t_end);
printf("CPU time during sleep(1): %.6f ms\n",
timespec_diff_ms(&t_start, &t_end));
/* Will be near 0 โ sleep does not burn CPU */
return 0;
}
/* Output:
do_work() took 245.871 ms
CPU time during sleep(1): 0.042 ms
*/
Get the CPU clock of any process by PID.
#define _XOPEN_SOURCE 600
#define _POSIX_C_SOURCE 200112L
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
clockid_t cid;
struct timespec ts;
pid_t target_pid;
if (argc < 2) {
/* Use own PID if no argument */
target_pid = getpid();
} else {
target_pid = (pid_t)atoi(argv[1]);
}
/* Get CPU-time clock ID for the target process */
if (clock_getcpuclockid(target_pid, &cid) != 0) {
perror("clock_getcpuclockid");
return 1;
}
/* Read the CPU time */
if (clock_gettime(cid, &ts) == -1) {
perror("clock_gettime");
return 1;
}
printf("PID %d has consumed %ld.%09ld s of CPU time\n",
(int)target_pid, ts.tv_sec, ts.tv_nsec);
/* Get resolution */
struct timespec res;
clock_getres(cid, &res);
printf("Clock resolution: %ld ns\n", res.tv_nsec);
return 0;
}
/* Compile: gcc -o cpu_clock cpu_clock.c -lrt
Usage: ./cpu_clock (own process)
./cpu_clock 1234 (PID 1234)
*/
CLOCK_REALTIME can jump backward (e.g., NTP sync, manual date set), causing negative elapsed times. CLOCK_MONOTONIC only increases โ it measures time since boot and is immune to clock adjustments.
Only CLOCK_REALTIME can be set, and it requires the CAP_SYS_TIME capability (typically root). CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID, and CLOCK_THREAD_CPUTIME_ID are not settable on Linux.
CLOCK_MONOTONIC measures wall-clock time (the process is sleeping, it still advances). CLOCK_PROCESS_CPUTIME_ID only advances when the process is actually running on CPU โ sleep(1) adds nothing to it.
Add -lrt to the compile command: gcc prog.c -o prog -lrt. Also define _POSIX_C_SOURCE 199309 before the includes.
The resolution (granularity) of the specified clock in a timespec structure. If it returns tv_nsec=1, the clock has nanosecond resolution. If tv_nsec=1000000 (1ms), it’s millisecond granularity.
