Linux内核中定义了jiffies变量来记录从系统启动到当前时刻系统时钟所产生的tick数。jiffies变量是一个无符号整型数值,即unsigned long类型。它的声明如下(在 include/linux/jiffies.h 中):

extern u64 __jiffy_data jiffies_64;

由此可见,jiffies变量在32位系统中的长度是32位,在64位系统中长度为64位。

在32位系统中,HZ=1000时,jiffies只要约 49.7 天就会发生回绕(溢出),而回绕会给内核时间度量带来混乱和其他潜在的问题。因此,在Linux2.6内核中引入一个64位的无符号整型变量jiffies_64,内核中计时都是对jiffies_64进行递增。jiffies_64也在 include/linux/jiffies.h 中有声明:

extern u64 __jiffy_data jiffies_64;

其中,u64为unsigned long long类型。在 1000HZ 的情况下,该变量运行几亿年都不会发出回绕,从而有效防止了回绕可能引起的问题。这就是定义jiffies_64变量的原因。

那么,既然在32位机器上也是用64位计时,为什么不直接把jiffies变量改为u64类型呢?或者说干脆用jiffies_64来代替jiffies呢?根本原因是为了保持兼容性及访问效率!从兼容性方面来看,大量的驱动程序使用jiffies 变量来进行一些与时间相关的操作,所以内核中需要保留该变量,以免影响系统功能;从访问效率方面来看,因为在 32 位的系统中访问 64 位的 jiffies_64 变量需要进行两次内存访问,一来访问速度没有直接访问 jiffies 来得快,二来无法保证原子性(在两次内存访问中间可能会被中断,从而造成读取数据的不正确)。但是当真的需要访问jiffies_64变量时(一般在驱动程序中很少访问 jiffies_64,通常只有内核核心代码才会访问),内核也提供了 get_jiffies_64() 函数来访问。该函数采用了加锁机制(xtime_lock),以防止读取数据的不正确。

虽然,jiffies和jiffies_64是两个变量,但它们最终指向相同的地址,只是jiffies取的是jiffies_64变量的低32位。这种效果通过链接程序实现的。通过链接器(ld)脚本 vmlinux.lds (x86 上位于 arch/x86/kernel下) 可看到:

 OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(phys_startup_32)
jiffies = jiffies_64;

其中最后一条语句的作用是,让符号jiffies的地址等于符号jiffies_64的地址,即让jiffies变量占用 jiffies_64 的低 32 位。这里涉及到链接器中的一个重要的概念:

在目标文件内定义的符号可以在链接器脚本内赋值,此时该符号应被定义为全局的。每个符号都对应一个地址,在链接器中的赋值(=)操作就是更改这个符号对应的地址。

所以,这和 C 语言中的等于(=)是完全不同的概念:C 中是赋值,链接器中是改变地址。

另外,jiffies_64 变量会被初始化为 INITIAL_JIFFIES ,该值定义在文件 include/linux/jiffies.h 中:

 /*
* Have the 32 bit jiffies value wrap 5 minutes after boot
* so jiffies wrap bugs show up earlier.
*/
#define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ))

这样,就使得系统在启动后 5 分钟时发生 jiffies 回绕。这么做有利于及早暴露设备驱动程序中可能的 jiffies 回绕导致的逻辑错误,方便驱动程序的开发。

参考文献:

【1】:http://www.groad.net/bbs/thread-3352-1-1.html

【2】:http://bbs.csdn.net/topics/320154818

【3】:《Linux内核设计与实现(原书第3版)》第11章

Linux内核时间管理(二)——jiffies与jiffies_64释疑的更多相关文章

  1. Linux内核电源管理综述

    资料:http://blog.csdn.net/bingqingsuimeng/article/category/1228414http://os.chinaunix.net/a2006/0519/1 ...

  2. Linux内核分析(二)----内核模块简介|简单内核模块实现

    原文:Linux内核分析(二)----内核模块简介|简单内核模块实现 Linux内核分析(二) 昨天我们开始了内核的分析,网上有很多人是用用源码直接分析,这样造成的问题是,大家觉得很枯燥很难理解,从某 ...

  3. Linux内核内存管理算法Buddy和Slab: /proc/meminfo、/proc/buddyinfo、/proc/slabinfo

    slabtop cat /proc/slabinfo # name <active_objs> <num_objs> <objsize> <objpersla ...

  4. Linux内核学习笔记二——进程

    Linux内核学习笔记二——进程   一 进程与线程 进程就是处于执行期的程序,包含了独立地址空间,多个执行线程等资源. 线程是进程中活动的对象,每个线程都拥有独立的程序计数器.进程栈和一组进程寄存器 ...

  5. Linux命令-磁盘管理(二)

    Linux命令-磁盘管理(二) Linux mmount命令 Linux mmount命令用于挂入MS-DOS文件系统. mmount为mtools工具指令,可根据[mount参数]中的设置,将磁盘内 ...

  6. linux内核--内存管理(二)

    一.进程与内存     所有进程(执行的程序)都必须占用一定数量的内存,它或是用来存放从磁盘载入的程序代码,或是存放取自用户输入的数据等等.不过进程对这些内存的管理方式因内存用途不一而不尽相同,有些内 ...

  7. 在linux内核中获得比jiffies精度更高的时间值【转】

    转自:http://blog.chinaunix.net/uid-20672257-id-2831219.html 内核一般通过jiffies值来获取当前时间.尽管该数值表示的是自上次系统启动到当前的 ...

  8. linux内核学习之二 一个精简内核的分析(基于时间片轮转)

    一   实验过程及效果 1.准备好相关的代码,分别是mymain.c,mypcb.h,myinterrupt.c ,如下图,make make成功: 在qemu创建的虚拟环境下的运行效果:(使用的命令 ...

  9. 【原创】解BUG-xenomai内核与linux内核时间子系统之间存在漂移

    版权声明:本文为本文为博主原创文章,转载请注明出处.如有问题,欢迎指正.博客地址:https://www.cnblogs.com/wsg1100/ 一.问题起源 何为漂移?举个例子两颗32.768kH ...

随机推荐

  1. 隐马尔可夫模型(HMM)原理

    本文主要讨论隐马尔科夫模型的三大要素,三大假设和三大问题. 1.引入 隐马尔可夫模型是一个关于时序的概率模型,它描述了一个由隐藏的马尔可夫链生成状态序列,再由状态序列生成观测序列的过程.其中,状态之间 ...

  2. 简单的cd命令

    cd ~ :进入home目录 cd   :进入home目录 cd - :进入上一个目录 cd /home/venn : 进入指定目录 当然,我想说的是cd(不加任何路径),进入home目录

  3. 选项卡(TabHost)的功能与用法

    TabHost是一种非常实用的组件,TabHost可以很方便地在窗口上放置多个便签页,每个标签页相当于获得了一个与外部容器相同大小的组件摆法区域.通过这种方式,就可以在一个容器里放置更多组件,例如手机 ...

  4. mysql 语句总结

    1.多表查询 SELECT a.id,catid,thumb,title FROM v9_gamedown as a LEFT JOIN v9_gamedown_data as b ON a.id=b ...

  5. CentOS6+MySQL5.6二进制安装

    一般我们安装mysql采用二进制安装的方式就足以满足我们的生产环境了,不过需要我们配置my.cnf文件 从官网下载二进制MySQL,选择Linux-Generic,最后这两个是二进制包 http:// ...

  6. Cisco VPN Client Error 56解决

    Cisco VPN Client Error 56解决 VPN Client报错 650) this.width=650;" style="width:575px;height:1 ...

  7. Unity基础学习-Unity概述

    Unity 概述 Unity是一个强大的引擎,里面包括大量的工具用来满足各种各样的需求.Unity的编辑器是直观的可定制的,让您在您的工作流中有较大的自由度. 本小节是开始学习Unity的关键部分.里 ...

  8. JavaScript 44 Puzzlers

    http://mp.weixin.qq.com/s?__biz=MzAxODE2MjM1MA==&mid=2651550987&idx=1&sn=f7a84b59de14d0b ...

  9. C# 编写通用的JSON数据进行序列化和反序列化

    注意事项:使用JSON系列化和反系列化,必须要添加引用System.Runtime.Serialization. 1.通用类代码如下: /// <summary>    /// JSON序 ...

  10. 使用JAVA开发微信公众平台(一)——环境搭建与开发接入

    一. 初始微信公众平台 微信公众平台,即我们平时所说的"公众号",曾用名"官方平台"."媒体平台",但最终命名为"公众平台&quo ...