第五章  定时测量

内核必须显式地与三种时钟打交道:实时时钟(Real Time Clock, RTC)、时间标记计数器(Time Stamp Counter, TSC)及可编程间隔定时器( ProgrammableIntervalTimer,PIT)。前两种硬件设备允许内核跟踪当前的时间;后一种设备由内核编程,以使它能以固定的、预先定义的频率发出中断。对于内核和用户程序使用的定时器来说,这样的周期性巾断是至关重要的。

实时时钟:

所有的PC都包含了一个叫实时时钟(RTC)的时钟.它是独立于CPU和所有其他芯片的。即使当PC关掉电源,RTC还继续走,因为它靠个小电池或蓄电池供电。RTC能发出周期性的中断,可作为一个闹钟来工作。

Linux只用RTC来获得时间和日期,然而,通过作用于/dev/rtc设备文件,也允许进程对RTC编程。内核通过0x70和0x71 1/O端口存取RTC。通过执行/sbin/clock系统程序(它直接作用于这两个I/O端口),系统管理员可以配置时钟。

时间标记计数器

一个64位的时间标记计数器(TSC)的寄存器,可以通过汇编语言指令rdtsc读这个寄存器。这个寄存器是一个计数器,它在每个时钟信号到来时加1,例如,如果时钟节拍的频率是400 MHz,那么,时间标记计数器每2.5纳秒增加一次。Linux 利用这个寄存器获得精准的时间测量

可编程间隔定时器

时间测量设备,到了发定时中断,PLT以某一固定的频率(由内核决定)不停地发出中断,定时中断的间隔叫做节拍,

时间计数器TSC :

如果CPU有TSC寄存器,用do_ gett imeofday()计算当前时间,否则,用

do_ normal_ gettime()计算。 在do_ _get_ fast_ time变量存放的指针指向合适的函数。

当TSC寄存器可用时,用do_ fast_ gett imecffset ()计算微秒数,否则,用do_ slow_ gect imeof fset ()计算。这个函数的地址存放在do_ gett imeoffset变量中。

在内核启动时运行的time_ init() 函数能将这些变最指向正确的函数。

进程描述符的counter域表示进程在CPU上运行剩余节拍数。(counter由一个下半部分以延缓的方式更新,一次递减可能大于一个节拍),变得小于0时,把need_resched置为1,恢复用户态程序执行时掉schedule,换程序在CPU执行

系统调用函数adjtimex(),每660s调用set_rtc_mmss调整一次实时时钟。

定时器:

一种软件工具,每个定时器有一个域,表示需要多长时间到期,jiffies+正确节拍数,每次内核检查定时器,就用jiffies和这个比较。由于使用下半部分,所以不能严格遵守时间(延迟几百ms)

Linux有三种类型的定时器,静态定时器,动态定时器和间隔定时器,前两者有内核使用,第三种可以由进程在用户态创建。

静态定时器

存在timer_table数组,每项一个结构体,

struct t imer_ struct (
unsigned long expires;

void (*fr.) lvoid) ;
);

expires域指定定时器到期时间。这个时间被表示成自系统启动以来的时钟节拍数。expires值小于或等于jiffies值的所有定时器就认为是到期了或停止了。fn域包含定时器到期时被执行函数的地址。

静态定时器检测工作也是由TIMER_BH下半部分调用函数检查。在内核激活一个定时器时,要在timer_active设置合适的 标志,这里会先清0然后执行fn。

动态定时器

struct timer_
list {

struct timer_
list *noxt;

struct tiner_
list *prev;

unsigned long
expires;

uns igned long
data ;

void (* funct
ion) (uns-gned 1ong) ;

};.

function域包含定时器到期时要执行函数的地址。data域指定传递给这个定时器函数的参数。

data域使得定义一个通用闲数处理几个设备驱动程序的定时问题成为可能,可以在data域存放设备ID,或其他有意义的数据,这些数据可被用来区分不同设备的函数使用。

expires域的含义与静态定时器相应域的含义相同。,

next和prev域实现双向循环链表的连接。事实上,每个活动动态定时器根据expires的值被精确地插人到512个双向循环链表的其中-一个中。在本章稍后将描述使用这个链表的算法。

动态定时器的遍历不像静态的是单循环,使用了一个聪明的数据结构。这个数据结构叫tvecs的数组,数组的元素指向tv1-5结构标识的链表。tv1是struct timer_vec_root,

struct timer_vec_root (
int index;
Struct timer_list *vec[TVR_SIZE] ;
);

其TVR_SIZE为256,index指定当前扫描的链表,每个节拍时增1,模256为0时,由tv2-tv5顺序补充。每个vec指向一个timer_ list链表。

tv2-tv4这个TVR_SIZE为64,炎型为struct timer_vec的tv2、tv3及tv4結枸分別包含了在緊接着到来的214-1、220-1及226-1个节拍内將要到期的所有动态定吋器。

tv5的结构与前面的几个结构相同,除了vec数组的最后一项包含的动态定时器expires域的值可以任意大,它再也不需要从另一个数组进行补充了。

动态定时器的应用:在一些情况下,例如,当内核不能提供一个给定的服务时,就可以把当前进程挂起一个固定的时间。这通常是通过执行一个进程延时完成的。

与定时测量相关的系统调用:

Gettimeofday():该函数实现了time()和ftime(),root用户可以调用stime或settimeofday来修改当前日期和时间,不过请注意当这两个系统调用修改xtime的值时都没有修改RTC寄存器,因此当系统关机时新的时间会丢失,除非用户执行/sbin/clock这个程序来改变RTC的值。

Settimer和alarm:间隔定时器,

通过POSIX setit imer ()系统调用可以激活间隔定时器。第一个参数指定应当采取下面的哪一个策略:

ITIMER_REAL:真正过去的时间;进程接受SIGALRM信号
ITIMER_VIRTUAL:进程在用户念下花费的时间;进程接受SIGVTALRM信号
ITIMER_PROF:进程既在用户态下又在内核态下所花费的时间;进程接受SIGPROF信号
为了能分别实现前述每种策略的间隔定时器,进程描述符要包含三对域:
it_real_incr 和it_real_value
it_virt_incr 和it_virt_value
it_prof_incr 和it_prof_value

每对中的第一个域存放着两个信号之间以节拍为单位的问隔;另一个城存放着定时器的当前值。

ITIMER_REAL间隔定时器是利用动态定时器实现的,因为即使进程不在CPU上运行时,内核也必须向进程发送信号。因此,每个进程描述符包含一个叫real_ timer的动态定时器对象。setitimer(}系统调用初始化rea1_timer域,然后调用add_timer()把动态定时器插人到合适的链表中。当定时器到期时,内核执行it_rea1_fn()定时函数。依次类推,it_real_in() 函数向进程发送一个SIGALRM信号。如果it_real_incr不为空,那么它会再次设置expires城,重新激活定时器。

ITIMER_VIRTUAL和ITIMER_PROF间隔定时器不需要动态定时器,因为只有当进程运行时,它们才能被更新: do_it_virt()和dc_it_prof () 由update_ore_process ()调用,当执行TIMER_BH下半部分时update_one_process()才运行。因此,每个节拍中,这两个间隔定时器通常都被更新--次,并且如果它们到期,就给当前进程发送一个合适的信号。

a1arm()系统调用会在一个指定的时间间隔用完时向调用的进程发送一个SIGALRM信号。当以ITIMER_ REAL为参数调用时,它非常类似于setitimer(),因为它利用了包含在进程描述符中的real_timer动态定时器。因此,不能同时使用以ITIMER_REAL为参数的alarm()和setitimer()。

深入理解Linux内核 学习笔记(5)的更多相关文章

  1. 深入理解Linux内核 学习笔记(1)

    1.用户和用户组 每个用户是一个或多个用户组的一名成员,组由唯一的用户组标识符(user group ID)标识.每个文件的相关权限也恰好与一个组相对应. root为超级用户, 2.模块 为了达到微内 ...

  2. 深入理解Linux内核 学习笔记(4)

    第四章 中断和异常 中断通常被分为同步中断和异步中断,同步中断是当指令执行时由CPU控制单元产生的,之所以称为同步,是因为只有在一条指令终止执行后CPU才会发出中断异步中断是由其他硬件设备依照CPU时 ...

  3. 深入理解Linux内核 学习笔记(3)

    第三章 进程 可以看到很多熟悉的结构体 进程状态: 可运行状态(TASK_ RUNNING) 进程要么在CPU上执行,要么准备执行. 可巾断的等待状态(TASK_ INTERRUPTIBLE) 进程被 ...

  4. 深入理解Linux内核 学习笔记(2)

    第二章 :内存寻址 略.基本同计算机组成原理中的讲述 内核代码和数据结构会存储在一个保留的页框中. 常规Linux安装在RAM物理地址0x00100000开始的地方.因为:页框0是由BIOS使用,存放 ...

  5. 深入理解Linux内核 学习笔记(8)

    第八章 系统调用 API定义了一个给定的服务:系统调用是通过软中断向内核发出一个明确的请求. API可能不调用系统调用,也可能调用多个系统调用. Linux系统调用必须通过执行int 0x80,系统调 ...

  6. 20135316王剑桥Linux内核学习笔记

    王剑桥Linux内核学习笔记 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 计算机是如何工作的 个人理 ...

  7. Linux内核学习笔记-2.进程管理

    原创文章,转载请注明:Linux内核学习笔记-2.进程管理) By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ...

  8. Linux内核学习笔记-1.简介和入门

    原创文章,转载请注明:Linux内核学习笔记-1.简介和入门 By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ...

  9. Linux内核学习笔记二——进程

    Linux内核学习笔记二——进程   一 进程与线程 进程就是处于执行期的程序,包含了独立地址空间,多个执行线程等资源. 线程是进程中活动的对象,每个线程都拥有独立的程序计数器.进程栈和一组进程寄存器 ...

随机推荐

  1. shell脚本头,#!/bin/sh与#!/bin/bash的区别.

    因为今天写了个小脚本,死活不成功,总是报文件或者目录不存在,问了一下我们马同学的正常写法,发现只有脚本头的区别,也就是今天本文要讲的#!/bin/sh与#!/bin/bash. 本文参考:https: ...

  2. Map的四种遍历

    //Map的四种遍历方法 public static void main(String[] args) { Map<String, String> map = new HashMap< ...

  3. PHP 7 新特性

    PHP 7 新特性 标量类型声明 PHP 7 中的函数的形参类型声明可以是标量了.在 PHP 5 中只能是类名.接口.array 或者 callable (PHP 5.4,即可以是函数,包括匿名函数) ...

  4. 输入流IS和输出流OS学习总结

    1.我们编写的程序,除了自身会定义一些数据信息外,经常还会引用外界的数据,或是将自身的数据发送到外界,比如我们编写的程序想读取一个文本文件, 又或者是我们想将程序的一些数据写到一个文件中,这时我们就要 ...

  5. window安装mysql5.7解压版(解决乱码问题)

    ♣安装mysql两种方法 ♣下载mysql5.7解压版 ♣配置步骤 ♣解决服务无法启动 ♣解决乱码 1.安装mysql两种方法 MySQL安装文件分为两种,一种是msi格式的,一种是zip格式的.如果 ...

  6. maven的pom文件中指定编译的版本

    <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> ...

  7. capwap学习笔记——初识capwap(二)(转)

    2.5.1 AC发现机制 WTP使用AC发现机制来得知哪些AC是可用的,决定最佳的AC来建立CAPWAP连接. WTP的发现过程是可选的.如果在WTP上静态配置了AC,那么WTP并不需要完成AC的发现 ...

  8. OAuth 2 开发人员指南(Spring security oauth2)

    https://github.com/spring-projects/spring-security-oauth/blob/master/docs/oauth2.md 入门 这是支持OAuth2.0的 ...

  9. 背景图片蒙上一层颜色(背景图片无法用rgba调整透明度!)

    方法就是在图片上面加一层DIV,将DIV的背景颜色调成rgba(0,0,0,0.3);即可

  10. 常见js特效的思路

    1.焦点轮播路 1.布局:父容器用overflow:hidden隐藏多余的图片 2:通过ID获取到重要的元素(父容器.图片列表.左右切换按钮等) 给左右按钮加上点击事件,通过JS更新图片的位置,判断边 ...