精华内容
下载资源
问答
  • jiffies

    千次阅读 2017-01-10 15:30:52
    定时器之jiffies

    全局变量jiffies用来记录自系统启动以来产生的节拍的总数。

     

    启动时,内核将该变量初始化为0,此后,每次时钟中断处理程序就会增加该变量的值。

     

    因为一秒内时钟中断的次数等于HZ 所以jiffies一秒内增加的值也就为HZ

     

    系统运行时间以秒为单位计算的话,就等于 jiffies/HZ

     

     

    Jiffies定义于文件<linux/jiffies.h>中:

    Externunsigned long volatile jiffies;

     

    将以秒为单位的时间转化为jiffies:(seconds*HZ

     

    jiffies转换为以秒为单位的时间:jiffies/HZ

     

    比较而言,内核中将秒转换为jiffies用的多一些,比如代码经常需要设置一些将来的时间:

    Unsigned long time_stamp = jiffies; /*现在*/

     

    Unsigned long time_stamp = jiffies+1; /*从现在开始1个节拍*/

     

    Unsigned long time_stamp = jiffies+5*HZ; /*从现在5*/

     

    Unsigned long time_stamp = jiffies+HZ/10; /*从现在开始1/10*/

    展开全文
  • 1、前言 ... 假定HZ=1000,那么jiffies只需要约49.7天就会产生回绕(溢出),这是因为jiffies本身是unsigned long 类型,因此在32位系统中支持的最大值为(2^32)-1=4294967295,又因为HZ是100...

    1、前言

    linux内核中定义了jiffies变量来记录从系统启动到当前时刻系统时钟所产生的tick数。jiffies变量是一个无符号整型数值,即unsigned long类型。
        它的声明如下(在 include/linux/jiffies.h 中):
        
        假定HZ=1000,那么jiffies只需要约49.7天就会产生回绕(溢出),这是因为jiffies本身是unsigned long 类型,因此在32位系统中支持的最大值为(2^32)-1=4294967295,又因为HZ是1000,即1s内产生1000次
        tick数,也就是说1秒内jiffies的值会增加1000,因此4294967295/3600/24/1000=49.710天。回绕会给内核时间度量带来混乱和其他潜在的问题。因此,在Linux2.6内核中引入一个64位的无符号整型变量jiffies_64,
        内核中计时都是对jiffies_64进行递增。
        /*
      * The 64-bit value is not atomic - you MUST NOT read it
      * without sampling the sequence number in jiffies_lock.
      * get_jiffies_64() will do this for you as appropriate.
      */
        extern u64 __cacheline_aligned_in_smp jiffies_64;
        
        因为u64 是unsigned long long 类型,因此同样HZ=1000的情况下,jiffies_64可以运行几亿年也不会发生回绕问题。

    2、分析源码路径

    基于kernel4.14源码分析
        /kernel-4.14/kernel/time/jiffies.c
        /kernel-4.14/include/linux/jiffies.h
        /kernel-4.14/arch/arc/kernel/vmlinux.lds.S
        /kernel-4.14/kernel/time/timer.c

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

    	#if (BITS_PER_LONG < 64)
    	 u64 get_jiffies_64(void);
    	 #else
    	 static inline u64 get_jiffies_64(void)
    	 {
    		return (u64)jiffies;
    	 }
    	 #endif

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

    	 #ifdef CONFIG_CPU_BIG_ENDIAN
    		jiffies = jiffies_64 + 4;
    	 #else
    		jiffies = jiffies_64;
    	 #endif

     其中最后一条语句的作用是,让符号jiffies的地址等于符号jiffies_64的地址,即让jiffies变量占用 jiffies_64 的低 32 位。
         注:这里涉及到链接器中的一个重要的概念:
            在目标文件内定义的符号可以在链接器脚本内赋值,此时该符号应被定义为全局的。每个符号都对应一个地址,在链接器中的赋值(=)操作就是更改这个符号对应的地址。

    4、jiffies_64的初始值

    在jiffies.h中定义了INITIAL_JIFFIES,这个是一个宏,其主要目的是用于给jiffies和jiffies_64变量赋值初始值,这个宏定义如下:

    	/*
    	* 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))
    	用于验证是否存在回绕问题。
    	例如kernel4.14中/kernel-4.14/kernel/time/timer.c中使用此宏对jiffies_64进行赋值:
    	#define CREATE_TRACE_POINTS
    	#include <trace/events/timer.h>
    
    	__visible u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES;
    
    	EXPORT_SYMBOL(jiffies_64);

    5、jiffies.h源码解析

    关于使用time_after等宏定义的强烈推荐,这是直接给出内核源码中的注释:

    /*
      *	These inlines deal with timer wrapping correctly. You are
      *	strongly encouraged to use them
      *	1. Because people otherwise forget
      *	2. Because if the timer wrap changes in future you won't have to
      *	   alter your driver code.
      *
      * time_after(a,b) returns true if the time a is after time b.
      *
      * Do this with "<0" and ">=0" to only test the sign of the result. A
      * good compiler would generate better code (and a really good compiler
      * wouldn't care). Gcc is currently neither.
      */

    5.1、常用宏定义说明

    time_after(a,b)/time_after64(a,b)---如果时间a的值在时间b的值后面则返回true,否则返回false
    time_before(a,b)/time_before64(a,b)---如果时间a的值在时间b的前面则返回true,否则返回false
    time_after_eq(a,b)/time_after_eq64(a,b)---如果时间a的值大于或等于时间b的值则返回true,否则返回false
    time_before_eq(a,b)/time_before_eq64(a,b)---如果时间a的值小于或等于时间b的值则返回true,否则返回false
    time_in_range(a,b,c)/time_in_range64---判断时间a是否位于时间[b,c]之间,如果是返回true,否则返回false
    time_in_range_open(a,b,c)---判断时间a是否位于时间[b,c)之间,如果是返回true,否则返回false

    5.2、不同时间单位之间的转换接口

    /*将jiffies数值转换为毫秒*/
    extern unsigned int jiffies_to_msecs(const unsigned long j);
    /*将jiffies数值转换为微秒*/
    extern unsigned int jiffies_to_usecs(const unsigned long j);
    /*将毫秒转为jiffies的值*/
    extern unsigned long __msecs_to_jiffies(const unsigned int m);
    /*将微秒转为jiffies的值*/
    extern unsigned long __usecs_to_jiffies(const unsigned int u);
    
    /*将timespec64表示的时间转为jiffies*/
    extern unsigned long timespec64_to_jiffies(const struct timespec64 *value);
    /*将jiffies表示的值转为timespec64表示的时间*/
    extern void jiffies_to_timespec64(const unsigned long jiffies,struct timespec64 *value);
    
    /*将timeval表示的时间转为jiffies*/
    extern unsigned long timeval_to_jiffies(const struct timeval *value);
    /*将jiffies表示的值转换为timeval表示的时间*/
    extern void jiffies_to_timeval(const unsigned long jiffies,struct timeval *value);
    
    extern clock_t jiffies_to_clock_t(unsigned long x);
    extern unsigned long clock_t_to_jiffies(unsigned long x);

    6、参考链接

    https://www.cnblogs.com/mewmicro/p/6421254.html?utm_source=itdadao&utm_medium=referral

    展开全文
  • 内核jiffies

    千次阅读 2013-09-05 11:57:25
    Linux 内核具有一个名为 jiffies 的全局变量,它代表从机器启动时算起的时间滴答数。这个变量最初被初始化为 0,每次时钟中断时都会加 1。可以使用 get_jiffies_64 函数来读取 jiffies 的值,然后使用 jiffies_to_...

         Linux 内核具有一个名为 jiffies 的全局变量,它代表从机器启动时算起的时间滴答数。这个变量最初被初始化为 0,每次时钟中断时都会加 1。可以使用 get_jiffies_64 函数来读取 jiffies 的值,然后使用 jiffies_to_msecs 将其换算成毫秒或使用 jiffies_to_usecs 将其换算成微秒。jiffies 的全局定义和相关函数是在 ./linux/include/linux/jiffies.h 中提供。微笑

    展开全文
  • 内核定时器 jiffies

    2021-04-24 16:01:34
    jiffies概念: 全局变量jiffies用来记录自系统启动以来产生的节拍的总数。启动时,内核将该变量初始化为0,每次时钟中断处理程序就会增加该变量的值,因此,1S内时钟中断的次数等于HZ。 #include <linux/jiffies....

    jiffies概念:
    全局变量jiffies用来记录自系统启动以来产生的节拍的总数。启动时,内核将该变量初始化为0,每次时钟中断处理程序就会增加该变量的值,因此,1S内时钟中断的次数等于HZ。
    jiffies变量是一个无符号整型数值,即unsigned long类型。
    jiffies转换为秒可采用公式:(jiffies/HZ)计算,将秒转换为jiffies可采用公式:(seconds*HZ)计算。

    #include <linux/jiffies.h>
    unsigned long timeout  = jiffies + HZ/2;//0.5s后超时
    unsigned long timeout  = jiffies + 10*HZ;//10s后超时
    

    1、 定时器数据结构

    struct timer_list {
        struct list_head entry;//定时器链表的入口
        unsigned long expires;//以jiffies为单位的定时值
        void (*function)(unsigned long);//定时器处理函数
        unsigned long data;//传给处理函数的长整型参数
        struct tvec_t_base_s *base;//定时器内部值,用户不要使用
    };
    

    2、 定义及初始化

    struct timer_list my_timer;//定义
    
    init_timer(&my_timer);//初始化
    
    //成员赋值
    my_timer.expires = jiffies + delay;//定时器超时时的节拍数
    my_timer.data = 0;//给定时器处理函数传入0值
    my_timer.functioin = my_function;//定时器超时时调用的函数
    
    //处理函数原型
    void my_timer_function(unsigned long data);
    

    3、激活定时器

    add_timer(&my_timer);
    

    注意:一般来说,定时器都在超时后立马执行,但是也有可能推迟到下一次时钟节拍时才能运行,所以不能用定时器来实现任何硬实时任务。

    参考链接:
    https://www.cnblogs.com/chaozhu/p/6183537.html
    https://www.cnblogs.com/mewmicro/p/6421254.html?utm_source=itdadao&utm_medium=referral
    https://www.cnblogs.com/chaozhu/p/6183537.html

    展开全文
  • jiffies计数器

    千次阅读 2014-01-23 18:06:14
    **********jiffies是一个计数器,记录了系统从刚开始启动到关闭系统时所运行的秒数,系统初始化时jiffies是0 **********内核是通过定时器中断来使jiffies计数器的值增加的,每次产生一个时钟中断,jiffies就会+1 *****...
  • 关于 jiffies

    2015-07-15 17:02:37
    3.Jiffies ...Jiffies为Linux核心变数(32位元变数,unsigned long),它被用来纪录系统自开机以来,已经过多少的tick。每发生一次timer interrupt,Jiffies变数会被加...在ARM体系结构中,jiffies被初始化为jiffies
  • jiffies字段详解

    千次阅读 2018-05-17 15:18:27
    jiffies变量,是在linux内核源码中经常可以看见的一个变量。...查看Linux内核的源码,可以发现,jiffies是一个宏定义,# define jiffies raid6_jiffies(),所以jiffies的值实际上是调用raid6_jiffies()的返回值...
  • jiffies防溢出

    2018-09-23 01:53:50
    Linux中使用jiffies作为时钟,其类型为volatile unsigned long 取值是有限制的0-0xffffffffff,内核依赖时钟来做定时器的功能,那么就有问题如果值溢出之后,jiffies的值会变为0从新开始计时,那么内核又是如何避免...
  • 内核定时器Jiffies

    2021-03-21 20:53:22
    内核定时器Jiffies 简介: 1、头文件 2、定义定时器变量 3、启动函数 4、初始化函数 5、关闭定时器 内核定时器Jiffies 简介: 在驱动中,如果是想指定一个时间去执行某一项操作,可以使用定时器timer,它的...
  • linux jiffies

    2013-10-18 11:22:59
    全局变量jiffies用来记录自系统启动以来产生的节拍的总数。启动时,内核将该变量初始化为0,此后,每次时钟中断处理程序都会增加该变量的值。一秒内时钟中断的次数等于Hz,所以jiffies一秒内增加的值也就是Hz。 ...
  • jiffies回绕问题

    2018-06-29 19:52:45
    jiffies变量  全局变量jiffies用来记录自启动以来产生的节拍的总数。系统启动时会将该变量初始化为0,此后,每当时钟中断产生时就会增加该变量的值。jiffies和另外一个变量息息相关:HZ。HZ是每秒系统产生的时钟...
  • HZ 与 jiffies

    2017-08-01 11:23:27
    jiffies在内核中是一个全局变量,它用来统计系统启动以来系统中产生的总节拍数,这个变量定义在include/Linux/jiffies.h中,定义形式如下。 unsigned long volatile jiffies; 想要理解jiffies的含义,我们需要...
  • jiffies存放

    2013-08-12 09:15:00
    固然书本上讲明jiffiesjiffies_64的低32位,但是我还是自己测试了下,重点在于链接脚本的写法。 此处只是为了测试,因此简化链接脚本。 /* link.lds */ 1 ENTRY(_start) ...
  • jiffies和HZ

    2016-11-22 22:30:00
    全局变量jiffies用来记录自系统启动以来产生的节拍的总数。启动时,内核将该变量初始化为0,此后,每次时钟中断处理程序都会增加该变量的值。一秒内时钟中断的次数等于Hz,所以jiffies一秒内增加的值也就是Hz。系统...
  • HZ和jiffies

    2019-02-28 15:02:02
    jiffies变量记录了系统启动以来,系统定时器已经触发的次数。 内核每秒中将jiffies变量增加HZ次。 HZ的值取决于体系架构。在x86系统上,在2.4内核中,该值默认设置为100;在2.6内核中,该值变为1000;而在2.6.13...
  • 内核变量——Jiffies

    2019-09-17 16:20:43
    全局变量jiffies表示自系统启动以来系统产生的嘀嗒数。当启动时,内核初始化该变量为0。每次时钟中断就会增1,所以系统运行时候可以计算为:jiffies/HZ秒。 jiffies变量定义如下: extern unsigned long volatile...
  • linux/jiffies.h>, 尽管你会常常只是包含 <linux/sched.h>, 它会自动地将 jiffies.h 拉进来. 不用说, jiffiesjiffies_64 必须当作只读的. 无论何时你的代码需要记住当前的 jiffies 值, 可以简单地...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 18,691
精华内容 7,476
关键字:

jiffies