中断机制(5.3和5.4)

一、视频学习

5.3 中断下半部处理机制

中断服务程序一般都是在中断请求关闭的条件下执行的,以避免嵌套而使中断控制复杂化

在这里插入图片描述

内核把中断分为两部分:

一个叫上半部是不可中断的,也就是中断服务程序,内核立即执行

一个叫下半部是可中断的,也就是一些内核函数,留着稍后处理

下半部机制以软中断机制为例:

在这里插入图片描述

在这里插入图片描述

workqueue是工作队列机制

在这里插入图片描述

每个软中断在内核中都是以softirq_action表示的

扫描二维码关注公众号,回复: 17351909 查看本文章

在这里插入图片描述

小任务机制是I/O驱动程序中实现可延迟函数地首选方法,小任务和工作队列都是延迟执行工作的一种机制,其实现是基于软中断,但他们更易于使用,因而更适合于设备驱动程序

所谓小任务就是执行一些迷你型的任务

在这里插入图片描述

func域就是下半部中要推迟执行的函数,data是传递给这个函数的唯一参数

在这里插入图片描述

为什么soft_irq和tasklet机制都是在中断上下文执行?

​ 因为它们都是不可挂起的,而且由于是串行执行,因此只要有一个处理时间较长的话,则会导致其他中断响应的延迟

为了完成这些不可能完成的任务,于是出现了工作队列机制

在这里插入图片描述

多个中断可以放在一个线程中,也可以每个中断分配一个线程

工作队列对线程作了封装,使用起来更方便,因为工作队列是线程,所以我们可以使用可以在线程中使用的方法

在这里插入图片描述

在这里插入图片描述

该结构主要维护了一个任务队列以及内核线程需要睡眠的等待队列,另外还维护了一个任务上下文

在这里插入图片描述

工作队列运行机制:

​ 当用户调用工作队列初始化函数对工作队列进行初始化后,内核就开始为用户分配一个工作队列对象,并且将它挂到一个全局的workqueue队列中,然后内核根据当前CPU的情况,为workqueue对象分配与CPU个数相同的cpu_workqueue_struct对象,每一个cpu_workqueue_struct对象都会有一条任务队列,紧接着内核为cpu_workqueue_struct对象分配一个内核线程,也就是内核daemon(守护进程)去处理每个队列中的任务,至此,用户调用初始化接口将工作队列初始化完毕,返回workqueue的指针,workqueue初始化完毕以后,将任务运行的上下文环境就构建起来了,但是具体还没有可执行的任务,所以需要定义具体的work_struct对象,然后将work_struct加入到任务队列中,内核会唤醒内核线程daemon去处理该任务

在这里插入图片描述

何时使用哪种软中断处理机制?

​ 软中断的使用原则很简单,最好不用,它甚至都不算一种真正的中断处理机制,只是tasklet的实现基础。

​ 工作队列也要少用,如果不是必须要用到线程的某些机制,就不要使用工作队列

​ 除了上述情况外,一般都是使用小任务tasklet机制

5.4 时钟中断机制

系统利用时钟中断维持系统时间,促使进程的切换,以保证所有进程共享CPU

在这里插入图片描述

在这里插入图片描述

实时时钟 RTC:用于长时间存放系统时间的设备,即使关机后也可依靠主板的CMOS来维持系统的计时

可编程间隔器 PIT:可以周期性的发送一个时间中断信号,在linux系统中,该中断时间间隔由HZ表示,这个时间间隔也被称为一个节拍(tick)

时间戳计数器 TSC:当时钟信号到来的时候,该寄存器内容自动加1

高精度计时器 HPET:这是一种由intel开发的新型定时器芯片,该设备有一组计时器,每个计时器对应有自己的时钟信号,时钟信号到来的时候就会自动加1

CPU本地定时器:在处理器的本地APIC(Advanced Programmable Interrupt Controller高级可编程中断控制器)中提供的一个定时设备,可以单次或者周期性的产生中断信号

高精度定时器 hrtimer:目前最常用的,它提供纳秒级的定时精度,以满足对精确时间有迫切需求的应用程序或者内核驱动

在这里插入图片描述

BIOS是英文"Basic Input Output System"的缩略语,直译过来后中文名称就是"基本输入输出系统"。它的全称应该是ROM-BIOS,意思是只读存储器基本输入输出系统。

RTC是OS时钟的时间基准,操作系统通过读取RTC来初始化OS时钟,在此之后,二者就保持同步运行,共同维护着系统时间

同步,例:操作系统在运行过程中,每隔一个固定时间会刷新或者校正RTC中的信息

OS时钟和RTC时钟之间要通过BIOS连接,因为传统PC机的BIOS中固化有对RTC进行有关操作的函数,通常操作系统也直接利用这些函数对RTC进行操作

Linux在内核初始化完成后就完全抛弃了BIOS中的程序

RTC处于最底层,提供最原始的时钟数据,而OS时钟建立在RTC之上,初始化完成后将完全由操作系统控制,操作系统通过OS时钟提供给应用程序所有和时间有关的服务,因为OS时钟完全是一个软件问题,其所能表达的时间由操作系统的设计者决定

在这里插入图片描述

Linux的时间基准是1970年1月1日凌晨0点

OS时钟记录的时间就是系统时间,系统时间以“时钟节拍”为单位

在这里插入图片描述

clocksource:从硬件层来说,它其实就是固定时钟频率驱动的计数器

clock_event_device:主要用于实现普通定时器和高精度定时器,同时也用于产生节拍tick事件,供给进程调度子系统使用

在软件架构上来看,时钟事件设备被分为了两层:

  1. 与硬件相关的被放在了machine层
  2. 与硬件无关的通用代码则被集中到了通用事件框架层

tick_device:它是基于时钟事件设备的进一步封装,用于代替原有的时钟滴答中断,给内核提供节拍事件,以完成进程的调度、进程信息统计、负载平衡和时间更新等操作

在这里插入图片描述

hrtimer_cpu_base结构管理着3种不同的时间基准系统的hrtimer:实时时间、启动时间、单调时间

CLOCK_MONTONIC,是单调时间,即从某个时间点开始到现在所过去的时间。用户不能修改这个时间,但是当系统进入休眠(suspend)时,CLOCK_MONOTONIC是不会增加的。(更改系统时间对它没有影响)

在这里插入图片描述

在这里插入图片描述

内核在时钟中断发生以后就执行定时器了

在这里插入图片描述

二、问答

1.为什么把中断分为两部分来处理?

​ 因为中断是一个随机事件,它随时会到来,如果关中断的时间太长,CPU就不能及时响应其他的中断请求,从而造成中断的丢失,因此内核的目标就是尽可能快地处理完中断请求,尽其所能把更多地处理向后推迟。

2.为什么要有好几种中断下部分处理机制?

​ 因为针对不同的情况需要与之相匹配的处理机制,以达到性能的最优化

​ soft_irq机制和小任务tasklet机制都是不可挂起的,而且由于是串行执行,因此只要有一个处理时间较长的话,则会导致其他中断响应的延迟,为了完成这些不可能完成的任务,于是出现了工作队列机制

​ 如果不是必须要用到线程的某些机制,就不要使用工作队列,一般都是使用小任务tasklet机制

3.系统有了低精度定时器,为什么还要有高精度定时器?

​ 为了适应不同的应用场景,Linux内核提供了两种定时器:低精度和高精度定时器。低精度定时器基于硬件的周期性中断实现,其定时周期的粒度为1/HZms,例如,内核HZ为1000,那么低精度的定时器最小定时时间为1ms;高精度定时器可以实现ns级的定时,不过,实际的定时周期粒度与CPU的主频有关,比如,桌面级的CPU一般都是GHZ级别,那么,其定时粒度可以达到ns级别,而对于嵌入式CPU,其主频一般在百兆级别,那么定时粒度就只能达到us级别了。在进行开发时,需要根据实际场景,选择合适的定时器来实现功能。

4.小任务机制和工作队列机制的区别

区别 小任务机制 工作队列机制
执行 下半部分在中断上下文种执行 下半部分在进程上下文中执行
睡眠 小任务不能睡眠 工作队列允许被重新调度、睡眠

5.什么情况下使用工作队列?什么情况下使用小任务?

在这里插入图片描述

6.Tasklet机制是什么?

Tasklet机制(小任务机制)是指对要推迟执行的函数进行组织的一种机制,也就是说,推迟处理的事情是由相关处理函数实现,何时执行,由小任务机制封装后交给内核去处理。

小任务的数据结构为tasklet_struct,每个结构代表一个独立的小任务,其定义如下:

struct tasklet_struct
{
	struct tasklet_struct *next;	//指向链表中的下一个结构
	unsigned long state;			//小任务的状态
	atomic_t count;					//引用的计数器
	void (*func)(unsigned long);	//要调用的函数
	unsigned long data;				//传递给函数的参数
};

猜你喜欢

转载自blog.csdn.net/qq_58538265/article/details/133916040