当前课程知识点:Linux 内核分析与应用 > 第5章 中断 > 5.4 时钟中断机制 > Video
大家好 今天我们来介绍一下Linux的时间系统
时钟中断是特别重要的一个中断
因为整个操作系统的活动都受到它的激励
系统利用时钟中断维持系统时间
促使进程的切换 以保证所有进程共享CPU
利用时钟中断进行记帐 监督系统工作以及确定未来的调度优先级等工作
可以说“时钟中断”是整个操作系统的脉搏
那么我们首先介绍一下基本的时钟硬件
Linux的OS时钟的物理产生原因是什么呢
是可编程定时/计数器产生的输出脉冲
这个脉冲送入CPU以后呢 就可以引发一个中断请求信号
我们就把它叫做时钟中断
那么时钟中断的周期呢 也就是脉冲信号的周期
我们叫做“滴答”或者“节拍”
从本质上说呢 时钟中断只是一个周期性的信号 完全呢是硬件的行为
该信号触发CPU执行一个中断服务程序
这是最简单的时钟硬件 在目前的系统中呢还有更多相关的时钟硬件
那么我们下面就来介绍与时钟有关的硬件
第一个叫做实时时钟RTC
它是干什么的呢 用于长时间存放系统时间的设备
即使关机后也可依靠主板CMOS呢来维持系统的计时
第二个叫做可编程间隔器计数器
该设备可以周期性的发送一个时间中断信号
在Linux系统中,该中断时间间隔由HZ表示
这个时间间隔也被称为一个节拍(tick)
第三个叫时间戳计数器
CPU附带了一个64位的时间戳寄存器
当时钟信号到来的时候 该寄存器内容自动的加1
那么第四个呢叫高精度计时器(HPET)
这是一种由intel开发的新型定时器芯片
该设备有一组计时器 每个计时器对应有自己的时钟信号
那么时钟信号到来的时候就会自动加1
第五个叫CPU本地定时器
在处理器的本地APIC中提供的一个定时设备
可以单次或者周期性的产生中断信号
最后一个我们叫高精度定时器(hrtimer)
这个定时器是目前最常用的 它提供纳秒级的定时精度
以满足对精确时间有迫切需求的应用程序或者内核驱动
例如多媒体应用 音频设备的驱动程序等等
在这6个相关硬件中呢 其中有2个计时器
2个定时器每个呢都有其特定的功能
下面我们来介绍一下基本的时钟运作机制
从这张图中我们看出一般来说 RTC是OS时钟的时间基准
操作系统通过读取RTC来初始化OS时钟
在此之后呢二者保持同步运行
共同维持着系统时间
所谓同步是什么意思呢 是指操作系统在运行过程中呢
每隔一个固定时间会刷新或者校正RTC中的信息
Linux中的时钟运作机制如图所示
OS时钟和RTC时钟之间要通过BIOS连接
是因为传统PC机的BIOS中固化有对RTC进行有关操作的函数
通常操作系统也直接利用这些函数对RTC进行操作
例如从RTC中读出有关数据对OS时钟初始化
对RTC呢进行更新等等
Linux在内核初始化完成后就完全抛弃了BIOS中的程序
我们看到RTC处于最底层 提供最原始的时钟数据
而OS时钟呢建立在RTC之上
初始化完成后将完全由操作系统控制
RTC呢就脱离了关系
操作系统通过OS时钟提供给应用程序所有和时间有关的服务
因为OS时钟完全是一个软件问题
其所能表达的时间由操作系统的设计者决定
将OS时钟定义为整型还是长整型
或者更大的超乎想象的数据都是由操作系统的设计者决定的
那么下面我们来看一下Linux中的时间系统
我们说操作系统的“时间基准”呢它是由设计者决定的
那么Linux的时间基准是1970年1月1日凌晨0点
OS时钟记录的时间就是系统时间
系统时间以“时钟节拍”为单位
什么是时钟节拍呢 时钟节拍表示发生一次中断的时间
比如说1ms
那么Linux中用全局变量jiffies表示系统自启动以来的时钟节拍数
比如系统启动了N秒 那么jiffies就为N×HZ
实际时间存放在内核的xtime变量中
系统启动时内核通过读取RTC来初始化实际时间
下面我们来介绍一下Linux的时钟框架
Linux时钟框架相当复杂 我们在此给予简述
如果你输入date命令 内核从哪个部件获取时间的呢
从这张图告诉大家 是从时钟源clock source
从硬件层来说呢 它其实就是固定时钟频率驱动的计数器
所谓计数器其实就是简单单调的加一操作 直到溢出为止
对于真实的用户来说 我们感知的是真实世界的真实时间
也就是所谓的墙上时间
那么clocksource只能提供一个按给定频率不停递增的周期计数
如何把它和真实的墙上时间相关联 这就是timekeeper
那么时钟事件设备(clock_event_device)起什么作用呢
它主要用于实现普通定时器和高精度定时器
同时也用于产生节拍tick事件 供给进程调度子系统使用
在软件架构上看 时钟事件设备被分为了两层
与硬件相关的被放在了machine层
与硬件无关的通用代码则被集中到了通用时间框架层
这符合内核对软件的设计需求
平台的开发者只需实现平台相关的接口即可
无需关注复杂的上层时间框架
tick_device起什么作用呢 它是基于时钟事件设备的进一步封装
用于代替原有的时钟滴答中断 给内核提供节拍事件
以完成进程的调度和进程信息统计
负载平衡和时间更新等操作
那么在这个图中我们主要来介绍一下高精度定时器的实现机制
高分辨率定时器的代码实现的时候呢
内核的开发者考察了多种数据结构 比如说
基数树哈希表等等 最终选择了哪一种数据结构呢
就是内核中常用的红黑树(rbtree)来组织hrtimer
hrtimer不停地被创建和销毁
新的hrtimer按顺序被插入到红黑树中
树的最左边的节点就是最快到期的定时器
咋每个cpu都有一个hrtimer_cpu_base结构
这个结构管理着3种不同的时间基准系统的hrtimer分别是
实时时间 启动时间和单调时间
每种时间基准系统通过它的一个字段呢 指向它各自的红黑树
关于具体的代码大家可以参考源代码中的相关代码
下面呢我们对定时器
做一个简单的介绍以及它如何简单的应用
定时器是管理内核所花时间的基础 也被称为动态定时器或内核定时器
定时器的使用步骤是这样的
首先执行一些初始化工作 然后呢设置一个到期时间
指定到期以后要执行的函数 然后激活定时器就可以了
那么定时器的数据结构是什么样子呢 在内核中它叫做timer_list结构
如图所示
那么如何使用定时器呢 我们有这么几个步骤 首先定义定时器
通过struct timer_list可以定义一个定时器
然后调用初始化函数init_timer()对它进行初始化 也就是说填充定时器的结构
那么填充好以后就激活定时器 通过add_timer这个函数
那么如果需要修改定时器 则可以调用相应的修改函数mod_timer
如果需要在定时器到期前停止定时器的话 可以使用
删除函数del_timer 对定时器进行停止
那么定时器如何进行执行呢
在内核在时钟中断发生以后就执行定时器了
那么定时器作为软中断它实际上是在下半部分
被执行的由哪一个函数来执行呢 被run_timer_softirq()来执行的
那么下面我们来看一下定时器的应用
这里我们给了一段代码 下面我们对代码做一个简要的介绍
首先设置进程的状态为不可中断的睡眠
然后编写内核定时器实现进程的延时
其中呢首先对定时器的各个字段赋初值
然后通过激活函数add_timer()激活定时器
再调用调度函数schedule()让该进程挂起
最后调度删除函数del_time()删除定时器
具体实现的代码参看内核之旅上的相关代码
最后我们对Linux时钟子系统给一个简要的总结
随着应用环境的改变使用需求的多样化 Linux 的时钟子系统也在不断的衍变
为了更好的支持音频等时间精度高的应用
Linux 提出了hrtimer这一高精度的时钟子系统
为了节约能源 Linux 改变了长久以来一直使用的基于HZ的tick机制
采用了无节拍(tickless)系统
即使是在对硬件平台的支持上呢 也是在不断的改进
Linux定时器机制比较复杂 本讲只是做一个简要的介绍
那么参考资料呢 我们来参考《深入理解Linux内核》第三版的第六章
同样我们带着思考离开
系统有了低精度定时器 为什么还要有高精度定时器
二者之间兼容吗 在实现上有什么样的关系
好 本讲就讲到这里 谢谢大家
-1.1 Linux操作系统概述
-1.2 Linux内核结构以及内核模块编程
--Video
-1.3 Linux内核源码中的双链表结构
--Video
-1.4 源码分析-内核中的哈希表
--Video
-1.5 动手实践-Linux内核模块的插入和删除
--Video
-第1章 概述--章节测验
-2.1 内存管理之内存寻址
--Video
-2.2 段机制
--Video
-2.3分页机制
--Video
-2.4 动手实践-把虚拟地址转换成物理地址
--Video
-第2章 内存寻址--章节测验
-3.1 进程概述
--Video
-3.2 Linux进程创建
--Video
-3.3 Linux进程调度
--Video
-3.4 动手实践-打印进程描述符task_struct中的字段
--Video
-3.5工程实践-基于内核模块的负载监控
--Video
-第3章 进程管理--章节测验
-4.1 Linux内存管理机制
--Video
-4.2 进程用户空间管理机制
--Video
-4.3 物理内存分配与回收机制(上)
--Video
-4.4 物理内存分配与回收机制(下)
--Video
-4.5 动手实践-Linux内存映射基础(上)
--Video
-4.6 动手实践-Linux内存映射实现(中)
--Video
-4.7 动手实践-Linux内存映射测试(下)
--Video
-4.8 初学者对内存管理的常见疑惑
-第4章 内存管理--章节测验
-5.1 中断机制概述
--Video
-5.2 中断处理机制
--Video
-5.3 中断下半部处理机制
--Video
-5.4 时钟中断机制
--Video
-5.5 动手实践-中断上半部的代码分析及应用
--Video
-5.6 动手实践-中断下半部的代码分析及应用
--Video
-第5章 中断--章节测验
-6.1 Linux中的各种API
--Video
-6.2 系统调用机制
--Video
-6.3 动手实践-添加系统调用(系统调用日志收集系统)
--Video
-第6章 系统调用--章节测验
-7.1 内核同步概述
--Video
-7.2 内核同步机制
--Video
-7.3 动手实践-内核多任务并发实例(上)
--Video
-7.4 动手实践-内核多任务并发实例(下)
--Video
-第7章 内核同步--章节测验
-8.1 虚拟文件系统的引入
--Video
-8.2 虚拟文件系统的主要数据结构
--Video
-8.3 文件系统中的各种缓存
--Video
-8.4 页高速缓存机制以及读写
--Video
-8.5 动手实践-编写一个文件系统(上)
--Video
-8.6 动手实践-编写一个文件系统(中)
--Video
-8.7 动手实践-编写一个文件系统(下)
--Video
-第8章 文件系统--章节测验
-9.1 设备驱动概述
--Video
-9.2 I/O空间管理
--Video
-9.3 设备驱动模型
--Video
-9.4 字符设备驱动程序简介
--Video
-9.5 块设备驱动程序简介
--Video
-9.6 动手实践-编写字符设备驱动程序
--Video
-9.7工程实践-编写块设备驱动的基础(上)
--Video
-9.8 工程实践-块设备驱动程序分析(中)
--Video
-9.9 工程实践-块设备驱动程序实现(下)
--Video
-第9章 设备驱动--章节测验
-致谢与说明
--Video