【问题标题】:Timing/Clocks in the Linux KernelLinux 内核中的计时/时钟
【发布时间】:2019-03-08 01:09:50
【问题描述】:

我正在编写一个设备驱动程序,并想对几段代码进行基准测试,以了解我可能遇到瓶颈的地方。因此,我想对几段代码进行计时。

在用户空间中,我习惯于使用clock_gettime()CLOCK_MONOTONIC。查看内核源代码(请注意,我正在运行内核 4.4,但最终会升级),看来我有几个选择:

  • getnstimeofday()
  • getrawmonotonic()
  • get_monotonic_coarse()
  • getboottime()

为方便起见,我编写了一个函数(见下文)来获取当前时间。我目前正在使用getrawmonotonic(),因为我认为这就是我想要的。我的函数将当前时间返回为ktime_t,因此我可以使用ktime_sub() 来获取两次之间的经过时间。

static ktime_t get_time_now(void) {
   struct timespec time_now;
   getrawmonotonic(&time_now);
   return timespec_to_ktime(time_now);
}

鉴于可用的高分辨率时钟功能(jiffies 不适用于我),对于我的给定应用程序来说,最好的功能是什么?更一般地说,我对有关这些功能和底层时钟的任何/所有文档感兴趣。首先,我很好奇时钟是否受到任何时间调整的影响以及它们的时代是什么。

【问题讨论】:

    标签: c linux linux-kernel


    【解决方案1】:

    您是否将直接在内核中进行的测量与在用户空间中进行的测量进行比较?我想知道您选择在内核中使用CLOCK_MONOTONIC_RAW 作为时基,因为您选择在用户空间中使用CLOCK_MONOTONIC。如果您正在内核中寻找一个类似且非粗略的函数,它返回CLOCK_MONOTONIC(而不是CLOCK_MONOTONIC_RAW)时间,请查看ktime_get_ts()

    您也可以使用原始内核刻度来测量您要测量的内容(而不是代表多个内核刻度的 jiffies),但我不知道该怎么做.

    一般来说,如果您想查找有关 Linux 计时的文档,您可以查看 Documentation/timers/timekeeping.txt。通常,当我试图弄清楚内核计时时,不幸的是,我也只是花大量时间阅读time/ 中的内核源代码(time/timekeeping.c 是您现在正在考虑使用的大多数功能......不是很好的评论,但你可以花一点时间把你的头绕起来)。如果您在学习后感到无私,请记住更新文档是为内核做出贡献的好方法:)

    最后关于时钟如何受时序调整影响以及使用哪些时期的问题:

    CLOCK_REALTIME 总是从 1970 年 1 月 1 日午夜开始(俗称 Unix 纪元),如果不存在 RTC 或者它尚未由用户空间中的应用程序设置(或者我猜是内核模块如果你想变得奇怪)。通常设置这个的用户空间应用程序是 ntp 守护进程,ntpdchrony 或类似的。它的值表示自 1970 年以来经过的秒数。

    CLOCK_MONTONIC 表示自设备启动以来经过的秒数,如果设备在xCLOCK_MONOTONIC 值处挂起,当它恢复时,它会在CLOCK_MONOTONIC 设置为@987654336 的情况下恢复@也一样。古代内核不支持它。

    CLOCK_BOOTTIME 类似于CLOCK_MONOTONIC,但在暂停/恢复期间添加了时间——因此,如果您在xCLOCK_BOOTTIME 值暂停5 秒,您将返回一个CLOCK_BOOTTIME 的值是 x+5。旧内核不支持它(它的支持是在 CLOCK_MONOTONIC 之后出现的)。

    完整的 NTP 守护进程(不是 SNTP 守护进程——这是一个更轻量级且创建精度更低的协议)设置系统时钟,或CLOCK_REALTIME,使用settimeofday() 进行大调整(“步数”或“跳跃” ) -- 这些会立即影响CLOCK_REALTIME 的总值,并使用adjtime() 进行较小的调整(“回转”或“倾斜”)——这些会影响CLOCK_REALTIME 每个CPU 时钟周期向前移动的速率。我认为对于某些架构,您实际上可以通过某种方式调整 CPU 时钟周期,如果可能的话,内核会以这种方式实现adjtime(),但不要引用我的话。从内核的大部分角度和用户空间的角度来看,这实际上并不重要。

    CLOCK_MONOTONICCLOCK_BOOTTIME 和所有其他朋友都以与CLOCK_REALTIME 相同的速度旋转,这在大多数情况下实际上是相当方便的。它们不受CLOCK_REALTIME 中步骤的影响,仅受 slews 影响。

    CLOCK_MONOTONIC_RAWCLOCK_BOOTTIME_RAW 和朋友不会以与CLOCK_REALTIMECLOCK_MONOTONICCLOCK_BOOTIME 相同的速度进行转换。我想这有时很有用。

    Linux 为用户空间提供了一些进程/线程特定的时钟(CLOCK_PROCESS_CPUTIME_IDCLOCK_THREAD_CPUTIME_ID),我对此一无所知。我不知道它们是否可以在内核中轻松访问。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-27
      • 1970-01-01
      • 1970-01-01
      • 2016-02-25
      • 2014-04-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多