博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux内核学习笔记八——定时器和时间管理
阅读量:6540 次
发布时间:2019-06-24

本文共 3810 字,大约阅读时间需要 12 分钟。

一 内核中的时间观念

       内核在硬件的帮助下计算和管理时间。硬件为内核提供一个系统定时器用以计算流逝的时间。系

 统定时器以某种频率自行触发,产生时钟中断,进入内核时钟中断处理程序中进行处理。

       墙上时间和系统运行时间根据时钟间隔来计算。

利用时间中断周期执行的工作:

       更新系统运行时间;

       更新实际时间;

       在smp系统上,均衡调度程序中各处理器上运行队列;

       检查当前进程是否用尽了时间片,重新进行调度;

       运行超时的动态定时器;

       更新资源消耗和处理器时间的统计值;

二 节拍率

       系统定时器的频率;通过静态预处理定义的——HZ;系统启动按照HZ值对硬件进行设置。体系结构不同,HZ值也不同;HZ可变的。

    //内核时间频率

    #define HZ 1000

提高节拍率中断产生更加频繁带来的好处:

       提高时间驱动事件的解析度;

       提高时间驱动事件的准确度;

       内核定时器以更高的频度和准确度;

       依赖顶上执行的系统调用poll()和select()能更高的精度运行;

       系统时间测量更精细;

       提高进程抢占的准确度;

提高节拍率带来的副作用:

       中断频率增高系统负担增加;

       中断处理程序占用处理器时间增多;

       频繁打断处理器高速缓存;

节拍率HZ值需要在其中进行平衡。

 

三 jiffies

  jiffies:全局变量,用来记录自系统启动以来产生的节拍总数。启动时内核将该变量初始化为0;

此后每次时钟中断处理程序增加该变量的值。每一秒钟中断次数HZ,jiffies一秒内增加HZ。系统运行时间 = jiffie/HZ.

jiffies用途:计算流逝时间和时间管理

jiffies内部表示:

              extern u64 jiffies_64;

              extern unsigned long volatile jiffies;     //位长更系统有关32/64

  32位:497天后溢出

  64位:……

      

//0.5秒后超时unsigned long timeout = jiffies + HZ/2;……//注意jiffies值溢出回绕用宏time_before 而非 直timeout > jiffiesif(time_before(jiffies,timeout)){       //没有超时}else{       //超时}

 

四 硬时钟和定时器

  两种设备进行计时:系统定时器和实时时钟。

实时时钟(RTC):用来持久存放系统时间的设备,即便系统关闭后,靠主板上的微型电池提供电力保持系统的计时。

    系统启动内核通过读取RTC来初始化墙上时间,改时间存放在xtime变量中。

系统定时器:内核定时机制,注册中断处理程序,周期性触发中断,响应中断处理程序,进行处理执行以下工作:

  l  获得xtime_lock锁,访问jiffies和更新墙上时间xtime;

  l  更新实时时钟;

  l  更新资源统计值:当前进程耗时,系统时间等;

  l  执行已到期的动态定时器;

  l  执行scheduler_tick()

 

//中断处理程序    irqreturn_t timer_interrupt(int irq, void *dev){    //ticks have passed    long nticks;    xtime_update(nticks);    while (nticks--)           update_process_times(user_mode(get_irq_regs()));    return IRQ_HANDLED;} void xtime_update(unsigned long ticks){    //seq锁    write_seqlock(&xtime_lock);    do_timer(ticks);    write_sequnlock(&xtime_lock);}void do_timer(unsigned long ticks){    jiffies_64 += ticks;    //更新墙上时间 ——实际时间    update_wall_time();    calc_global_load(ticks);} void update_process_times(int user_tick){    struct task_struct *p = current;    //计算当前进程执行时间    account_process_tick(p, user_tick);    //触发软中断TIMER_SOFTIRQ 超时的timer    run_local_timers();    //计算进程时间片    scheduler_tick();}

 

五 定时器

       定时器:管理内核时间的基础,推后或执行时间执行某些代码。

定时器数据结构:

struct timer_list {              struct list_head entry;              //定时值基于jiffies              unsigned long expires;              //定时器内部值              struct tvec_base *base;              //定时器处理函数              void (*function)(unsigned long);              //定时器处理函数参数              unsigned long data;              ……       };

 

定时器使用:

struct timer_list my_timer;       //初始化定时器       init_timer(&my_timer);       ……             //激活定时器       add_timer(&my_timer);       //删除定时器       del_timer(my_timer);       ……

 

六 延迟执行

       使用定时器和下半部机制推迟执行任务。还有其他延迟执行的机制:

忙等待:

       利用节拍,精确率不高

       unsigned long delay = jiffies + 2*HZ ; //2秒 节拍整数倍才行;

       while(time_before(jiffies,delay))

              ;

短延迟:延迟时间精确到毫秒,微妙;短暂等待某个动作完成时,比时钟节拍更短;依靠数次循环达到延迟效果。

       void udelay(unsigned long usecs)

       void mdelay(unsigned long msecs)

 

schedule_timeout()延迟:使执行的任务睡眠指定时间,达到延迟

 

signed long __sched schedule_timeout(signed long timeout){       struct timer_list timer;       unsigned long expire;       switch (timeout)       {         case MAX_SCHEDULE_TIMEOUT:              //无限期睡眠              schedule();              goto out;         default:              if (timeout < 0) {                     current->state = TASK_RUNNING;                     goto out;              }       }       //超时时间       expire = timeout + jiffies;       //初始化一个timer定时器 参数current task       setup_timer_on_stack(&timer, process_timeout, (unsigned long)current);       __mod_timer(&timer, expire, false, TIMER_NOT_PINNED);       schedule();       del_singleshot_timer_sync(&timer);        /* Remove the timer from the object tracker */       destroy_timer_on_stack(&timer);       timeout = expire - jiffies;  out:       return timeout < 0 ? 0 : timeout;}static void process_timeout(unsigned long __data){       //唤醒被睡眠的任务       wake_up_process((struct task_struct *)__data);}

 

转载地址:http://dysdo.baihongyu.com/

你可能感兴趣的文章
win8.1 64位环境搭建android开发环境
查看>>
matlab两种不同模式的并行运算
查看>>
MySQL启动和关闭服务命令
查看>>
微软.NET Core RC2正式发布,横跨所有平台
查看>>
Unix 系统下的 Nginx 1.4.x
查看>>
查找特定文件,修改为当前系统时间
查看>>
WCF 之 概述
查看>>
jquery $post $get $
查看>>
linux find命令-print0和xargs中-0使用技巧(转载)
查看>>
Java实现Redis pipeline比较
查看>>
怎么关闭win10和win8快速启动
查看>>
C#设计模式之十外观模式(Facade Pattern)【结构型】
查看>>
GridControl常见用法【转】
查看>>
CS001496 - Gather data from web page with JavaScript, WebKit, and Qt
查看>>
SQLSERVER中的NUMA架构
查看>>
obiee11g中关闭缓存
查看>>
Oracle DB 通过 Oracle Enterprise Manager注册要使用的恢复目录
查看>>
初学数位DP--hdu 2089
查看>>
【转】linux下awk内置函数的使用(split/substr/length)
查看>>
模型变换和视图变换
查看>>