20191330雷清逸 学习笔记8
作者:互联网
20191330 雷清逸 学习笔记8(第五章)
一、知识点归纳以及自己最有收获的内容
知识点归纳
摘要
本章讨论了定时器和定时器服务;介绍了硬件定时器的原理和基于Intel x86的 PC 中的硬件定时器;讲解了 CPU操作和中断处理;描述了Linux中与定时器相关的系统调用、库函数和定时器服务命令;探讨了进程间隔定时器、定时器生成的信号,并通过示例演示了进程间隔定时器。编程项目的目的是要在一个多任务处理系统中实现定时器、定时器中断和间隔定时器。多任务处理系统作为—个Linux进程运行,该系统是 Linux进程内并发任务的一个虚拟 CPU。Linux 进程的实时模式间隔定时器被设计为定期生成SIGALRM信号,充当虚拟CPU的定时器中断,虚拟CPU使用SIGALRM信号捕捉器作为定时器的中断处理程序。该项目可让读进程通过定时器队列实现任务间隔定时器,还可让读进程使用Linux 信号掩码来实现临界区,以防止各项任务和中断处理程序之间出现竞态条件。
最有收获的部分
- 有关硬件定时器的相关知识
- 有关个人计算机定时器的相关知识
- 有关CPU操作的知识
- 有关中断处理的知识
- 有关时钟服务函数的知识
- 有关间隔定时器的知识
硬件定时器
- 定时器是由时钟源和可编程计数器组成的硬件设备。时钟源通常是一个晶体振荡器,会产生周期性电信号,以精确的频率驱动计数器。
- 计数器周期称为定时器刻度,是系统的基本计时单元。
个人计算机定时器
-
1.实时时钟(RTC):
(1)RTC由一个小型备用电池供电。即使在个人计算机关机时,它也能继续运行。它用于实时提供时间和日期信息。
(2)在所有类Unix系统中,时间变量是一个长整数,包含从1970年7月1日起经过的秒数。
-
2.可编程间隔定时器(PIT)(Wang2015):
(1)PIT是与CPU分离的一个硬件定时器。
(2)可对它进行编程,以提供以毫秒为单位的定时器刻度。
-
3.多核CPU中的本地定时器(Intel 1997;Wang 2015):
(1)在多核CPU中,每个核都是一个独立的处理器,它有自己的本地定时器,由CPU时钟驱动。
4.高分辨率定时器:
(1)大多数电脑都有一个时间戳定时器(TSC),由系统时钟驱动。
CPU操作
-
每个CPU都有一个程序计数器(PC),也称为指令指针(IP),以及一个标志或状态寄存器(SR)、一个堆栈指针(SP)和几个通用寄存器,当PC指向内存中要执行的下一条指令时,SR包含CPU的当前状态,如操作模式、中断掩码和条件码,SP指向当前堆栈栈顶。
-
在以上各步骤中,由于无效地址、非法指令、越权等原因,可能会出现一个错误状态,称为异常或陷阱。
-
中断是I/O设备或协处理器发送给CPU的外部信号,请求CPU服务。
-
中断处理和异常处理都在操作系统内核中进行。在大多数情况下,用户级程序无权访问它们,但它们是理解操作系统(如Linux)定时器服务和信号的关键。
中断处理
- 外部设备(如定时器)的中断被馈送到中断控制器的预定义输入行(Intel 1990;Wang 2015),按优先级对中断输入排序,并将具有最高优先级的中断作为中断请求(IRQ)路由到CPU。
- 对于每个中断,可以编程中断控制器以生成一个唯一编号,叫做中断向量,标识中断源。在获取中断向量号后,CPU用它作为内存中中断向量表(AMD64 2011)中的条目索引,条目包含一个指向中断处理程序入口地址的指针来实际处理中断。
时钟服务函数
时钟服务可通过系统调用、库函数和用户级命令调用。
以下是Linux的一些基本时钟服务函数:
-
gettimeofday-settimeofday
#include <sys/time.h>
int gettimeofday(struct timeval *tv,struct timezone *tz);
int settimeofday(const struct timeval *tv,const struct timezone *tz);
这是对Linux内核的系统调用;settimeofday()函数用于设置当前时间;它可以通过库函数ctime(&time)转化为日历形式。
-
time系统调用
time_t time(time_t *t)
该函数会以秒为单位返回当前时间
time系统调用具有一定的局限性,只提供以秒为单位的分辨率,而不是以微秒为单位。
-
times系统调用
clock_t times(struct tms *buf)
该函数可用于获取某进程的具体执行时间。它将进程时间存储在struct tms buf中
-
time和date命令
- date:打印或设置系统日期和时间。
- time:报告进程在用户模式下和系统模式下的执行时间和总时间。
- hwclock:查询并设置硬件时钟(RTC),也可以通过BIOS来完成。
间隔定时器
Linux为每个进程提供了三种不同类型的间隔计时器。
间隔计时器由setitimer()系统调用创建。getitimer()系统调用返回间隔定时器的状态。
-
分类:
(1)ITIMER_REAL:实时减少,在到期时生成一个SIGALRM(14)信号。
(2)ITIMER_VIRTUAL:仅当进程在用户模式下执行时减少,在到期时生成一个SIGVTALRM(26)信号。
(3)ITIMER_PROF:当进程正在用户模式和系统(内核)模式下执行时减少。
函数getitimer()用当前值填充curr_value指向的结构体,即参数which(ITIMER_REAL、ITIMER_VIRTUAL或ITIMER_PROF三者之一)指定的定时器在下次到期之前剩余的时间。
REAL模式间隔定时器
- VIRTUAL和PROF模式下的间隔计时器仅在执行进程时才有效。这类定时器的信息可保存在各进程的PROC结构体中。
- 在大多数操作系统内核中,使用的数据结构都是定时器队列。
二、问题与解决思路
问题:Linux下的定时器有sleep,usleep,nanosleep等等,它们有什么区别呢?
答:经过对相关资料的查阅,发现它们的区别如下:
sleep()和nanosleep()都是使进程睡眠一段时间后被唤醒,但是二者的实现完全不同。
Linux中并没有提供系统调用sleep(),sleep()是在库函数中实现的,它是通过调用alarm()来设定报警时间,调用sigsuspend()将进程挂起在信号SIGALARM上,sleep()只能精确到秒级上。
nanosleep()则是Linux中的系统调用,它是使用定时器来实现的,该调用使调用进程睡眠,并往定时器队列上加入一个timer_list型定时器,time_list结构里包括唤醒时间以及唤醒后执行的函数,通过nanosleep()加入的定时器的执行函数仅仅完成唤醒当前进程的功能。系统通过一定的机制定时检查这些队列(比如通过系统调用陷入核心后,从核心返回用户态前,要检查当前进程的时间片是否已经耗尽,如果是则调用schedule()函数重新调度,该函数中就会检查定时器队列,另外慢中断返回前也会做此检查),如果定时时间已超过,则执行定时器指定的函数唤醒调用进程。当然,由于系统时间片可能丢失,所以nanosleep()精度也不是很高。
alarm()也是通过定时器实现的,但是其精度只精确到秒级,另外,它设置的定时器执行函数是在指定时间向当前进程发送SIGALRM信号。
三、实践内容与截图,代码链接
实践内容为书本P162-163页的示例5.1,示例5.2及示例5.3
- 示例5.1(gettimeofday系统调用)
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
struct timeval t;
int main()
{
gettimeofday(&t,NULL);
printf("sec: %ld usec=%ld\n", t.tv_sec,t.tv_usec);
printf((char *)ctime(&t.tv_sec));
}
实践截图如下:
- 示例5.2(settimeofday系统调用)
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <time.h>
struct timeval t;
int main()
{
int r;
t.tv_sec = 123456789;
t.tv_usec = 0;
r = settimeofday(&t,NULL);
if (!r){
printf("settimeofday() failed\n");
exit(1);
}
gettimeofday(&t,NULL);
printf("sec=%ld usec=%ld\n",t.tv_sec,t.tv_usec);
printf("%s",ctime(&t.tv_sec));
}
实践截图如下:
- 示例5.3(time系统调用)
#include <stdio.h>
#include <time.h>
time_t start,end;
int main()
{
int i;
start = time(NULL);
printf("start=%ld\n",start);
for(i=0;i<123456789;i++)
end = time(NULL);
printf("end =%ld time=%ld\n",end,end-start);
}
实践截图如下:
标签:调用,中断,笔记,20191330,定时器,清逸,Linux,进程,CPU 来源: https://www.cnblogs.com/leo-skr/p/15505637.html