【Linux操作系统分析】定时测量——RTC,TSC,PIT,jiffies,计时体系结构,延迟函数

 

1 基本概念

定时机制连同一些更可见的内核活动(如检查超时)来驱使进程切换。

两种主要的定时测量:

  • 保存当前的时间和日期,以便能通过time(), ftime()和gettimeofday()系统调用把它们返回给用户程序。
  • 维持定时器,这种机制能够告诉内核或用户程序某一时间间隔已经过去了。

定时测量是由基于固定频率振荡器和计数器的几个硬件电路完成的。

2 时钟和定时器电路

时钟电路用于跟踪当前时间和产生精确的时间度量。

定时器电路由内核编程,所以它们以udingde,预先定义的频率发出中断。

时钟电路的分类

  • 用于跟踪当前时间

    • 实时时钟RTC
    • 时间戳计数器TSC
  • 产生周期性的时钟中断,用于计时

    • 可编程间隔定时器PIT

2.1 实时时钟RTC——IRQ8上产生中断

当PC被切断电源,RTC还继续工作。

内核通过0x70和0x71I/O端口访问RTC。

能在IRQ8上发出周期性的中断,频率在2HZ~8192HZ之间,可编程

2.2 时间戳计数器TSC

在80x86微处理器中,有一个CLK输入引线接收外部振荡器的时钟信号。TSC在每个时钟信号到来时加1.

TSC是一个64位的时间戳计数器寄存器,汇编指令rdtsc读这个寄存器。Linux在初始化时系统时必须确定时钟信号的频率。

获得tsc的时钟频率:calibrate_tsc()函数通过计算一个大约在5ms的时间间隔内所产生的时钟信号的个数来算出CPU实际频率。

Linux通过rdtscll()或rdtscl()用来读取TSC的事。

与可编程间隔定时器相比,TSC可以获得更精确的时钟。

2.3 可编程间隔定时器PIT

使用I/O端口0x40~0x43

LInux给PC的第一个PIT进行编程,使它以大于1000Hz的频率向IRQ0发出时钟中断,即每1ms产生一次时钟中断,这个时间间隔叫做一个节拍(tick),它的长度以纳秒为单位存放在tick_nsec变量中。

由setup_pit_timer()进行初始化。在init_pit_timer()中初始化时钟中断频率。

与系统时钟信号有关的宏定义:

(1)宏定义Hz

在不同的体系机构下,系统时钟所要求的可编程定时器中断的频率,即每秒tick的个数

(2)宏定义CLOCK_TICK_RATE

记录了不同体系结构下,驱动可编程定时器工作的输入时钟频率

(3)宏定义LATCH

记录了上述两个宏定义的比值,用于在内核初始化过程中设置可编程定时器中计数器寄存器counter的初始值。

3 Linux计时体系结构

LInux的计时体系结构是一组与时间流相关的内核数据结构和函数。

功能:

  • 更新自系统启动以来所经过的时间
  • 更新时间和日期
  • 确定当前进程的执行时间,考虑是否要抢占
  • 更新资源使用统计计数
  • 检查到期的软定时器

内核有两个基本的计时函数:

  • 保持当前最新的时间
  • 计算在当前秒内走过的纳秒数

在单处理器系统中,所有定时活动都由IRQ0上的时钟中断触发,包括:

  • 在中断中立即执行的部分
  • 作为下半部分延迟执行的部分

3.1 计时体系结构的数据结构

3.1.1定时器对象(时钟源)

为了使用一种统一的方法来处理可能存在的定时器资源,内核使用能够了“定时器对象”,它是timer_opts类型的一个描述符。其中最重要的两个方法:

mark_offset:由时钟中断处理程序调用,并以适当的数据结构记录每个节拍到来时的准确时间。

get_offset:使用已记录的值来计算上一次时钟中断(节拍)以来经过的时间。

这两种方法,使得Linuxd计时体系结构能够打到子节拍的分辨率,也就是说,内核能够以比节拍周期更高的精度来测定当前的时间,这种操作被称为“定时插补”。

在内核初始化期间,select_timer()函数设置cur_timer指向适当定时器对象(时钟源)的地址。变量timer_cur存放了某个定时器对应的那个的地址,该定时器是系统可利用的定时器资源中最好的。

3.1.2jiffies变量

一个计数器,用来记录自系统启动以来产生的节拍总数。

因为一秒钟内产生系统时钟中断次数等于宏定义HZ的值,所以变量jiffies的值在一秒内增加HZ。

3.1.3xtime变量

xtime变量存放当前时间和日期,它是一个timespec类型的数据结构。以便内核对某些对象和事件作时间标记,如记录文件的创建时间、修改时间、上次访问时间,或者供用户进程通过系统调用来使用。

基本每个tick更新一次。

3.2 单处理器系统上的计时体系结构

考点:tick_handle_periodic函数的功能(Linux的计时体系结构的功能)

tick_init调用clockevents_tegister_notifier注册tick_notifier到clockevents_chain上。

Update_wall_time()完成变量xtime的更新。

time_init_hook()来设置系统时钟中断处理程序。

在时钟中断处理函数中:

会调用tick_init函数,书上很多流程中的函数最终都是被这个函数所调用,流程如下:

4 软定时器和延迟函数

软定时器:

  • 动态定时器(内核)
  • 间隔定时器(可以用户)

动态定时器:被动态的创建和撤销,当前活动的动态定时器个数没有限制

定时器是一种软件功能,即允许在将来的某个时刻,函数在给定的时间间隔用完时被调用。每个定时器都包含一个字段,表示定时器将需要多长时间才到期。这个字段的初值就是jiffies的当前值加上合适的节拍数。

注意,对于必须严格遵守定时时间的那些实时应用而言,定时器并不适合,因为定时器的检查总是由可延迟函数进行。

4.1创建并激活一个动态定时器——init_timer初始化一个time_list对象

  • 创建一个新的timer_list对象
  • 调用init_timer初始化,并设置定时器要处理的函数和参数
  • 设置定时时间
  • 使用add_timer加入到合适的链表中
具体的步骤:

4.2动态定时器的数据结构

用于和系统核心变量jiffies进行比较。

  • 成员变量function:该函数指针变量保存了内核定时器超时后要执行的函数,即定时器超时处理函数。
  • 成员变量data:该无符号长整型变量用作定时器超时处理函数的参数。
  • 成员变量base:该指针变量表明了该内核定时器节点归属于系统中哪一个处理器,在使用函数init_timer()初始化内核定时器节点的过程中,将该指针指向了一个每处理器变量tvec_bases的成员变量t_base。

4.3动态定时器的维护

run_timer的主要功能

  • 定时器时间表示参数加一
  • 处理的定时器去除
  • 依次处理到期定时器

动态定时器应用之delayed work

动态定时器应用之schedule_timeout:  setup_time_on_stack(&timer, process_timeout, (unsigned long)current);  timer时间到了之后,process_timeout函数将当前进程变为等待态。

4.4延迟函数:

当内核需要等待一个较短的时间间隔,如几毫秒,通常设备驱动器会等待预先定义的整个微秒直到硬件完成某些操作。这些情况下,内核使用udelay()和ndelay()函数:前者接收一个微秒级的时间间隔作为它的参数,并在指定的延迟结束后返回,后者与前者类似,但是指定延迟的参数是纳秒级的。

http://www.cnblogs.com/suzhou/archive/2013/06/04/3638986.html

Linux计时体系结构的更多相关文章

  1. Linux异常处理体系结构

    arm11处理器裸机的异常与中断处理参考: [OK6410裸机程序]异常处理 [OK6410裸机程序]按键中断 另外参考一篇:Linux中断体系结构 在ARM V4及V4T以后的大部分处理器中,中断向 ...

  2. 字符设备驱动-------Linux异常处理体系结构

    裸机中断流程 外部触发 CPU 发生中断, 强制的跳到异常向量处 跳转到具体函数 保存被中断处的现场(各种寄存器的值) 执行中断处理函数,处理具体任务 恢复被中断的现场 Linux处理异常流程 异常发 ...

  3. linux文件系统体系结构 和 虚拟文件系统(VFS)

    图 1. Linux 文件系统组件的体系结构 用户空间包含一些应用程序(例如,文件系统的使用者)和 GNU C 库(glibc),它们为文件系统调用(打开.读取.写和关闭)提供用户接口.系统调用接口的 ...

  4. linux内核体系结构

    linux内核第一记   1.linux体系结构   从上图可知,Linux分为:用户空间和内核空间.内核空间和用户空间是程序执行的两种不同的状态,通过系统调用和硬件中断能够完成从用户空间到内核空间的 ...

  5. Linux中断体系结构

    1.中断处理体系结构 Linux内核将所有中断统一编号,使用一个irq_desc结构数组来描述这些中断. 数组声明在/linux/kernel/irq/handle.c中,其中#define NR_I ...

  6. 字符设备驱动-----Linux中断处理体系结构

    一.中断处理体系结构的初始化 Linux内核将所有的中断统一编号,使用一个irq_desc结构数组来描述这些中断;每个数组项对应一个中断,也可能是一组中断,它们共用相同的中断号,里面记录了中断的名称. ...

  7. 1.字符设备驱动------Linux中断处理体系结构

    一.中断处理体系结构的初始化 Linux内核将所有的中断统一编号,使用一个irq_desc结构数组来描述这些中断;每个数组项对应一个中断,也可能是一组中断,它们共用相同的中断号,里面记录了中断的名称. ...

  8. linux的学习记录随笔

    为什么学习linux 因为操作系统是一种介质,你要接触其中的东西,首先必须要有介质,而linux在服务器端是老大哥的地位,所以呢,学习linux吧. 学习的方式 可以看视频 imooc.百度传课.网易 ...

  9. Linux 网络子系统

    今天记录一下Linux网络子系统相关的东西. 因为感觉对这一块还是有一个很大的空白,这件事情太可怕了. 摘抄多份博客进行总结一下Linux网络子系统的相关东西. 一. Linux网络子系统体系结构 L ...

随机推荐

  1. 二叉树的实现 -- 数据结构与算法的javascript描述 第十章

    /** * 树,一种非线性的数据结构. 以分层的方式存储数据. * 一棵树最上面的节点成为根节点,如果一个节点下面有多个节点,这个节点称为父节点,下面的节点称为子节点 * 没有任何子节点的节点,陈宝国 ...

  2. 由RGB到HSV颜色空间的理解

    1. RGB模型 2. HSV模型 3. 如何理解RGB与HSV的联系 4. HSV在图像处理中的应用 5. opencv中RGB-->HSV实现 在图像处理中,最常用的颜色空间是RGB模型,常 ...

  3. hadoop 配置文件注意问题

    一定要配置成hostname形式: 如伪分布:配成localhost:9000 完全分布:配成big1:9000

  4. iOS中关于动态Tableview中的cell数据传输的多线程问题解决之拙见

    iOS中关于动态Tableview中的cell数据传输的多线程问题解决之拙见 (2015-12-05 12:48:20)[编辑][删除] 转载▼     首先我们先明确一下问题: 1.因为UI是在主线 ...

  5. ##DAY9 UITabBarController

    ##DAY9 UITabBarController UIViewController的tabBarController UIViewController的tabBarItem #pragma mark ...

  6. BZOJ 2716: [Violet 3]天使玩偶( CDQ分治 + 树状数组 )

    先cdq分治, 然后要处理点对答案的贡献, 可以以询问点为中心分成4个区域, 然后去掉绝对值(4种情况讨论), 用BIT维护就行了. --------------------------------- ...

  7. mysql数据库中列转行

    今天突然想到了数据库中的行专列与列转行,还不熟悉,在上网看了一下然后就自己写了个例子. 数据库表示这样滴! //全部查询出来SELECT (case type when 'MySql数据库' then ...

  8. nodejs事件机制

    var EventEmitter = function() { this.evts = {}; }; EventEmitter.prototype = { constructor: EventEmit ...

  9. C#学习日志 day 5 ------ windows phone 8.1真机调试手机应用

    在vs2013中,可以写windows phone 8.1的程序,但是调试时需要用到windows自带的虚拟机hyper-V 正版的系统开启hyper—V的时候不会有问题,但是盗版的系统可能导致系统不 ...

  10. Gson使用初探

    参考地址: http://www.stormzhang.com/android/2014/05/22/android-gson/ 我的示例代码: public void doGsonTest(View ...