服务器测评网
我们一直在努力

linux时间编程

Linux时间编程基础

Linux时间编程是系统开发中的重要组成部分,涉及时间的获取、格式化、转换以及定时任务等多个方面,本文将详细介绍Linux时间编程的核心概念、常用函数及实践应用,帮助开发者更好地理解和运用时间管理功能。

linux时间编程

Linux时间表示方式

Linux系统中有多种时间表示方式,主要分为以下几类:

  • 日历时间(Calendar Time):自1970年1月1日00:00:00 UTC以来的秒数,也称为Unix时间戳,通过time()函数获取,返回time_t类型值。
  • 处理器时间(Process Time):表示进程的CPU时间消耗,包括用户态和内核态时间,通过times()函数获取,返回clock_t类型值。
  • 高精度时间(High-Resolution Time):用于需要纳秒级精度的场景,如性能分析,通过clock_gettime()函数获取,支持CLOCK_REALTIME(实时时间)和CLOCK_MONOTONIC(单调时间)等时钟类型。

时间获取函数

1 time()函数

time()函数是最基础的时间获取函数,声明如下:

#include <time.h>  
time_t time(time_t *t);  
  • 若参数t非NULL,则将时间值同时存储在t指向的内存中;
  • 返回当前Unix时间戳,若失败则返回(time_t)-1

2 gettimeofday()函数

gettimeofday()函数提供微秒级精度,已逐渐被clock_gettime()取代,但部分旧代码仍在使用:

#include <sys/time.h>  
int gettimeofday(struct timeval *tv, struct timezone *tz);  
  • timeval结构体包含秒(tv_sec)和微秒(tv_usec)字段;
  • timezone参数通常设为NULL。

3 clock_gettime()函数

推荐使用的高精度时间函数:

#include <time.h>  
int clock_gettime(clockid_t clk_id, struct timespec *tp);  
  • clk_id指定时钟类型,如CLOCK_REALTIME(受系统时间调整影响)或CLOCK_MONOTONIC(不受系统时间影响,适合计算耗时);
  • timespec结构体包含秒(tv_sec)和纳秒(tv_nsec)字段。

时间格式化与转换

1 localtime()gmtime()

将Unix时间戳转换为可读的本地时间或UTC时间:

linux时间编程

#include <time.h>  
struct tm *localtime(const time_t *timep);  
struct tm *gmtime(const time_t *timep);  
  • 返回tm结构体指针,包含年、月、日、时、分、秒等字段;
  • 注意返回的指针指向静态内存,后续调用会覆盖前值。

2 strftime()函数

tm结构体格式化为字符串:

#include <time.h>  
size_t strftime(char *str, size_t maxsize, const char *format, const struct tm *timeptr);  
  • format参数支持格式化占位符,如%Y(四位年份)、%m(月份)、%d(日期)等;
  • 示例:strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm);

3 mktime()函数

tm结构体转换回Unix时间戳:

#include <time.h>  
time_t mktime(struct tm *timeptr);  
  • 会自动处理tm结构体的字段越界问题(如月份为13时自动进位);
  • 返回转换后的时间戳,若失败返回(time_t)-1

定时器与延时

1 sleep()usleep()

简单的延时函数:

#include <unistd.h>  
unsigned int sleep(unsigned int seconds);  
#include <unistd.h>  
int usleep(useconds_t usec);  
  • sleep()以秒为单位;usleep()以微秒为单位(已废弃,推荐使用nanosleep())。

2 nanosleep()

高精度延时函数:

#include <time.h>  
int nanosleep(const struct timespec *req, struct timespec *rem);  
  • req指定延时时间(秒和纳秒);
  • 若被信号中断,剩余时间会写入rem参数,便于继续延时。

3 setitimer()timer_create()

用于设置周期性定时器:

linux时间编程

  • setitimer():为进程设置定时器,支持ITIMER_REAL(实时时钟)、ITIMER_VIRTUAL(用户态CPU时间)等类型;
  • timer_create():创建 POSIX 定时器,可绑定特定信号处理函数。

实践应用场景

1 日志时间戳

在日志记录中,需将时间戳格式化为可读字符串:

time_t now = time(NULL);  
struct tm *tm = localtime(&now);  
char time_str[32];  
strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", tm);  
printf("[%s] Log message\n", time_str);  

2 性能测量

使用clock_gettime()计算代码块执行时间:

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);  

3 定时任务调度

结合timer_create()和信号处理实现周期性任务:

timer_t timer_id;  
struct sigevent sev;  
sev.sigev_notify = SIGEV_SIGNAL;  
sev.sigev_signo = SIGRTMIN;  
timer_create(CLOCK_REALTIME, &sev, &timer_id);  
struct itimerspec its = {0};  
its.it_interval.tv_sec = 1; // 每秒触发一次  
its.it_value.tv_sec = 1;    // 首次触发延迟1秒  
timer_settime(timer_id, 0, &its, NULL);  

注意事项

  • 线程安全localtime()gmtime()是非线程安全的,建议使用localtime_r()gmtime_r()替代;
  • 时钟选择CLOCK_REALTIME可能受系统时间调整影响,计算耗时时应优先使用CLOCK_MONOTONIC
  • 精度限制:不同硬件平台对高精度时间的支持程度不同,需通过clock_getres()查询系统精度。

Linux时间编程提供了丰富的函数和接口,从基础的秒级时间戳到纳秒级高精度计时,能够满足不同场景的需求,开发者需根据实际应用选择合适的时间表示方式和函数,并注意线程安全与精度问题,通过合理运用时间编程技术,可以高效实现日志记录、性能优化和定时任务等功能。

赞(0)
未经允许不得转载:好主机测评网 » linux时间编程