jiffies变量

  全局变量jiffies用来记录自启动以来产生的节拍的总数。系统启动时会将该变量初始化为0,此后,每当时钟中断产生时就会增加该变量的值。jiffies和另外一个变量息息相关:HZ。HZ是每秒系统产生的时钟中断次数,所以jiffies每秒增加的值也就是HZ;在x86体系结构中,内核版本在2.4以前的值为100,在2.6内核中被定义为1000。

jiffies的定义

extern unsigned long volatile jiffies;  //定义于<linux/jiffies.h>

  值得注意的一点,C 编译器通常只将变量装载一次 。 一 般情况下不能保证循环中的 jiffies 变量在每次循环中被读取时都重新被载入。但是我们要求 jiffies 在每次循环时都必须重新装载,因为在后台 jiffies 值会随时钟中断的发生而不断增加。为了解决这个问题,<linux/jiffies.h > 中 jiffies 变量被标记为关键字 volatile 。关键字 volatile指示编译器在每次访问变量时都重新从主内存中获得,而不是通过寄存器中的变量别名来访问,从而确保前面的循环能按预期的方式执行。
  从定义可以看出,jiffies的类型为unsigned long,在32位体系结构上unsigned long是32位,在64位体系结构上是64位。 在32位体系结构上,在系统的HZ值为100的情况下,jiffies的回绕时间为497天,如果HZ为1000,那么回绕时间将只有49.7天左右。如果发生了回绕现象,对内核中直接利用jiffies来比较时间的代码将产生很不利的影响,比如在《linux内核设计与实现》一书中有一个例子可以说明这个问题:

unsigned long timeout = jiffies + HZ/2; //0.5后超时
/*执行一些任务*/
........
/*然后检查时间是否过长*/
if(timeout>jiffies){/*没有超时...*/
}else{/*超时了....*/
}

  在这个例子中,如果设置了timeout后发生了回绕,那么第一个判断条件将变为真,这与实际情况不符,尽管因为实际的时间比timeout要大,但因为jiffies发生了回绕变成了0,所以jiffies肯定小于timeout的值。 内核也专门针对这种情况提供了四个宏来帮助比较jiffies计数:

#define  time_after(unknown,known)           ((long)(known) - (long)(unknown)<0)
#define  time_before(unkonwn,known)         ((long)(unknown) - (long)(known)<0)
#define  time_after_eq(unknown,known)      ((long)(unknown) - (long)(known)>=0)
#define  time_before_eq(unknown,known)    ((long)(known) -(long)(unknown)>=0)

  这些宏看起来很奇妙,只是将计数值强制转换为long类型然后比较就能避免回绕带来的问题,这是为什么呢?这和计算机中数据存储的形式有关!!
  计算机中数据的存储是按照二进制补码的方式存储的,之所以采用补码的方式存储是因为这样可以简化运算规则和线路设计。另外一个相关的概念就是原码,原码采用一个最高位作为符号位,其余位是数据大小的二进制表示。 补码的定义是这样的:正数的补码即为原码,负数的补码为原码除符号位外其他各位取反再加1。举例如下:

[+1]补码 = [+1]原码 = 0000 0001
[-1]补码 = [-1]原码取反+1 = 1111 1110 + 1 = 1111 1111

  而c语言中的数据类型相当于在代码和实际机器的存储之间的一个中间层,机器中存储的数据,如果按照不同的类型格式取读取就会得到不同的结果,才代码和实际存储之间,编译器充当了翻译者的角色。这是编译器能实现多种数据类型和强制类型转换的基础。
  有了这些基础后,就不难理解上述宏定义的巧妙之处了,为了便于说明,以下假设jiffies是单字节的无符号数,范围为0~255。假如jiffies开始为250,由于是无符号数据,那么它在机器中实际存储的补码为1111 1010,记为J1;timeout如果被设为252,实际存储为1111 1100;而过了一会jiffies发生回绕编变成了1,实际存储变为0000 0001,记为J2。 那么此时如果按照无符号数比较其大小关系,有: J1<timeout & J2 <timeout,这样的结果与实际的时间节拍统计是不符的,但是如果我们按照有符号数来比较会有什么结果呢?
   J1如果按照有符号数读取,首先从补码转换成原码:1000 0110,转换成十进制为-6;
  timeout按照有符号数读取,首先从补码转换成原码:1000 0100,转换成十进制为-4;
  J2按照有符号数读取,首先从补码转换成原码:0000 0001,转换成十进制为1;
  这样它们的大小关系为: J1<timeout<J2。 这与实际的节拍计数就吻合了,以上内核定义的几个宏就是通过这种方式巧妙解决jiffies回绕问题的。
  但这个写法有一个小小的缺点,就是延时不能大于周期数,否则计算就不正确了,对于32 位的情况就是延时不能大于231−1231−12^{31}-1,想来也没有哪个程序会一次性 delay 49.7天吧……所以这一套宏便能够胜任了。

jiffies回绕问题相关推荐

  1. socket read time out解决方法_time_after方法对jiffies回绕问题的解决

    前言: 最近在啃< Linux内核设计与实现>,看到第四章CFS时候,读了几遍没太理清这一小节到思路,看到40页这么一句话:"如果这里所讨论的定时器节拍对你来说很陌生,快先去看看 ...

  2. 对 jiffies 溢出、回绕及 time_after 宏的理解

    原文如下: 关于jiffies变量:      全局变量jiffies用来记录自启动以来产生的节拍的总数.系统启动时会将该变量初始化为0,此后,每当时钟中断产生时就会增加该变量的值.jiffies和另 ...

  3. jiffies和jiffies_64

    Linux内核时间管理(二)--jiffies与jiffies_64释疑 </h1><div class="clear"></div><d ...

  4. Linux中的jiffies介绍

    HZ和jiffies Linux中的软定时器(低分辨率的timer_list定时器)利用CPU时钟中断来感知时间更新,并通过TIMER_SOFTIRQ软中断来运行到期的定时器.时钟中断每秒触发HZ次, ...

  5. Linux 内核宏 time_after解析

    同学们留言回复答案看看 可能很多老鸟对这样的Linux 内核宏已经见惯不怪了,但是作为新手的Linux内核开发者,我觉得非常有必要了解其中的原理和作用. jiffies 这个想必大家已经非常熟悉,ji ...

  6. STM32单片机初学心得

    一个小阶段下来收获颇丰,经过复盘,整理相关笔记如下.(本早该发布一直拖到了现在) 1. 关于延时效果除了HAL_Delay外常用的方法 在这个阶段中做了一个小项目--楼道灯. 因为还未接触到继电器,所 ...

  7. Linux时间管理与定时器

    学习资料:LINUX驱动程序开发实例教程2 时钟周期是指1s,而时钟频率是指1s内时钟脉冲的个数: 时钟滴答:1s内的时钟中断数 1.问:时间戳和节拍总值jiffies有什么区别? 答:时间戳是通过读 ...

  8. linux内核之时钟管理

    时钟管理 定时器和时间管理 节拍率:HZ jiffies 实时时钟 时钟中断处理程序 定时器和时间管理 时间管理在内核中占有非常重要的地位.相对于事件驱动而言,内核中有大量的函数都是基于时间事件驱动的 ...

  9. linux 内核获取时间,Linux内核中的jiffies 以及时间的获取time

    硬件给内核提供一个系统定时器用以计算和管理时间,内核通过编程预设系统定时器的频率,即节拍率(tick rate),每一个周期称作一个tick(节拍).Linux内核从2.5版内核开始把频率从100调高 ...

最新文章

  1. python bindings_OpenCV-Python Bindings 如何工作 | 六十四
  2. PHP和mysql的长连接
  3. iostat来对linux硬盘IO性能进行了解
  4. OPPO Reno 2正式发布:主打4800万变焦四摄 售价2999元
  5. linux能运行安卓模拟器吗,Ubuntu 14.04中使用模拟器运行Android系统
  6. Android:访问网络资源,在手机本地显示网络资源源代码
  7. JAVA 实现《超级玛丽》游戏
  8. RS485通信和Modbus通信协议汇总
  9. linux 声卡设备文件夹,Linux操作系统声卡驱动的安装与配置
  10. cdr怎么转plt_win10系统怎么将cdr格式转换成plt?
  11. gif一键抠图 在线_高效抠图PS竟全然不是对手?堪称黑科技的AI一键抠图网站
  12. QT 信号与槽不在同一个线程 connect
  13. java 标点符号_java的标点符号
  14. 华为AX3Pro路由器配置成交换机使用
  15. 微信怎么识别图片文字
  16. DCT域图像水印技术
  17. 关于DXP的规则检查中Un-Rounted Net Constraint问题
  18. oracle数据库启动cannot mount database in EXCLUSIVE mode
  19. 怎么查看显卡算力(附nvidia显卡算力表)
  20. 一些opencv小工程(蓝白转换,进度条亮度对比度,鼠标位置读取rgb)

热门文章

  1. phpcms注入漏洞之文件poster.php
  2. 第三只眼使用局域网版本还是网络版好_iOS13.4测试版使用3天后,发现3个优化,建议升级!...
  3. 如何用stata画莫兰散点图_吃下这颗安利:STATA
  4. Vue | 实现页面跳转刷新,在Vue页面中调用其他页面的方法
  5. ironpython2.7.8相当于python3.7吗_IronPython与numpy的Python速度之比较
  6. 微信小程序盲盒-可对接微信支付
  7. N点虚拟主机管理系统(For Windows2003/2008)功能及介绍
  8. ASP.NET Forms验证 实现子域名(SubDomain)共享登陆下的缺陷 [转]
  9. asp.net 异步群发邮件时遭遇到的问题 ddddddddd
  10. linux: 批量修改文件夹及文件夹下文件的名字