第五章 定时器及时钟服务
5.1 硬件定时器
- 定时器是硬件设备,包括时钟源和可编程计数器。
- 时钟源通常是一个晶体振荡器,会产生周期性电信号,以精确的频率驱动计数器。使用一个倒计时值对计数器进行编程,每个时钟信号减1。当计数减为0时,计数器向CPU生成一个定时器中断,将计数值重新加载到计数器中,并重复倒计时。
- 计数器周期称为定时器刻度,是系统的基本计时单元。
5.2 个人计算机定时器
- 实时时钟(RTC):RTC由一个小型备用电池供电。即使在个人计算机关机时,它也能连续运行。它用于实时提供时间和日期信息。当Linux启动时,它使用RTC更新系统时间变量,以与当前时间保持一致。在所有类Unix系统中,时间变量是一个长整数,包含 从1970年1月1日起经过的秒数。
- 可编程间隔定时器(PIT):PIT是与CPU分离的一个硬件定时器。可对它进行编程,以提供以毫秒为单位的定时器刻度。在所有I/O设备中,PIT可以最高优先级IRQ0中断。PIT定时器中断由Linux内核的定时器中断处理程序来处理,为系统操作提供基本的定时单元,例如进程调度、进程间隔定时器和其他许多定时事件。
- 多核CPU中的本地定时器:在多核CPU中,每个核都是一个独立的处理器,它有自己的本地定时器,由CPU时钟驱动。
- 高分辨率定时器:大多数电脑都有一个时间戳定时器(TSC),由系统时钟驱动。它的内容可通过64位TSC寄存器读取。由于不同系统主板的时钟频率可能不同,TSC不适合作为实时设备,但它提供纳秒级的定时器分辨率。一些高端个人计算机可能还配备有专用高速定时器,以提供纳秒级定时器分辨率。
5.3 CPU操作
- 每个CPU都有一个程序计数器(PC),也称为指令指针(IP),以及一个标志或状态寄存器(SR)、一个堆栈指针(SP)和几个通用寄存器。
- 当PC指向内存中要执行的下一条指令时,SR包含CPU的当前状态,如操作模式、中断掩码和条件码,SP指向当前堆栈栈顶。
- CPU操作可通过无限循环进行建模。
- 当CPU遇到异常时,它会根据内存中预先安装的指针来执行软件中的异常处理程序。
- 在每条指令执行结束时,CPU会检查挂起的中断。
- 中断是I/O设备或协处理器发送给CPU的外部信号,请求CPU服务。
- 如果状态寄存器屏蔽了中断,CPU会忽略中断请求,否则,它将直接执行中断处理。
- 中断处理和异常处理都在操作系统内核中进行
5.4 中断处理
- 中断是为了解决外部设备完成某些工作后通知CPU的一种机制(譬如硬盘完成读写操作后通过中断告知CPU已经完成)。早期没有中断机制的计算机就不得不通过轮询来查询外部设备的状态,由于轮询是试探查询的(也就是说设备不一定是就绪状态),所以往往要做很多无用的查询,从而导致效率非常低下。由于中断是由外部设备主动通知CPU的,所以不需要CPU进行轮询去查询,效率大大提升。
- 从物理学的角度看,中断是一种电信号,由硬件设备产生,并直接送入中断控制器(如 8259A)的输入引脚上,然后再由中断控制器向处理器发送相应的信号。处理器一经检测到该信号,便中断自己当前正在处理的工作,转而去处理中断。此后,处理器会通知 OS 已经产生中断。这样,OS 就可以对这个中断进行适当的处理。不同的设备对应的中断不同,而每个中断都通过一个唯一的数字标识,这些值通常被称为中断请求线。
- 外部设备(如定时器)的中断被反馈送到中断控制器的预定义输入行,按优先级对中断输入排序,并将具有最高优先级的中断作为中断请求路由器到CPU。如果状态寄存器屏蔽了中断,CPU会忽略中断请求,使其处于挂起状态,否则,它将直接执行中断处理。对于每个中断,可以编程中断控制器以生成一个唯一编号,叫作中断向量,标识中断源。获取中断向量号后,CPU用它作为内存中中断向量表中的条目索引,条目包含一个指向中断处理程序入口地址的指针来实际处理中断。
- 详细知识点请查看此链接:https://blog.csdn.net/m0_50662680/article/details/128474337
5.5 时钟服务函数
- 操作系统内核会提供与时钟相关的各种服务。
- 时钟服务可通过系统调用、库函数和用户级命令调用。
5.5.1 gettimeofday-settimeofday
#include <sys/time.h> int gettimeofday (struct timeval *tv, struct timezone *tz); int settimeofday (const struct timeval *tv, const struct timezone *tz);
其中,参数tv指向一个timeval结构体。
struct timeval { time_t tv_sec; /* seconds (秒)*/ suseconds_t tv_usec; /* microseconds(微秒) */ };
1.gettimeofday系统调用
1 #include <stdio.h> 2 #include <string.h> 3 #include <sys/time.h> 4 int main() 5 { 6 struct timeval tv; 7 gettimeofday(&tv, NULL); 8 printf("tv_sec: %d\n", tv.tv_sec); 9 printf("tv_usec: %d\n", tv.tv_usec); 10 return 0; 11 }
出现段错误,无法显示时间
2.settimeofday系统调用
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<sys/time.h> 4 #include<time.h> 5 struct timeval t; 6 int main() 7 { 8 int r; 9 t.tv_sec=123456789; 10 t.tv_usec=0; 11 r=settimeofday(&t,NULL); 12 if(!r) 13 { 14 printf("settimeofday() failed\n"); 15 exit(1); 16 } 17 gettimeofday(&t,NULL); 18 printf("sec=%ld usec=%ld\n",t.tv_sec,t.tv_usec); 19 }
5.5.2 time系统调用
time_t time(time_t *t)以秒为单位返回当前时间
运行结果如下:
5.5.3 times系统调用
clock_t times(struct tms *buf); //可用于获取某进程的具体执行时间。它将进程时间存储在struct tms buf中。 struct tms{ clock_t tms_utime; //用户模式时间 clock_t tms_stime; //系统模式时间 clock_t tms_cutime;//孩子的用户时间 clock_t tms_cstime;//孩子的系统时间 };
5.5.4 time和date命令
- date:打印或设置系统日期和时间。
- time:报告进程在用户模式和系统模式下的执行时间和总时间。
- hwclock:查询并设置硬件时钟(RTC),也可以通过BIOS来完成。
向ChatGpt请求苏格拉底式询问
标签:定时器,struct,中断,tv,第五章,Linux,CPU,时钟 From: https://www.cnblogs.com/20211115fyq/p/17805502.html