Linux 内核 | 内核的时间函数


简介

遇到一个小需求:测量内核中函数执行时间,需要获取当前的系统时间来计算时间差。

网络上很多资料都还停留在使用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));

参考文档

  1. Linux内核中的时间函数
  2. Difference between CLOCK_REALTIME and CLOCK_MONOTONIC?
  3. What is the difference between CLOCK_MONOTONIC & CLOCK_MONOTONIC_RAW?

声明:一丁点儿|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - Linux 内核 | 内核的时间函数


勿在浮沙筑高台,每天进步一丁点儿!