Linux计时函数是操作系统时间管理的重要组成部分,广泛应用于性能分析、任务调度、延时控制等场景,Linux提供了多种计时函数,涵盖高精度、低开销、跨平台等不同需求,理解这些函数的原理与适用场景,对于开发高效、稳定的系统级应用至关重要,本文将详细介绍Linux中常用的计时函数,包括其工作机制、使用方法及注意事项。

时间表示基础
在讨论计时函数前,需先了解Linux中的时间表示方式,Linux主要使用两种时间结构体:time_t和struct timespec。time_t是一个整数类型,表示自1970年1月1日00:00:00 UTC以来的秒数,精度为秒,常用于表示日历时间,而struct timespec则提供了更高精度的表示,包含tv_sec(秒)和tv_nsec(纳秒)两个成员,适用于需要微秒或纳秒级精度的场景。struct timeval(包含tv_sec和tv_usec,微秒精度)在部分旧接口中仍有使用,但新代码推荐优先采用struct timespec,因其支持纳秒精度且更符合POSIX标准。
高精度计时函数
clock_gettime()与clock_settime()
clock_gettime()是POSIX标准推荐的高精度计时函数,用于获取特定时钟的时间,其原型为:
#include <time.h> int clock_gettime(clockid_t clk_id, struct timespec *tp);
clk_id参数指定时钟类型,常用值包括:
CLOCK_REALTIME:实时时钟,受系统时间调整影响,用于获取日历时间;CLOCK_MONOTONIC:单调时钟,从系统启动开始计时,不受系统时间修改影响,适合测量耗时;CLOCK_PROCESS_CPUTIME_ID:进程CPU时间,统计进程使用的CPU时间(用户态+内核态);CLOCK_THREAD_CPUTIME_ID:线程CPU时间,统计线程使用的CPU时间。
clock_settime()可设置CLOCK_REALTIME的时间,但需root权限,通常用于时间同步场景。
示例:测量代码执行耗时
struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start);
// 待测代码
clock_gettime(CLOCK_MONOTONIC, &end);
double elapsed = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9;
printf("Elapsed time: %.6f seconds\n", elapsed);
gettimeofday()
gettimeofday()是传统的微秒级计时函数,虽非POSIX标准(但广泛支持),但在某些场景下仍被使用:
#include <sys/time.h> int gettimeofday(struct timeval *tv, struct timezone *tz);
tv参数返回当前时间(秒+微秒),tz已废弃,通常传入NULL,与clock_gettime()相比,gettimeofday()精度较低(微秒),且受系统时间调整影响,不推荐用于高精度计时。
进程/线程CPU时间统计
times()
times()函数用于获取进程及其子进程的CPU时间统计,返回类型为clock_t(通常为时钟滴答数):

#include <sys/times.h> clock_t times(struct tms *buf);
struct tms包含四个字段:
tms_utime:用户态CPU时间;tms_stime:内核态CPU时间;tms_cutime:子进程用户态CPU时间;tms_cstime:子进程内核态CPU时间。
需通过sysconf(_SC_CLK_TCK)获取每秒时钟滴答数,将时间转换为秒。
示例:
struct tms buf;
clock_t ticks = times(&buf);
double user_time = buf.tms_utime / (double)sysconf(_SC_CLK_TCK);
printf("User CPU time: %.2f seconds\n", user_time);
getrusage()
getrusage()可获取进程或线程的资源使用情况,包括CPU时间、内存占用等:
#include <sys/resource.h> int getrusage(int who, struct rusage *usage);
who参数可选RUSAGE_SELF(当前进程)、RUSAGE_CHILDREN(子进程)或RUSAGE_THREAD(当前线程,需定义_GNU_SOURCE)。ru_utime和ru_stime分别返回用户态和内核态CPU时间(秒+微秒)。
示例:
struct rusage usage;
getrusage(RUSAGE_SELF, &usage);
double sys_time = usage.ru_stime.tv_sec + usage.ru_stime.tv_usec / 1e6;
printf("System CPU time: %.2f seconds\n", sys_time);
休眠与定时器函数
休眠函数
nanosleep():高精度休眠函数,参数为struct timespec,支持纳秒级精度:#include <time.h> int nanosleep(const struct timespec *req, struct timespec *rem);
若被信号中断,剩余休眠时间通过
rem返回,可循环调用直至休眠完成。sleep():秒级休眠,底层调用nanosleep(),但中断后不会继续休眠:#include <unistd.h> unsigned int sleep(unsigned int seconds);
usleep():微秒级休眠(非标准,已废弃),推荐使用nanosleep()。
定时器函数
setitimer():设置进程定时器,支持三种类型:ITIMER_REAL:实时定时器,触发SIGALRM信号;ITIMER_VIRTUAL:用户态定时器,触发SIGVTALRM信号;ITIMER_PROF:用户态+内核态定时器,触发SIGPROF信号(包括系统调用时间)。#include <sys/time.h> int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value);
timer_create()/timer_settime():POSIX定时器接口,支持线程级定时器,可指定回调函数或信号,功能更灵活,适用于复杂定时场景。
计时函数的选择与注意事项
-
精度需求:
- 纳秒级精度:优先选择
clock_gettime(CLOCK_MONOTONIC); - 微秒级精度:
gettimeofday()或clock_gettime(); - 秒级精度:
time()或sleep()。
- 纳秒级精度:优先选择
-
单调性要求:
测量耗时时应避免使用CLOCK_REALTIME,因其受系统时间同步(如NTP)影响,可能导致时间回退。CLOCK_MONOTONIC是更安全的选择。
-
跨平台兼容性:
clock_gettime()是POSIX标准,现代Linux系统均支持;gettimeofday()在旧系统中更通用,但精度较低;Windows平台需使用QueryPerformanceCounter等替代接口。 -
信号中断处理:
nanosleep()和setitimer()可能被信号中断,需检查返回值并处理剩余时间或重试逻辑。 -
性能开销:
clock_gettime()和times()开销较低,适合频繁调用;getrusage()涉及内核态切换,开销较大,不宜用于高频统计。
Linux计时函数提供了从秒级到纳秒级的多维度时间管理能力,开发者需根据场景需求选择合适的接口,高精度耗时测量推荐clock_gettime(CLOCK_MONOTONIC),CPU时间统计可采用getrusage()或times(),休眠场景优先nanosleep(),需注意时钟单调性、信号中断及跨平台兼容性问题,以确保计时逻辑的准确性与稳定性,正确使用计时函数,不仅能提升系统性能分析的可靠性,还能为任务调度、资源控制等核心功能提供精准的时间基准。


















