Linux时间处理函数
时间类常用结构体
time_t 秒级
time_t 是一个整数类型,用于表示从 Unix 纪元(1970 年 1 月 1 日 00:00:00 UTC)开始的秒数。它是时间戳的标准表示形式。
time_t rawtime;
time(&rawtime); // 获取当前时间的时间戳
struct timespec 秒级和纳秒级结构体
struct timespec 用于表示高精度的时间,包括秒和纳秒。
struct timespec {
time_t tv_sec; // 秒
long tv_nsec; // 纳秒
};
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts); // 获取当前时间
struct timeval 秒级和微秒级结构体
struct timeval 用于表示微秒级的时间,常用于计时和超时操作。
struct timeval {
time_t tv_sec; // 秒
suseconds_t tv_usec; // 微秒
};
struct timeval tv;
gettimeofday(&tv, NULL); // 获取当前时间
struct tm 转换分解后的时间结构体
struct tm 代表一个分解的时间结构体,包含了年、月、日、小时、分钟、秒等各个组成部分。通常通过 localtime 或 gmtime 从 time_t 类型的时间戳转换而来。
#include <time.h>
struct tm {
int tm_sec; // 秒 [0, 60]
int tm_min; // 分钟 [0, 59]
int tm_hour; // 小时 [0, 23]
int tm_mday; // 月份中的天数 [1, 31]
int tm_mon; // 月份 [0, 11]
int tm_year; // 自 1900 年以来的年数
int tm_wday; // 星期几 [0, 6] (周日为 0)
int tm_yday; // 一年中的第几天 [0, 365]
int tm_isdst; // 夏令时标志
};
struct tm * timeinfo;
time_t rawtime;
time(&rawtime);
timeinfo = localtime(&rawtime); // 转换为本地时间
struct itimerspec 定时器的结构体值
struct itimerspec 用于表示定时器的值,包括定时器的到期时间和周期。
struct itimerspec {
struct timespec it_interval; // 定时器重复触发的时间间隔
struct timespec it_value; // 定时器首次触发前等待的时间
};
struct itimerspec timer;
// 设置定时器
timer.it_value.tv_sec = 5; // 定时器首次触发前等待的时间
timer.it_value.tv_nsec = 0; // 纳秒部分
timer.it_interval.tv_sec = 1; // 定时器重复触发的时间间隔
timer.it_interval.tv_nsec = 0; // 纳秒部分
示例:使用select监听定时文件描述符是否到达时间
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/timerfd.h>
#include <time.h>
#include <string.h>
#include <inttypes.h>
#include <sys/select.h>
int main() {
int timerfd;
struct itimerspec timer;
char buf[8]; // 事件通知的大小为 8 字节
uint64_t count; // 存储读取的计数值
// 创建定时器文件描述符
timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
if (timerfd == -1) {
perror("timerfd_create");
exit(EXIT_FAILURE);
}
// 设置定时器首次触发前等待的时间(it_value)和重复触发的时间间隔(it_interval)
timer.it_value.tv_sec = 5; // 定时器首次触发前等待 5 秒
timer.it_value.tv_nsec = 0; // 纳秒部分
timer.it_interval.tv_sec = 3; // 定时器重复触发的时间间隔为 1 秒
timer.it_interval.tv_nsec = 0; // 纳秒部分
if (timerfd_settime(timerfd, 0, &timer, NULL) == -1) {
perror("timerfd_settime");
close(timerfd);
exit(EXIT_FAILURE);
}
fd_set fds;
struct timeval timeout;
// 监听定时器事件
while (1) {
FD_ZERO(&fds);
FD_SET(timerfd, &fds);
timeout.tv_sec = 1; // 超时时间为 1 秒
timeout.tv_usec = 0;
if (select(timerfd + 1, &fds, NULL, NULL, &timeout) == -1) {
perror("select");
close(timerfd);
exit(EXIT_FAILURE);
}
if (FD_ISSET(timerfd, &fds)) {
ssize_t n = read(timerfd, buf, sizeof(buf));
if (n != sizeof(buf)) {
perror("read");
close(timerfd);
exit(EXIT_FAILURE);
}
memcpy(&count, buf, sizeof(count));
printf("Timer expired, count: %" PRIu64 "\n", count);
}
}
close(timerfd);
return 0;
}
localtime获取的数据存储问题
localtime获得的时间数据存储在栈上的固定位置,每次调用该函数,都会更新该值,为了防止出错,需要拷贝出来,示例:
#include <string.h>
#include <inttypes.h>
#include <sys/select.h>
int main() {
time_t time_now;
struct tm* tm;
time(&time_now);
tm = localtime(&time_now);
printf("第一次:%d-%d-%d %d:%d:%d\n", tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
sleep(10);
time(&time_now);
localtime(&time_now);
printf("第二次:%d-%d-%d %d:%d:%d\n", tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
return 0;
}
结果: