pc解读13:定时器的使用与时间获取
2013-06-04 18:51
232 查看
现代计算机上的操作系统基本上都是多任务的操作系统,每个任务轮流占用系统一个小时间片,系统速度如此之快,以至于每个任务都觉得自己占有整台计算机。同时现代计算机上运行着很多时间敏感的程序,比如定期备份系统,每日凌晨进行系统维护等等。要实现这些功能,离不开定时和计时的需求,而这些需求的高效实现离不开硬件的支持,我们来解读下,pc机给软件提供了怎样的平台。
RTC
最早的IBM-PC上有RTC实时时钟芯片,并且有电池供电,有了它,计算机就有了手表的功能,RTC是一个独立的系统,即使PC关机或者断电,仍可正常工作,这也是为什么机器关机后再次启动仍能保持时间的基础。RTC集成在南桥中。
既然RTC是一个独立的系统,那么程序指令能否访问到它呢,这是肯定的。在PC机中可以通过I/O端口0×70和0×71来读写RTC芯片中的寄存器。其中,端口0×70是RTC的寄存器地址索引端口,0×71是数据端口。接下来我们看看寄存器地址索引端口能索引到哪些东西。
最常见的RTC芯片是MC146818(Motorola),一共有64个寄存器。编号为0×00~0x3F,这些寄存器一共可以分为三组,时钟与日历寄存器组:共有10个(0×00~0×09),表示时间、日历的具体信息。在PC机中,这些寄存器中的值都是以BCD格式来存储的(比如23dec=0x23BCD)。状态和控制寄存器组:共有4个(0x0A~0x0D),控制RTC芯片的工作方式,并表示当前的状态。 CMOS配置数据:通用的CMOS RAM,它们与时间无关,因此我们暂时不关心它。可见,我们随时可以通过io访问指令读写系统时间。
PIT
时间有了,我们还需要定时器的功能。于是PIT(可编程间隔计时器)就出现了。PIT, 一般用8254芯片实现,信号来源是主板的晶振,根据时钟脉冲信号来计数,用来计数的存储单元是16位,所以最多接收65536个时钟信号就复原了。一般工作方式是程序设置一个初始值,然后每收到一个脉冲就自动减1,减到0时向系统发出中断信号,以达到定时功能。但由于只有16位数据,频率高了之后能定时时间太短,频率低了又不够精确,所以现在基本已经被淘汰了。该芯片本身有3个通道:通道0与IRQ0绑定,用于给操作系统提高时间中断,通道1通常用于DMA控制器对RAM的刷新,通道2被连接到PC机的扬声器,以产生方波信号。
东西在这了,怎么用是毕竟是软件的事情。但总得告诉软件用怎样的指令来控制他。与RTC一样,也是通过IO空间来访问。三个通道计数端口地址分别为 40h,41h,42h,再加一个控制寄存器43h。为什么要加一个控制器呢,原因是每个通道计数器是16位的,但是对应的端口地址是8位的,所以要读整个计数需要两次读相应的端口,先得告诉控制器你要读的是高8位数据还是第8位数据。同时每个通道还可以设置工作模式,每个通道可以有6种工作模式,由于PIT已经基本被淘汰了,所以也没有必要深究了,有兴趣的可以百度。
TSC
从Pentium 起,cpu提供一个寄存器 TSC,用来累计每一次外部振荡器产生的时钟信号,也就是说cpu每收到一个时钟脉冲,就修改tsc中的计数,相应的TSC寄存器是64位的,大大增长了计数能力。由于在整个系统中cpu频率是最高的,相应的TSC的精度就非常高。TSC寄存器是只读的,通过单独的指令rdtsc(read tsc)来读取。
问题是TSC获取的频率来源可能并不是固定的,因为有后来发展的降频技术,在cpu闲时,可把频率降下来以降低功率,节省能源。所以后来又出来了HPET。
HPET高精度定时器
HPET(High Precision Event Timer)俗称高精度定时器。是PIT 和 RTC 的替代者,提供了更高的时钟频率(至少10 MHz )以及更宽的计数器宽度。一个 HPET 包括了一个固定频率的数值增加的计数器以及3到32个独立的计时器,这每一个计时器有包涵了一个比较器和一个寄存器(保存一个数值,表示触发中断的时机)。每一个比较器都比较计数器中的数值和寄存器中的数值,当这两个数值相等时,将产生一个中断。对HPET的配置通过访问timer配置寄存器完成。该寄存器会被MMIO到某个内存区域(由BIOS阶段acpi权举得到),大小为1k(64bit上大小会最多到64k)。更详细的说明可百度。
RTC
最早的IBM-PC上有RTC实时时钟芯片,并且有电池供电,有了它,计算机就有了手表的功能,RTC是一个独立的系统,即使PC关机或者断电,仍可正常工作,这也是为什么机器关机后再次启动仍能保持时间的基础。RTC集成在南桥中。
既然RTC是一个独立的系统,那么程序指令能否访问到它呢,这是肯定的。在PC机中可以通过I/O端口0×70和0×71来读写RTC芯片中的寄存器。其中,端口0×70是RTC的寄存器地址索引端口,0×71是数据端口。接下来我们看看寄存器地址索引端口能索引到哪些东西。
最常见的RTC芯片是MC146818(Motorola),一共有64个寄存器。编号为0×00~0x3F,这些寄存器一共可以分为三组,时钟与日历寄存器组:共有10个(0×00~0×09),表示时间、日历的具体信息。在PC机中,这些寄存器中的值都是以BCD格式来存储的(比如23dec=0x23BCD)。状态和控制寄存器组:共有4个(0x0A~0x0D),控制RTC芯片的工作方式,并表示当前的状态。 CMOS配置数据:通用的CMOS RAM,它们与时间无关,因此我们暂时不关心它。可见,我们随时可以通过io访问指令读写系统时间。
PIT
时间有了,我们还需要定时器的功能。于是PIT(可编程间隔计时器)就出现了。PIT, 一般用8254芯片实现,信号来源是主板的晶振,根据时钟脉冲信号来计数,用来计数的存储单元是16位,所以最多接收65536个时钟信号就复原了。一般工作方式是程序设置一个初始值,然后每收到一个脉冲就自动减1,减到0时向系统发出中断信号,以达到定时功能。但由于只有16位数据,频率高了之后能定时时间太短,频率低了又不够精确,所以现在基本已经被淘汰了。该芯片本身有3个通道:通道0与IRQ0绑定,用于给操作系统提高时间中断,通道1通常用于DMA控制器对RAM的刷新,通道2被连接到PC机的扬声器,以产生方波信号。
东西在这了,怎么用是毕竟是软件的事情。但总得告诉软件用怎样的指令来控制他。与RTC一样,也是通过IO空间来访问。三个通道计数端口地址分别为 40h,41h,42h,再加一个控制寄存器43h。为什么要加一个控制器呢,原因是每个通道计数器是16位的,但是对应的端口地址是8位的,所以要读整个计数需要两次读相应的端口,先得告诉控制器你要读的是高8位数据还是第8位数据。同时每个通道还可以设置工作模式,每个通道可以有6种工作模式,由于PIT已经基本被淘汰了,所以也没有必要深究了,有兴趣的可以百度。
TSC
从Pentium 起,cpu提供一个寄存器 TSC,用来累计每一次外部振荡器产生的时钟信号,也就是说cpu每收到一个时钟脉冲,就修改tsc中的计数,相应的TSC寄存器是64位的,大大增长了计数能力。由于在整个系统中cpu频率是最高的,相应的TSC的精度就非常高。TSC寄存器是只读的,通过单独的指令rdtsc(read tsc)来读取。
问题是TSC获取的频率来源可能并不是固定的,因为有后来发展的降频技术,在cpu闲时,可把频率降下来以降低功率,节省能源。所以后来又出来了HPET。
HPET高精度定时器
HPET(High Precision Event Timer)俗称高精度定时器。是PIT 和 RTC 的替代者,提供了更高的时钟频率(至少10 MHz )以及更宽的计数器宽度。一个 HPET 包括了一个固定频率的数值增加的计数器以及3到32个独立的计时器,这每一个计时器有包涵了一个比较器和一个寄存器(保存一个数值,表示触发中断的时机)。每一个比较器都比较计数器中的数值和寄存器中的数值,当这两个数值相等时,将产生一个中断。对HPET的配置通过访问timer配置寄存器完成。该寄存器会被MMIO到某个内存区域(由BIOS阶段acpi权举得到),大小为1k(64bit上大小会最多到64k)。更详细的说明可百度。
相关文章推荐
- VC下毫秒级定时器、测量时间的获取、LARGE_INTEGER使用
- jquery计算时间差(天、时、分、秒)并使用定时器实时获取
- android中如何使用DatePicker获取时间
- python 学习笔记 13 -- 经常使用的时间模块之time
- jmeter 使用时间戳去redis获取验证码实现有验证码登录接口测试
- iOS NSDate的基本使用,获取时间戳
- java中使用Calendar获取指定日期前n个小时的时间日期
- 使用Smarty 获取当前日期时间和格式化日期时间的方法详解
- MFC 使用datetimepicker获取时间
- 在vb中使用Iphlpapi.dll获取网络信息 第二章 第十五节 设置本机默认的生存时间(time-to-live:TTL)值
- date使用_获取当前日期和时间
- c# 根据当前时间获取,本周,本月,本季度,月初,月末,各个时间段(转但是都是使用过)
- java使用new Date()和System.currentTimeMillis()获取当前时间戳
- 使用jquer获取当前时间,并赋值到input上。
- 使用php 获取时间今天明天昨天时间戳的详解
- 超时时间已到。超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小
- 使用Perl代码获取访问网页的载入时间
- 《Linux时间》--------------获取系统时间、设置系统时间、定时器
- PHP中使用mktime获取时间戳的一个黑色幽默分析
- 超时时间已到。超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。