Linux内核设计与实现 第七章 中断和中断处理

处理器的速度快过外围硬件设备若干数量级。
既然硬件的反应这么慢,那么内核就应该在此期间处理其他事务,等到硬件真正完成了请求的操作之后,再回过头来对它进行处理。
轮询:内核定期对硬件设备的状态进行查询,然后做出相应的处理。
中断:硬件向内核发出信号,内核根据信号处理硬件设备

7.1中断

中断:
硬件设备生成中断的时候并不考虑与处理器的时钟同步,就是处理器不知道中断什么时候产生,因为这里中断是由硬件产生的。
从物理角度看,中断是一种电信号,由硬件设备生成,并直接送入中断控制器的输入引脚。
不同的设备对应的中断不同,每个中断都通过一个唯一的数字标志,即中断号。中断号与中断请求(IRQ)线相关联。
大部分体系结构都支持动态分配可用中断的特性。

异常(也叫软中断):
异常考虑与处理器的时钟同步,就是处理器知道异常什么时候产生,因为异常是由处理器产生的,即软件执行产生的。
许多处理器体系结构处理异常与处理中断的方法类似,因此内核对异常和中断的处理方法也类似。

7.2中断处理程序

在响应一个特定中断的时候,内核会执行一个函数,该函数叫中断处理函数。
中断处理函数执行在中断上下文中,该上下文中执行的代码不可阻塞。
中断可能随时发生,因此中断处理程序也就随时可能执行。所以必须保证中断处理程序能够快速执行,这样才能保证尽可能快地恢复中断代码的执行。

7.3上半部与下半部的对比

又想中断处理程序运行得快,又想中断处理程序完成的工作量多。
中断处理程序的上半部:接受到一个中断,它就立即开始执行,但只做有严格时限的工作。
中断处理程序的下半部:接受到一个中断,能够被允许稍后完成的工作会推迟到下半部。

例子:
硬件网卡收到来自网络的数据包发起中断,
中断上半部快速拷贝网络数据到系统内存,拷贝慢了网卡缓存会溢出,网卡无缓存导致后续传来的数据包只能被丢弃。
中断下半部处理和操作数据包。

7.4注册中断处理程序

中断处理程序是管理硬件的驱动程序的组成部分。每一设备都有相关的驱动程序,如果设备使用中断,那么相应的驱动程序就注册一个中断处理程序。

int request_irq(unsigned int irq,irq_handler_t handler,unsigned long flags, const char *name,void *dev)//注册一个中断处理程序
request_irq(中断号,指向中断处理程序的指针,中断类型标志,声明设备的ascii名称,传递回处理函数的cookie)

1)中断处理程序标志

IRQF_DISABLED:该标志置位时,内核处理本中断处理程序时,禁止所有其他中断。不置位时,内核处理本中断处理程序时,允许所有其他中断。
IRQF_SAMPLE_RANDOM:该标志置位时,本设备的中断间隔时间就会作为熵池。不置位时,本设备的中断间隔时间就会不作为熵池。
IRQF_SHARED:该标志置位时,一条中断线可以有多个中断处理程序。不置位时,一条中断线只可以有一个中断处理程序。
触发共享IRQ前,必须确保若干共享某中断线的硬件的驱动的卡只有一个是允许中断,其余硬件的驱动的卡禁用中断

2)一个中断例子

在这里插入图片描述

3)释放中断处理程序实例


//在共享IRQ上,free_irq()函数的调用方,必须确保在调用此函数之前,在其驱动的卡上禁用中断
void free_irq (unsigned int irq,void * dev)//删除中断处理程序,处理程序被移除。如果中断线不再被任何驱动程序使用,就将此中断线禁用。

7.5编写中断处理程序

1)static irqreturn_t intr_handler(int irq,void *dev)

中断处理函数:static irqreturn_t intr_handler(int irq,void *dev)
irq:中断号
dev:通用指针,可以用来区分共享同一中断处理程序的多个设备,也可以指向中断处理程序使用的一个数据结构。通用指针dev由注册一个中断处理程序时指定。

中断处理函数的返回类型 irqreturn_t。
中断可能返回两个特殊的值:IRQ_NONE和IRQ_HANDLED。
IRQ_NONE:表明中断处理程序检测到的一个中断不是注册处理函数时指定的源。
IRQ_HANDLED:表明中断处理程序检测到的一个中断是注册处理函数时指定的源。

绝大数的中断处理程序至少需要知道产生中断的设备,告诉它内核已经收到它产生的中断了。
对于复杂一些的的设备,可能还需要在中断处理程序中发送和接收数据,以及执行一些扩充的工作。扩充的工作尽可能推给下半部处理程序。

Linux中的中断处理程序是无须重入的,当一个给定的中断处理程序正在执行时,相应的中断线在所有处理器上都会被屏蔽掉,以防止在同一中断线上接收另一个新的中断。

2)共享的中断处理程序

在这里插入图片描述

3)中断处理程序实例

略,详情看原书
在这里插入图片描述
在这里插入图片描述

7.6中断上下文

上下文:

角度一:
处理器总处于以下状态中的一种:
1、内核态,运行于进程上下文,内核代表进程运行于内核空间;
2、内核态,运行于中断上下文,内核代表硬件运行于内核空间;
3、用户态,运行于用户空间。
1)进程上下文:当一个进程在执行时,CPU的所有寄存器中的值、进程的状态以及堆栈中的内容被称为该进程的上下文。当内核需要切换到另一个进程时,它需要保存当前进程的所有状态,即保存当前进程的上下文,以便在再次执行该进程时,能够必得到切换时的状态执行下去。在LINUX中,当前进程上下文均保存在进程的任务数据结构中。例如执行系统调用或运行内核线程。
2)中断上下文:硬件通过触发信号,导致内核调用中断处理程序,进入内核空间。这个过程中,硬件的一些变量和参数也要传递给内核,内核通过这些参数进行中断处理。所谓的“中断上下文”,其实也可以看作就是硬件传递过来的这些参数和内核需要保存的一些其他环境(主要是当前被打断执行的进程环境)。

角度二:
1)进程上下文中:进程上下文是一种内核所处的操作模式,此时内核代表当前进程执行。所以进程上下文中是指内核代表当前进程执行中
2)中断上下文中:中断上下文是一种内核所处的操作模式,此时内核抢占当前进程执行。所以中断上下文中是指内核抢占当前进程执行中
进程上下文是内核代表当前进程执行,内核代替之前执行的进程执行,做的事还是之前进程要做的,睡眠以后一定有进程继续做同样的事,正常就会在将事情推进到某处时,唤醒。
中断上下文是内核抢占当前进程执行,内核抢占后做的事与之前执行的进程和它的伙伴进程做的事肯定不一样。所以如果内核抢占当前进程执行中睡了,是没进程唤醒的。
因此,不能从中断上下文中调用某些会引起睡眠的函数。

曾经中断处理程序的栈,共享所中断的进程的内核栈。Linux2.6中断处理程序有了自己的专属的栈,叫中断栈。

7.7中断处理机制的实现

在这里插入图片描述

硬件产生中断,处理器跳转到对应的一个固定唯一的位置,读取中断号保存于栈中,对当前进程保护现场,再调用函数do_IRQ()。
函数do_IRQ()对中断进行应答,就是应答硬件,接着禁止这条中断线的中断传递。再看看这条线有无有效的处理程序,并且这个程序已经取消禁止而没有执行。
最后do_IRQ()调用handle_IRQ_ecent()来运行这条中断线安装的中断处理程序。

7.8/proc/interrupts

在这里插入图片描述

7.9中断控制

一般来说,控制中断系统的原因归根结底是需要提供同步。通过禁止中断,可以确保某个中断处理程序不会抢占当前代码。
此外,禁止中断还可以禁止内核抢占。
再考虑支持多处理器,内核代码就需要使用锁,防止来自其他处理器的并发访问。即防止某处理器需要禁止某中断,另一处理器又需要允许某中断,形成矛盾。可能就是一个要置位禁止某中断的标志位,一个要复位该标志位。

1)禁止和激活中断

local_irq_disable()//屏蔽当前CPU上的所有中断
local_irq_enable()//打开本地处理器的所有中断
local_irq_save()//将把当前中断状态保存到flags中
local_irq_restore()//将local_irq_save保存的flags状态值恢复

2)禁止指定中断线

//在某些情况下需要只禁止整个系统中的一条特定的中断线。
//当然由于PCI设备已经必须支持中断线共享,就没有禁止不禁止一说了。
void disable_irq(unsigned int irq)//禁止中断控制器上指定的中断线,确保指定的中断线上没有处理程序运行,才能返回。
void disable_irq_nosync(unsigned int irq)//禁止中断控制器上指定的中断线,不确保指定的中断线上没有处理程序运行,就能返回。

void enable_irq(unsigned int irq)//激活中断控制器上指定的中断线。
void synchronize_irq(unsigned int irq)//等待一个特定的中断处理程序退出。

3)中断系统的状态

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值