内核时间管理

内核中的时间

节拍率

  • 硬件定时器的节拍率是通过宏定义的。这个宏是HZ。
  • HZ宏在<asm/param.h>文件中定义;
  • 不同的体系结构HZ的值不同;
  • 对于ARM来说
    早期的linux内核版本,这个值是100;
    对于3.5.0版本的内核,这个值是200。
    也就是说每秒钟硬件定时器会产生200次中断。
  • 若要修改HZ的值,可执行一下kernel/timeconst.pl脚本,该脚本会在kernel下自动生成timeconst.h

jiffies

  • 全局变量jiffies用来记录自系统启动以来产生的节拍的总数。
  • 启动时,内核将该变量初始化为0.
  • 此后,每次时钟中断的处理程序会增加该变量的值。
  • 因为一秒内时钟中断次数为HZ,所以jiffies一秒内增加的值为HZ。
  • jiffies全局变量在<linux/jiffies.h>文件中定义:


jiffies的溢出和回绕问题

  • jiffies为32位无符号类型,其能够记录的最大值为4294967295.
  • 对于ARM体系统结构来说,HZ为200,也就是每秒钟jiffies增加200.
  • 那么248.5天后,jiffies的值就会溢出;这是jiffies的值又回绕到0值。

定时器

  • 内核经常需要推后执行某些代码,内核定时器能够使工作放到指定时间点上执行。
  • 内核定时器的使用只需设置一个超时时间,指定超时发生后执行的函数就可以了。
  • 指定的函数在定时时间到是自动执行。
  • 定时器并不周期运行,而是在超时执行了指定的函数后,自动撤销。
  • 也就是,定时器超时后执行的函数只会执行一次。
  • 定时器使用timer_list结构表示
    定义在<linux/timer.h> 文件中



    expires :定时值
    data : 传给定时器处理函数的参数
    function :定时器处理函数

  • 定时值的计算
    如当前的节拍数是jiffies
    1秒后的定时值是 jiffies+HZ
    10ms后的定时值是 jiffies+HZ/100
  • 使用定时器,先要创建一个struct timer_list结构变量。
  • 然后初始化该结构体变量的各个成员。方有以下几种:
    • 方法一:
      DEFINE_TIMER(timer_name, function_name, expires_value, data);
      该宏会静态创建一个名叫 timer_name 内核定时器,并初始化其 function, expires, data和 base 成员。
    • 方法二:
struct timer_list mytimer;
setup_timer(&mytimer, (*function)(unsigned long), unsigned long data);
mytimer.expires = jiffies + 5*HZ;
  • 方法三:
struct timer_list mytimer;
init_timer(&mytimer); 
mytimer.expires = jiffies + 5*HZ;
mytimer.data = (unsigned long) dev;
mytimer.function = &my_timer_func; 
  • 无论用哪种方法初始化,其本质都只是给成员赋值,所以只要在激活定时器之前,expires, function 和 data成员都可以直接再修改。
  • 激活定时器:
    add_timer(struct timer_list * )
  • 修改定时值并激活定时器:
    mod_timer(struct timer_list *timer, unsigned long expires)
  • 删除定时器:
    del_timer(struct timer_list * )
    删除定时器意味着定时器不再处于激活运行状态,可以用上面的两个激活函数重新激活运行。

定时器使用流程

  • 先定义一个定时器处理函数,函数的原型如下:
    void my_timer_function(unsigned long data);
  • 创建定时器:
    struct timer_list my_timer;
  • 设置定时器的值:
    my_timer.expires = jiffies + HZ/100; //定时10ms
    my_timer.data = 0;
    my_timer.function = my_timer_function;
  • 在需要时,激活定时器
    add_timer(&my_timer);//激活定时器
    mod_timer(&my_timer,jiffies+HZ/100);修改定时值,并激活定时器

延时执行

  • 内核代码(尤其是驱动程序)除了使用定时器或下半部机制以外还需要其他方法来推迟执行任务。
  • 内核提供了许多延迟方法处理各种延迟要求。
    不同的方法有不同的处理特点,
    有些是在延迟任务时挂起处理器,防止处理器执行任何实际工作;
    另一些不会挂起处理器,所以也不能确保被延迟的代码能够在指定的延迟时间运行。
  • 忙等待
    最简单的延迟方法(虽然通常也是最不理想的办法)是忙等待。
    该方法仅仅在想要延迟的时间是节拍的整数倍,或者精确率要求不高时才可以使用。
    忙循环实现起来很简单,比如:



    循环不断执行,直到jiffies大于delay为止。

  • 内核提供了四个宏来帮助比较节拍计数,它们能正确地处理了节拍计数回绕情况。
  • 这些宏定义在文件<linux/jiffies.h>中:
time_after(a,b)     //a>b时,为真
time_before(a,b)    //a<b时,为真
time_after_eq(a,b)  //a>=b时,为真
time_before_eq(a,b) //a<=b时,为真
  • 短延时
    内核提供了短暂而精确的延时函数
    对于频率为200HZ的时钟中断,它的节拍间隔是5ms;所以我们必须寻找其他方法满足更短、更精确的延迟要求。
    内核提供了两个可以处理微秒和毫秒级别的延迟的函数,定义在文件<linux/delay.h>:
void udelay(unsigned long usecs)
void mdelay(unsigned long msecs)
udelay(150);    /*延迟150微秒*/

udelay()函数依靠执行数次循环达到延迟效果,而mdelay()函数又是通过udelay()函数实现的。
因为内核知道处理器在一秒内能执行多少次循环(BogoMIPS),所以udelay()函数仅仅需要根据指定的延迟时间在1秒中占的比例,就能决定需要进行多少次循环就能达到要求的推迟时间.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,287评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,346评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,277评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,132评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,147评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,106评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,019评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,862评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,301评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,521评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,682评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,405评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,996评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,651评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,803评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,674评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,563评论 2 352

推荐阅读更多精彩内容