对于linux下的编程,无论是用户态还是内核态,时间获取都是经常需要使用到的。以下分别从用户态和内核态整理了几个常用的时间获取接口,供编写代码时快速查阅。
#include
int clock_gettime (clockid_t __clock_id, struct timespec *__tp);
作用
:根据系统时钟的类型,获取当前时间__clock_id
:系统时钟的类型。常用取值:
__tp
: 存放当前的时间。返回值
:成功则返回0,失败则返回-1timespec
结构体:
struct timespec
{
__time_t tv_sec; /* Seconds. 秒 */
__syscall_slong_t tv_nsec; /* Nanoseconds. 纳秒*/
};
示例:
#include
#include
#include
long long get_clock_sys_time_ns(void)
{
struct timespec tp;
long long time_ns = 0;
clock_gettime(CLOCK_MONOTONIC, &tp);
time_ns = (long long)tp.tv_sec * 1000000000 + tp.tv_nsec;
return time_ns;
}
int main(void)
{
struct timespec tp;
///< 获取从1970年1月1日到目前的时间
memset(&tp, 0, sizeof(struct timespec));
clock_gettime(CLOCK_REALTIME, &tp);
printf("clock_id = CLOCK_REALTIME, sec = %ld, nsec = %ld\n", tp.tv_sec, tp.tv_nsec);
///< 获取系统启动时间
memset(&tp, 0, sizeof(struct timespec));
clock_gettime(CLOCK_MONOTONIC, &tp);
printf("clock_id = CLOCK_MONOTONIC, sec = %ld, nsec = %ld, sys_time = %lld ns\n", tp.tv_sec, tp.tv_nsec, get_clock_sys_time_ns());
///< 获取本进程运行时间
memset(&tp, 0, sizeof(struct timespec));
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp);
printf("clock_id = CLOCK_PROCESS_CPUTIME_ID, sec = %ld, nsec = %ld\n", tp.tv_sec, tp.tv_nsec);
///< 获取本线程运行时间
memset(&tp, 0, sizeof(struct timespec));
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp);
printf("clock_id = CLOCK_THREAD_CPUTIME_ID, sec = %ld, nsec = %ld\n", tp.tv_sec, tp.tv_nsec);
return 0;
}
#include
int gettimeofday(struct timeval *tv, struct timezone *tz);
作用
:获取当前时间(从1970年1月1日到目前的时间)tv
:当前UTC时间tz
:当前时区信息返回值
:成功则返回0,失败则返回-1timeval结构体:
struct timeval
{
__time_t tv_sec; /* Seconds. 秒*/
__suseconds_t tv_usec; /* Microseconds. 微秒*/
};
timezone结构体:
struct timezone
{
int tz_minuteswest; /* Minutes west of GMT. 和Greenwich时间差了多少分钟 */
int tz_dsttime; /* Nonzero if DST is ever in effect. 日光节约时间的状态 */
};
示例:
#include
#include
#include
long long get_sys_time_ms(void)
{
long long time_ms = 0;
struct timeval tv;
gettimeofday(&tv, NULL);
time_ms = ((long long)tv.tv_sec*1000000 + tv.tv_usec) / 1000;
return time_ms;
}
int main(void)
{
///< 获取系统时间
printf("sys_time = %lld ms\n", get_sys_time_ms());
return 0;
}
#include
time_t time(time_t *tloc);
作用
:获取1970-01-01 00:00:00 +0000至今的秒数(UTC)tloc
:返回的秒存储指针返回值
:成功则返回秒数,失败则返回-1,错误原因存在errno中。time_t的类型:
typedef long time_t;
示例:
#include
#include
time_t get_utc_time(void)
{
return time(NULL);
}
int main(int argc, char **argv)
{
time_t utc_time = get_utc_time();
printf("utc_time = %ld s\n", utc_time);
return 0;
}
#include
struct tm *localtime(const time_t *timep);
作用
:将time_t类型的时间转换为struct tm类型的时间timep
:当前UTC秒数返回值
:返回当地时间tm结构体:
struct tm
{
int tm_sec; /* Seconds. [0-60] (1 leap second) */
int tm_min; /* Minutes. [0-59] */
int tm_hour; /* Hours. [0-23] */
int tm_mday; /* Day. [1-31] */
int tm_mon; /* Month. [0-11] 注意:0代表1月,以此类推*/
int tm_year; /* Year - 1900. 该值为实际年份减去1900*/
int tm_wday; /* Day of week. [0-6] 注意:0代表星期一,以此类推*/
int tm_yday; /* Days in year.[0-365] 从每年的1月1日开始的天数,其中0代表1月1日,以此类推*/
int tm_isdst; /* DST. [-1/0/1] 夏玲时标识符*/
};
示例:
#include
#include
time_t get_utc_time(void)
{
return time(NULL);
}
int main(int argc, char **argv)
{
time_t utc_time = get_utc_time();
printf("utc_time = %ld s\n", utc_time);
struct tm *local_tm = localtime(&utc_time);
printf("local time = %.4d-%.2d-%.2d %.2d:%.2d:%.2d\n", local_tm->tm_year + 1900,
local_tm->tm_mon + 1,
local_tm->tm_mday,
local_tm->tm_hour,
local_tm->tm_min,
local_tm->tm_sec);
return 0;
}
#include
struct tm *localtime_r(const time_t *timep, struct tm *result);
作用
:将time_t类型的时间转换为struct tm类型的时间timep
:当前UTC秒数result
:当地时间返回值
:返回当地时间注:
localtime不是一个线程安全的函数。对于实时性要求较高的系统,多个线程同时调用localtime,可能会造成数据被覆盖。使用localtime_r来替代。
示例:
#include
#include
time_t get_utc_time(void)
{
return time(NULL);
}
int main(int argc, char **argv)
{
time_t utc_time = get_utc_time();
printf("utc_time = %ld s\n", utc_time);
struct tm result;
struct tm *local_tm = localtime_r(&utc_time, &result);
printf("local time = %.4d-%.2d-%.2d %.2d:%.2d:%.2d\n", local_tm->tm_year + 1900,
local_tm->tm_mon + 1,
local_tm->tm_mday,
local_tm->tm_hour,
local_tm->tm_min,
local_tm->tm_sec);
printf("result time = %.4d-%.2d-%.2d %.2d:%.2d:%.2d\n", result.tm_year + 1900,
result.tm_mon + 1,
result.tm_mday,
result.tm_hour,
result.tm_min,
result.tm_sec);
return 0;
}
#include
struct tm *gmtime(const time_t *timep);
作用
:返回tm结构的GMT时间(UTC时间)timep
:当前UTC秒数返回值
:返回当地时间例子:
#include
#include
time_t get_utc_time(void)
{
return time(NULL);
}
int main(int argc, char **argv)
{
time_t utc_time = get_utc_time();
printf("utc_time = %ld s\n", utc_time);
struct tm *gmt_tm = gmtime(&utc_time);
printf("gmt time = %.4d-%.2d-%.2d %.2d:%.2d:%.2d\n", gmt_tm->tm_year + 1900,
gmt_tm->tm_mon + 1,
gmt_tm->tm_mday,
gmt_tm->tm_hour,
gmt_tm->tm_min,
gmt_tm->tm_sec);
return 0;
}
localtime和gmtime的区别:
localtime和gmtime都是C语言中的函数,用于将time_t类型的时间转换为struct tm类型的时间。它们的区别在于,gmtime将time_t转换为UTC时间,即世界标准时间,而localtime将time_t转换为本地时间。
例子:使用gmtime与localtime接口返回的小时数来计算当地时区
#include
#include
time_t get_utc_time(void)
{
return time(NULL);
}
int main(int argc, char **argv)
{
time_t utc_time = get_utc_time();
printf("utc_time = %ld s\n", utc_time);
struct tm *gmt_tm = gmtime(&utc_time);
printf("gmt time = %.4d-%.2d-%.2d %.2d:%.2d:%.2d\n", gmt_tm->tm_year + 1900,
gmt_tm->tm_mon + 1,
gmt_tm->tm_mday,
gmt_tm->tm_hour,
gmt_tm->tm_min,
gmt_tm->tm_sec);
int gmt_hour = gmt_tm->tm_hour;
struct tm *local_tm = localtime(&utc_time);
printf("local time = %.4d-%.2d-%.2d %.2d:%.2d:%.2d\n", local_tm->tm_year + 1900,
local_tm->tm_mon + 1,
local_tm->tm_mday,
local_tm->tm_hour,
local_tm->tm_min,
local_tm->tm_sec);
int local_hour = local_tm->tm_hour;
int local_time_zone = local_hour - gmt_hour;
if (local_time_zone < -12)
{
local_time_zone += 24;
}
else if (local_time_zone > 12)
{
local_time_zone -= 24;
}else{}
printf("local_time_zone = %d\n", local_time_zone);
return 0;
}
#include
void do_gettimeofday(struct timeval *tv);
作用
:与C标准库中gettimeofday()用法相同tv
:当前UTC时间timeval结构体:
struct timeval
{
__time_t tv_sec; /* Seconds. 秒*/
__suseconds_t tv_usec; /* Microseconds. 微秒*/
};
示例:
#include
#include
MODULE_LICENSE("GPL");
int __init do_gettimeofday_init(void)
{
printk("do_gettimeofday test begin.\n");
struct timeval now=
{
.tv_sec=0,
.tv_usec=0
}; //声明一个变量
do_gettimeofday(&now); //调用函数获取时间,此时间是距离1970-01-01 00:00:00的时间
/*显示当前时间差*/
printk("the seconds of the day is: %ld\n", now.tv_sec); //秒数
printk("the microseconds of the day is: %ld\n", now.tv_usec); //微秒数
printk("do_gettimeofday test over.\n");
return 0;
}
void __exit do_gettimeofday_exit(void)
{
printk("Goodbye do_gettimeofday test\n");
}
module_init(do_gettimeofday_init);
module_exit(do_gettimeofday_exit);
3.2.基于ktime_t格式的时间
参考:linux kernel时钟获取
#include "linux/ktime.h"
ktime_t ktime_get(void);
作用
:获取的是CLOCK_MONOTONIC时间。通过ktime_get获取的时间是不统计设备休眠时间的,并且这个时间统计的起始点则是设备启动后。
返回值
:返回ktime_t格式的数据类型,单位为纳秒。
ktime_t的定义:
typedef s64 ktime_t;
示例:
time_test_drv_init
ktime_t curTime = 0;
curTime = ktime_get();
TIME_TEST_INFO("ktime_get:%lld ns", curTime);
#include "linux/time64.h"
void ktime_get_ts64(struct timespec64 *ts);
作用
:和ktime_get的功能是完全一样的,区别在于对时间的表示数据类型由ktime_t变成了timespec64。
timespec64的定义如下:
struct timespec64 {
time64_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
timespec64中包含了秒和纳秒,相对ktime_t纳秒这个时间表示更加适合人类查看.
示例:
static void show_time_ts64(const char* caller, const int line, const struct timespec64 *curTimeTs)
{
pr_info("%s,%d:%lld s %ld ns\n", caller, __LINE__, curTimeTs->tv_sec, curTimeTs->tv_nsec);
}
time_test_drv_init
struct timespec64 curTimeTs;
ktime_get_boottime_ts64(&curTimeTs);
show_time_ts64(__func__, __LINE__, &curTimeTs);
3.ktime_get_boottime()
static inline ktime_t ktime_get_boottime(void);
作用
:ktime_get_boottime获取的时间和ktime_get最大的不同是其包含了设备进入休眠的时间,其这个时间统计的起始点也是设备启动后。
返回值
:返回值类型为ktime_t,单位为纳秒。
示例:
time_test_drv_init
ktime_t curTime = 0;
curTime = ktime_get_boottime();
TIME_TEST_INFO("ktime_get_boottime:%lld ns", curTime);
4.ktime_get_boottime_ts()
void ktime_get_boottime_ts64(struct timespec64 *);
作用
:ktime_get_boottime_ts相对于ktime_get_boottime的功能是完全一样的,区别在于对时间的表示数据类型由ktime_t变成了timespec64。
5.ktime_get_real()
ktime_t ktime_get_real(void);
作用
:ktime_get_real获取的时间的起点不是设备的启动时间点了,而是相对UTC的,即从1970开始。
示例:
time_test_drv_init
ktime_t curTime = 0;
curTime = ktime_get_real();
TIME_TEST_INFO("ktime_get_real:%lld ns", curTime);
6.ktime_get_real_ts()
void ktime_get_real_ts(struct timespec64 *);
作用
:ktime_get_real_ts相对于ktime_get_real的功能是完全一样的,区别在于对时间的表示数据类型由ktime_t变成了timespec64。
示例:
time_test_drv_init
struct timespec64 curTimeTs;
ktime_get_real_ts64(&curTimeTs);
void delay_us(uint32_t nus)
{
volatile uint32_t startts, endts, ts;
ts = nus;
startts = get_time_us();
endts = startts + ts;
if (endts > startts)
{
while (get_time_us() < endts);
}
else
{
while (get_time_us() > endts);
while (get_time_us() < endts);
}
}