【问题标题】:Converting jiffies to milli seconds将 jiffies 转换为毫秒
【发布时间】:2011-02-13 11:01:09
【问题描述】:

如何在 Linux 中手动将 jiffies 转换为毫秒,反之亦然?我知道内核 2.6 有一个功能,但我正在研究 2.4(家庭作业),虽然我查看了代码,但它使用了很多宏常量,我不知道它们是否在 2.4 中定义。

【问题讨论】:

  • 2.6内核使用的函数是什么?
  • @kaciula 请参阅 include/linux/jiffies.h 中的 jiffies_to_msecs()

标签: linux linux-kernel


【解决方案1】:

正如之前的回答所说,jiffies 增加的速率是固定的。

为接受jiffies 的函数指定时间的标准方法是使用常量HZ

这是 Hertz 的缩写,即每秒的滴答数。在计时器刻度设置为 1 毫秒的系统上,HZ=1000。某些发行版或架构可能会使用另一个数字(过去 100 很常见)。

为函数指定jiffies 计数的标准方法是使用HZ,如下所示:

schedule_timeout(HZ / 10);  /* Timeout after 1/10 second */

在大多数简单的情况下,这都能正常工作。

2*HZ     /* 2 seconds in jiffies */
HZ       /* 1 second in jiffies */
foo * HZ /* foo seconds in jiffies */
HZ/10    /* 100 milliseconds in jiffies */
HZ/100   /* 10 milliseconds in jiffies */
bar*HZ/1000 /* bar milliseconds in jiffies */

然而,最后两个有一点问题,因为在具有 10 毫秒计时器滴答的系统上,HZ/100 为 1,并且精度开始受到影响。您可能会在 0.0001 和 1.999 计时器滴答之间(基本上是 0-2 毫秒)之间得到延迟。如果您尝试在 10 毫秒滴答系统上使用 HZ/200,则整数除法会给您 0 jiffies!

所以经验法则是,对于微小的值(接近 1 jiffie 的值)使用 HZ 时要非常小心。

要换一种方式,你可以使用:

jiffies / HZ          /* jiffies to seconds */
jiffies * 1000 / HZ   /* jiffies to milliseconds */

你不应该期望比毫秒精度更好。

【讨论】:

  • 是否可以使用CLI获取HZ值?例如。在 2.6 内核上从 /proc/[pid]/stat 读取 utime 后,我可以轻松地将其转换为秒而不需要从 C 代码编译它吗?
  • 如果您从用户空间与 HZ 交互,请改用 USER_HZ。 'man 7 time' 说使用 sysconf(_SC_CLK_TCK) 来获取这个值。
  • 我没有看到从 shell 脚本中执行此操作的明显方法,但它通常是一个常量,除非您一直在对内核做不自然的事情。在 x86 上 USER_HZ 为 100。
【解决方案2】:

Jiffies 在 Linux 2.4 中是硬编码的。检查HZ 的定义,该定义在特定于架构的param.h 中定义。它通常是 100 Hz,即每(1 秒/100 刻 * 1000 毫秒/秒)10 毫秒一个刻。

这适用于 i386,HZ 在include/asm-i386/param.h 中定义。

include/linux/time.h 中有函数称为timespec_to_jiffiesjiffies_to_timespec,您可以在其中在struct timespecjiffies 之间来回转换:

    #define MAX_JIFFY_OFFSET ((~0UL >> 1)-1)

    static __inline__ unsigned long
    timespec_to_jiffies(struct timespec *value)
    {
            unsigned long sec = value->tv_sec;
            long nsec = value->tv_nsec;

            if (sec >= (MAX_JIFFY_OFFSET / HZ))
                    return MAX_JIFFY_OFFSET;
            nsec += 1000000000L / HZ - 1;
            nsec /= 1000000000L / HZ;
            return HZ * sec + nsec;
    }

    static __inline__ void
    jiffies_to_timespec(unsigned long jiffies, struct timespec *value)
    {
            value->tv_nsec = (jiffies % HZ) * (1000000000L / HZ);
            value->tv_sec = jiffies / HZ;
    }

注意:我在 2.4.22 版本中检查了此信息。

【讨论】:

    【解决方案3】:

    我在kernelnewbies 上找到了这个示例代码。确保你链接到-lrt

    #include <unistd.h>
    #include <time.h>
    #include <stdio.h>
    
    int main()
    {
        struct timespec res;
        double resolution;
    
        printf("UserHZ   %ld\n", sysconf(_SC_CLK_TCK));
    
        clock_getres(CLOCK_REALTIME, &res);
        resolution = res.tv_sec + (((double)res.tv_nsec)/1.0e9);
    
        printf("SystemHZ %ld\n", (unsigned long)(1/resolution + 0.5));
        return 0;
     }
    

    【讨论】:

      【解决方案4】:

      要使用 CLI 获取 USER_HZ 值(请参阅已接受答案下的 cmets):

      getconf CLK_TCK
      

      【讨论】:

        猜你喜欢
        • 2011-04-22
        • 1970-01-01
        • 1970-01-01
        • 2013-07-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-17
        • 2013-06-23
        相关资源
        最近更新 更多