定时器和时间管理

系统定时器是一种可编程硬件芯片。它能以固定频率产生中断。该中断就是所谓的定时器中断。它所相应的中断处理程序负责更新系统时间,还负责执行须要周期性执行的任务。

系统定时器和时钟中断处理程序是Linux系统内核管理机制中的中枢。

另外一个关注的焦点是动态定时器——一种用来推迟运行程序的工具。

比方说。假设软驱马达在一定时间内都未活动,那么软盘驱动程序会使用动态定时器关闭软驱马达。

内核能够动态创建或销毁动态定时器。

内核中的时间观念

内核在硬件的帮助下计算和管理时间。

硬件为内核提供一个系统定时器用以计算流逝的时间。

系统定时器以某种频率自行触发。产生时钟中断。进入内核时钟中断处理程序中进行处理。该频率能够通过编程预定,称为节拍率(tick rate)。

连续两次时钟中断的间隔时间称为节拍(tick)。它等于节拍率分之中的一个秒。

墙上时间和系统执行时间依据时钟间隔来计算。

节拍率HZ

节拍率(HZ)是时钟中断的频率,表示的一秒内时钟中断的次数。

比方 HZ=100 表示一秒内触发100次时钟中断程序。

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

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

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

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

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

系统时间測量更精细。

提高进程抢占的精确度;

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

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

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

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

jiffies

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

启动时内核将该变量初始化为0。此后每次时钟中断处理程序添加该变量的值。每一秒钟中断次数HZ,jiffies一秒内添加HZ。系统执行时间 = jiffie/HZ.

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

jiffies 变量总是无符号长整数(unsignedlong)。因此,在32位体系结构上是32位,在64位体系结构是64位,当 jiffies 的值超过它的最大存放范围后就会发生溢出,它的值会回绕到0。内核提供了四个宏来帮助比較节拍计数,它们能正确地处理节拍计数回绕情况。

硬时钟和定时器

实时时钟(RTC):用来持久存放系统时间的设备。即便系统关闭后,靠主板上的微型电池提供电力保持系统的计时。系统启动内核通过读取RTC来初始化墙上时间,改时间存放在xtime变量中。

系统定时器:内核定时机制。注冊中断处理程序,周期性触发中断。响应中断处理程序。

时钟中断处理程序

时钟中断处理程序可以划分为两个部分:体系结构相关部分和体系结构无关部分。与体系结构相关的例程作为系统定时器的中断处理程序而注冊到内核中,以便在产生时钟中断时,它可以对应地执行。

尽管处理程序的详细工作依赖于特定的体系结构,可是绝大多数处理程序最低限度都要执行例如以下工作:

1)获得 xtime_lock 锁。以便对訪问 jiffies_64 和墙上时间 xtime 进行保护。

2)须要时应答或又一次设置系统时钟。

3)周期性地使用墙上时间更新实时时钟。

4)调用体系结构无关的时钟例程:do_timer()。

中断服务程序主要通过调用与体系结构无关的例程 do_timer 运行以下的工作:

1)给 jiffies_64 变量添加 1 (这个操作即使是在 32 位体系结构上也是安全的,由于前面已经获得了 xtime_lock 锁)。

2)更新资源消耗的统计值。比方当前进程所消耗的系统时间和用户时间。

3)运行已经到期的动态定时器。

4)运行 scheduler_tick 函数。

5)更新墙上时间,该时间存放在 xtime 变量中。

6)计算平均负载值。

实际时间

实际时间就是现实中钟表上显示的时间。事实上内核中并不经常使用这个时间,主要是用户空间的程序有时须要获取当前时间。所以内核中也管理着这个时间。实际时间的获取是在开机后。内核初始化时从RTC读取的。

内核读取这个时间后就将其放入内核中的 xtime 变量中,而且在系统的执行中不断更新这个值。

定时器

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

时器由结构 time_list 表示:

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

使用定时器:

struct timer_list my_timer;init_timer( &my_timer );                     /* 初始化定时器 */my_timer.expires = jiffies + delay;     /* 定时器超时时的节拍数 */
my_timer.data = 0;                            /* 给定时器处理函数传入 0 值 */
my_timer.function = my_function;      /* 定时器超时时调用的函数 */add_timer( &my_timer );                    /* 激活定时器  */

假设须要更改超时时间,能够调用 mod_timer 函数:mod_timer 函数无论 my_timer 是否已被激活,一旦从 mod_timer 返回,my_timer 都被激活并且设置了新的定时值。

假设调用时 my_timer 未被激活。该函数返回 0。否则返回 1。

假设须要停止定时器。能够使用 del_timer 和 del_timer_sync 函数。

延迟运行

内核代码除了使用定时器或下半部机制以外还须要其它方法来推迟运行任务。这样的推迟通常发生在等待硬件完毕某些工作时,并且等待的时间往往很短。

忙等待:

忙等待想要延迟的时间时节拍的整数倍,或者精确要求不高时才干够使用。

unsigned long delay = jiffies + 5 * HZ;
while( time_before( jiffies, delay ) )cond_resched();

cond_resched函数将调度一个新程序投入执行,但它仅仅有在设置完 need_resched 标志后,才干生效。换句话说。该方法有效的条件是系统中存在更重要的任务须要执行。注意由于该方法须要调用调度程序,所以它仅仅能在进程上下文中使用。

短延迟

void udelay( unsigned long usecs );
void mdelay( unsigned long msecs );

前一个函数利用忙循环将任务延迟到指定的微秒数后执行,后者延迟指定的毫秒数。

schedule_timeout

该方法会让须要延迟执行的任务睡眠到指定的延迟时间耗尽后再又一次执行。但不保证睡眠时间正好等于指定的延迟时间——仅仅能尽量使睡眠时间接近指定的延迟时间。当指定的时间到期后。内核唤醒被延迟的任务并将其又一次放回执行队列。

/* 将任务设置为可中断睡眠状态 */
set_current_state( TASK_INTERRUPTIBLE );
/* 小睡一会儿,“s”秒后唤醒 */
schedule_timeout( s * HZ);

唯一的參数是延迟的相对时间,单位为 jiffies,注意在调用 schedule_timeout 函数前必须首先将任务设置为 TASK_INTERRUPTIBLE 或 TASK_UNINTERRUPTIBLE 两种状态之中的一个,否则任务不会睡眠。

因为schedule_timeout()函数须要调用调度程序。所以调用它的代码必须保证可以睡眠。

简而言之,调用代码必须处于进程上下文中,而且不能持有锁。

设置超时时间,在等待队列上睡眠

进程上下文中的代码为了等待特定事假发生,能够将自己放入等待队列。然后调用调度程序去运行新任务。

一旦事件发生后。内核调用 wake_up 函数唤醒在睡眠队列上的任务,使其又一次投入执行。

有时。等待队列上的某个任务可能即在等待一个特定事件到来,又在等待一个特定时间到来——就看谁来的更快。这样的情况下。代码能够简单的使用schedule_timeout()函数取代schedule()函数。这样一来。当希望指定时间到期。任务都会被唤醒。当然,代码须要检查被唤醒的原因——有可能是被事件唤醒。也有可能由于延迟的时间到期,还可能由于接收到了信号——然后运行对应的操作。

被激活或未被激活的定时器都能够使用。假设定时器还未被激活,该函数返回 0,否则返回 1。注意。不须要为已经超时的定时器调用该函数,由于它们会自己主动被删除。两者差别在于 del_timer_sync 会等待其它处理器上执行的定时器处理程序都退出才执行。所以 del_timer_sync 不能在中断上下文中使用。

但在安全性方面考虑。优先使用 del_timer_sync。

參考

http://www.cnblogs.com/bastard/archive/2012/09/21/2696393.html

http://www.cnblogs.com/pennant/archive/2012/12/31/2839545.html

http://www.cnblogs.com/wang_yb/archive/2013/05/10/3070373.html

Linux内核设计与实现

Linux内核——定时器和时间管理相关推荐

  1. Linux内核深入理解定时器和时间管理(7):相关的系统调用

    Linux内核深入理解定时器和时间管理 相关的系统调用 rtoax 2021年3月 在原文基础上,增加5.10.13内核源码相关内容. 结构体 ---------------------------- ...

  2. Linux内核深入理解定时器和时间管理(5):clockevents 框架

    Linux内核深入理解定时器和时间管理 clockevents 框架 rtoax 2021年3月 在原文基础上,增加5.10.13内核源码相关内容. 1. Introduction to the cl ...

  3. Linux内核深入理解定时器和时间管理(4):定时器 timer

    Linux内核深入理解定时器和时间管理 定时器 timer rtoax 2021年3月 在原文基础上,增加5.10.13内核源码相关内容. 1. Timers This is fourth part ...

  4. Linux内核深入理解定时器和时间管理(3):tick 广播 框架 和 dyntick

    Linux内核深入理解定时器和时间管理 tick 广播 框架 和 dyntick rtoax 2021年3月 在原文基础上,增加5.10.13内核源码相关内容. 结构体 --------------- ...

  5. Linux内核深入理解定时器和时间管理(2):clocksource 框架

    Linux内核深入理解定时器和时间管理 clocksource 框架 rtoax 2021年3月 在原文基础上,增加5.10.13内核源码相关内容. 全局部变量 ------------------- ...

  6. Linux内核深入理解定时器和时间管理(1):硬件时钟和jiffies

    Linux内核深入理解定时器和时间管理 硬件时钟和jiffies rtoax 2021年3月 在原文基础上,增加5.10.13内核源码相关内容. 全局部变量 --------------------- ...

  7. Linux内核深入理解定时器和时间管理(6):x86_64 相关的时钟源(kvm-clock,tsc,acpi_pm,hpet)

    Linux内核深入理解定时器和时间管理 x86_64 相关的时钟源(kvm-clock,tsc,acpi_pm,hpet) rtoax 2021年3月 在原文基础上,增加5.10.13内核源码相关内容 ...

  8. Linux 内核定时器实验————复习到这

    目录 Linux 时间管理和内核定时器简介 内核时间管理简介 内核定时器简介 Linux 内核短延时函数 硬件原理图分析 实验程序编写 修改设备树文件 定时器驱动程序编写 编写测试APP 运行测试 编 ...

  9. 如何使用 Linux 内核定时器

    1. Linux内核定时器介绍 1.1 内核时间管理 内核中很多函数需要时间管理,比如周期性的调度程序.延时程序.定时器.硬件定时器提供时钟源,时钟源频率可以设置,设置好后就周期性的产生定时中断,系统 ...

最新文章

  1. 国内四大搜索站长工具
  2. Py之textgenrnn:textgenrnn库的简介、安装、使用方法详细攻略
  3. 五十四、最基础的冒泡排序
  4. >mysql -uroot -p Enter password: ERROR 1045 (28000): Access denied ,被mysql连接问题折磨到问题解决,分享
  5. nssl1192-加密【字符串hash】
  6. (十九)java多线程之ForkJoinPool
  7. 【报告分享】2019应届生求职趋势报告.pdf(附下载链接)
  8. 我们自身的认知可以改变吗?
  9. symantec病毒服务器的部署及配置
  10. 关于quartus ii 破解失败的问题
  11. hyperf获取客户端真实ip
  12. m序列产生原理及其性质
  13. 1-4 正弦和余弦
  14. android wps翻译功能吗,Android版WPS Office将支持金山词霸即时翻译
  15. vmware虚拟机网络设置详解
  16. html5 电子白板 直播,基于HTML5的电子白板的设计与实现
  17. JAVA高级视频_IO输入与输出_第一部分(System、Runtime、Date、Calendar、MathRandom、IO输入输出与概述、文件的续写、FileReader、复制文件、)...
  18. 《感冒+发烧》后的感受
  19. ts找不到primeng/primeng
  20. 【Python3.7】就餐人数:在为完成练习 9-1 而编写的程序中,添加一个名为 number_served 的属性,并将其默认值设置为 0。根据这个类创建一个名为 restaurant 的实例

热门文章

  1. python在字符串结尾加反斜杠_Python原始字符串和尾部反斜杠
  2. 倾斜模型精细化处理_基于倾斜摄影和近景摄影技术的实景三维模型结合(CC与 DPModeler结合)...
  3. [Ext JS] 3.3 树(Tree)的定义和使用
  4. [Ext JS 4] 动态加载
  5. 怎么使用计算机的移动与复制,Excel移动和公式的复制
  6. php 获得焦点,jquery中blur()失去焦点与focus() 获取焦点事件
  7. mysql密码加强_MySQL密码增强插件
  8. windows启动管理器_必备的9个Windows设置技巧,可以将Windows 10的性能大幅提高
  9. Windows环境下Docker常用命令
  10. 使用yum命令安装服务时,一直卡在Loaded plugins: fastestmirror Determining fastest mirrors