第五章 定时器及时钟服务
5.1硬件定时器
定时器是由时钟源和可编程计数器组成的硬件设备。时钟源通常是一个晶体振荡器,会产生周期电信号,以精确的频率驱动计数器。使用一个倒计时值对计数器进行编程,每个时钟信号减1.当计数减为0时,计数器向CPU生成一个定时器中断,讲计数值重新加载到计数器中,并重复倒计时。计数器周期称为定时器可读,是系统的基本计时单元。
5.2个人计算机定时器
(1)实时时钟(RTC)
(2)可编程间隔定时器(PIT)
(3)多核CPU中的本地定时器
(4)高分辨率定时器
5.3CPU操作
每一个CPU都有一个程序计数器(PC),也成为指令指针(IP),以及一个标志或状态寄存器(SR)、一个堆栈指针(SP)和几个通用寄存器。
5.4时钟服务函数
1、gettimeofday-settimeofday
#include<sys/time.h>
int gettimeofdat(struct timeval *tv,struct timezone *tz);
int settimeofdat(const struct timeval *tv,const struct timezone *tz);
第一个参数tv指向一个timeval结构体
struct timeval{
time_t tv_sec; //seconds
suseconds_t tv_usec; //microsecondes
}
第二个参数timezone已过期,应设置为NULL。gettimeofday()函数用于返回当前时间(当前秒的秒和微秒)。settimeofday()函数用于设置当前时间。在Unix/Linux中,时间表示自1970年1月1日00:00:00起经过的秒数。它可以通过库函数ctime(&time)转换为日历形式。
2、time系统调用
time_t time (time_t *t)
以秒为单位返回当前时间。如果参数t不是NULL,还会将时间存储在t指向的内存中。
3、times系统调用
clock_t times(struct tms *buf);
可用于获取进程的具体执行时间。他将进程时间存储在struct tms buf中,即:
struct tms{
clock_t tms_utime; //user mode time
clock_t tms_stime; //system mode time
clock_t tms_cutime; //user time of children
clock_t tms_cstime; //system time of children
};
4、time和data命令
- date:打印或设置系统日期和时间
- time:报告进程在用户模式和系统模式下的执行时间和总时间
- hwclock:查询并设置硬件时钟(RTC),也可通过BIOS来完成
5.5间隔定时器
Linux为每个进程提供了三种不同类型的间隔计时器,可用作进程计时的虚拟时钟。间隔定时器由setitimer()系统调用创建。getitimer()系统调用返回间隔定时器的状态。
int getitimer(int which,struct itimerval *curr_value);
int setitimer(int which,const struct itimerval *new_value,struct itimerval *ld_value);
有三类间隔定时器
间隔定时器的值用以下结构体(在<sys/time.h>中)定义:
struct itimerval{
struct timeval it_interval; //interval for periodic timer
struct timeval it_value; //time until next expiration
}
struct timeval{
time_t tv_sec; //seconds
suseconds_t tv_usec; //microseconds
}
5.6 REAL模式间隔定时器
VIRTUAL和 PROF模式下的间隔计时器仅在执行进程时才有效。这类定时器的信息可保存在各进程的PROC结构体中。(硬件)定时器中断处理程序只需要访问当前运行进程的PROC结构体,就可以减少定时器计时,在定时结束时重新加载定时器计时,并向进程生成一个信号。操作系统内核不必使用额外的数据结构来处理进程的VIRTUAL和 PROF定时器。但是,REAL模式间隔定时器各不相同,因为无论进程是否正在执行,它们都必须由定时器中断处理程序来更新。因此,操作系统内核必须使用额外的数据结构来处理进程的REAL模式定时器,并在定时器到期或被取消时采取措施。
实践与代码
例:5.1gettimeofdat系统调用
源代码
运行结果
例5.3 time系统调用
源代码
运行结果
问题及解决办法
在运行例5.1时,出现段错误的情况
解决办法:通过gcc发现系统对于代码中的ctime发出警告,并提示修改判断是系统不识别ctime这个函数,通过
man ctime
发现ctime的头文件为<time.h>,在源代码中加入引用最终解决。