简介
遇到一个小需求:测量内核中函数执行时间,需要获取当前的系统时间来计算时间差。
网络上很多资料都还停留在使用struct timeval
和对应的函数void do_gettimeofday(struct timeval *tv);
来获取时间。在我使用的内核版本(Linux kernel 5.10.20)已经不存在相应的接口了。因此这里记录一下系统时间获取的方式,避免再次忘记(记笔记的重要性)。
API
在最新内核中获取当前系统时间的API如下(函数定义在 kernel/time/timekeeping.c 文件),基于的结构体也从timeval
变为struct timespec64
(定义在 include/linux/time64.h 文件)
void ktime_get_ts64(struct timespec64 *ts); //CLOCK_MONOTONIC
void ktime_get_real_ts64(struct timespec64 *); //CLOCK_REALTIME
void ktime_get_boottime_ts64(struct timespec64 *);//CLOCK_BOOTTIME
void ktime_get_raw_ts64(struct timespec64 *); //CLOCK_MONOTONIC_RAW
以上 4 个 API 实际上表明 Linux 提供了 4 种时间:
- CLOCK_REALTIME:以 1970年1月1日… 为起点,随 time-of-day 被修改的时候而改变(例如,NTP网络时间协议)
- CLOCK_MONOTONIC :代表从过去某个固定的时间点开始的绝对的逝去时间,它不受任何系统time-of-day时钟修改的影响,在没有机器重启的情况下,若你想计算出两个事件发生的间隔时间的话,那么它将是最好的选择。但是 CLOCK_MONOTONIC 在系统 suspend 时并不会增长。
- CLOCK_BOOTTIME:以系统启动的时间为起点,在系统 suspend 的时候该时钟依然增长。
- CLOCK_MONOTONIC_RAW:与 CLOCK_MONOTONIC 相似,虽然 CLOCK_MONOTONIC 不受 NTP 的影响,但是随着 NTP 了解本地振荡器和上游服务器之间存在错误时,它的频率确实会发生变化,而 CLOCK_MONOTONIC_RAW 完全取决于本地振荡器。
实例
以 ktime_get_boottime_ts64()
函数为例测量某段 code 的执行时间。头文件 #include <linux/timex.h> 对 struct timespec64
的一些处理函数声明在 include/linux/time64.h 文件中,例如下面 code 使用的timespec64_sub()
和timespec64_to_ns()
。
//
#include <linux/timex.h>
struct timespec64 ts_start, ts_end;
struct timespec64 ts_delta;
ktime_get_boottime_ts64(&ts_start);
// ...函数逻辑
ktime_get_boottime_ts64(&ts_end);
// 计算时间差
ts_delta = timespec64_sub(ts_end, ts_start);
pr_notice("[DB] time consumed: %lld (ns)\n",timespec64_to_ns(&ts_delta));
Comments | NOTHING