linux内核中断机制

来源:
导读 大家好,我是本期栏目编辑小友,现在为大家讲解linux内核中断机制问题。 为什么需要打断? 如果要求内核定期轮询设备以便处理,会做很多

大家好,我是本期栏目编辑小友,现在为大家讲解linux内核中断机制问题。

为什么需要打断?

如果要求内核定期轮询设备以便处理,会做很多无用的工作,因为外设的处理速度一般比CPU慢,CPU不能一直等待外部事件。因此,让设备在需要的时候主动通知内核是一种聪明的方法,这就是中断。

中断处理器

为了响应特定的中断,内核将执行函数——中断处理程序。中断处理程序与其他内核函数的区别在于,中断处理程序由内核调用以响应中断,并且它们在一个称为中断上下文的特殊上下文中运行。

中断处理程序只是普通的C代码。特别的是,中断处理程序在中断上下文中运行,它的行为是有限的:

1)无法向用户空间发送或接收数据。

2)不要使用可能导致阻塞的功能。

3)不要使用可能导致排班的功能。

中断机制

Linux中断主要分为硬中断(IRQ)和软中断。

IRQ主要分为短IRQ和长IRQ。短类型的IRQ需要很短的时间,在此期间机器的其他部分被锁定,并且不能处理其他中断。长IRQ需要很长时间,在此期间可能会出现其他中断。

当用户程序被外部信号中断时,立即保存现场工作,包括保存返回地址、用户寄存器等数据,然后搜索中断向量表,找出相应的中断处理程序。系统中断分为三种类型:捕获、系统调用和外部中断。捕获:找到用户编写的处理程序,通过捕获处理程序的入口表执行。系统调用:软中断,通过系统调用表找到操作系统核心提供的服务例程。外部中断:直接调用内核提供的外部中断处理程序运行。

1.硬中断过程。

在Linux中,如果一个硬件想要向CPU发送中断信号,必须先获得一条可用的“中断请求线”(即中断前必须获得一个可用的IRQ号),生成一个中断信号,通过电信号发送给中断控制器(硬件芯片)。然后,CPU根据中断控制器的状态位确定中断的来源,获取中断号,根据中断号搜索中断向量表,从表中获取中断处理函数的地址,跳转到中断函数的入口地址。

2.中断处理程序-硬中断。

中断处理程序的主要任务:

A.保护一些不受硬件保护的必要寄存器。

B.识别每个中断源,并分析中断的原因。

C.处理中断事件。

D.恢复正常工作。

Linux规定中断处理程序是不可重入的,这意味着同一条中断线上不能出现新的中断,因为所有处理器都屏蔽了原始中断所在的中断线路。

Linux还规定同一个中断程序不能并行,所以不能同时调用同一个中断处理程序来处理嵌套中断。

在Linux中,中断处理程序分为上下两部分。

上半部分主要用于处理有严格时间限制的任务。上半部分可以看作是一个“注册中断”的函数,它将中断例程的下半部分挂在下半部分的执行队列中。上半部分要求快速执行,主要是因为上半部分完全屏蔽了中断下的执行,即不能中断。

下部主要用来处理以后可以执行的任务。下部是可中断的。当其他中断发生时,下部可以中断,等待另一个中断的上部执行后再继续。

上下半机构

我们期望中断处理程序快速运行,并希望它完成大量工作。这两个目标是相互制约的。——的上下半机构怎么解决?

我们将中断处理减半。中断处理程序是上部——接受中断,他立即开始执行,但只在严格的时间限制内工作。允许稍后完成的工作将被推迟到下半部分,然后下半部分将由开放终端在合适的时间执行。上半部分简单快速,执行时禁止部分或全部中断。下半部分稍后执行,执行过程中可以响应所有中断。这种设计可以使系统处于中断屏蔽状态的时间尽可能短,从而提高系统的响应能力。上半部分只有中断处理机制,下半部分有软中断实现、小任务实现和工作队列实现。

让我们用网卡解释一下这两半。当网卡收到数据包时,它会通知内核并触发中断。所谓上半部分就是及时将数据包读入内存,防止数据包因延迟而丢失,这是一项刻不容缓的任务。读取内存后,这些数据的处理不再紧迫。此时,内核可以执行中断前运行的程序,而网络数据包的处理则交给下半部分。

分成上下两半的原则。

1)如果一个任务对时间非常敏感,将其放入中断处理程序中执行;

2)如果任务与硬件相关,将其放入中断处理程序中执行;

3)如果要保证一个任务不会被其他中断中断,就把它放在中断处理程序中执行;

4)对于所有其他任务,考虑将它们放在下半部分执行。

Linux中提供了三种机制来实现机制的下部。

(1)软中断。

软中断是一组静态定义的下半部分结构,32个软中断结构由数组组织。两个相同的软中断可以同时执行,并且必须在编译期间静态注册。

一般来说,软中断机制是为对时间要求最严格、最重要的系统的后半部分保留的。在Linux2.6中,只有两个子系统是通过软中断实现的:网络子系统和SCSI。

(2)小任务

小任务比软中断好。

机制方便且简单,而且它本身也是基于软中断实现,属于软中断,既可以静态的创建tasklet,也可以动态的创建tasklet。

  Linux中tasklet分为两类:HI_SOFTIRQ和TASKLET_IRQ,前者比后者的优先级要高,优先调用前者。在中断数组irq_desc[]中会分配两项给tasklet,即两种类型各占数组中一项。两者分别以一个链表来组织。

  (3)工作队列

  (work queue)工作队列与前两者最大的不同之处是它是唯一一个能在进程上下文中运行的下半部机制,意味着它能允许睡眠。

  工作队列的实质是将推后的工作交给一个内核线程来完成,核心思想即时创建一个内核线程,Linux中已经默认提供了一种命名为enents一类工作者线程来实现工作队列。

  Linux软中断和工作队列的作用是什么

  Linux中的软中断和工作队列是中断上下部机制中的下半部实现机制。

  1.软中断一般是“可延迟函数”的总称,它不能睡眠,不能阻塞,它处于中断上下文,不能进城切换,软中断不能被自己打断,只能被硬件中断打断(上半部),可以并发的运行在多个CPU上。所以软中断必须设计成可重入的函数,因此也需要自旋锁来保护其数据结构。

  2.工作队列中的函数处在进程上下文中,它可以睡眠,也能被阻塞,能够在不同的进程间切换,以完成不同的工作。

  可延迟函数和工作队列都不能访问用户的进程空间,可延时函数在执行时不可能有任何正在运行的进程,工作队列的函数有内核进程执行,他不能访问用户空间地址。中断的数据结构

  Linux内核中定义了一个数组irq_desc[]数组来管理中断。数组中的每一项对应一个中断源。数组中的每个成员都为irq_desc_t结构体,即数组中的每一项对应着中断向量表中的一项。

  中断的数据结构

  Linux内核中定义了一个数组irq_desc[]数组来管理中断。数组中的每一项对应一个中断源。数组中的每个成员都为irq_desc_t结构体,即数组中的每一项对应着中断向量表中的一项。

  (1)irq_desc_t结构体

  irq_desc_t结构体用来描述中断源。其中结构体中的handler指向hw_interrupt_type结构体的指针,acTIon变量指向由irqacTIon结构体组成的单向链表的头的指针。

  (2)irqacTIon结构体

  该结构体中指明内核接收到特定IRQ后该才去的动作。结构体中变量handler指向中断处理程序。

  (3)hw_interrupt_type结构体

  用来描述中断控制器,是一个抽象的中断控制器。

  

  中断上下文

  当一个中断处理程序正在执行时,内核处于中断上下文中。中断上下文是不可以睡眠的。与进程上下文是不同的,进程上下文即使睡眠了也可以重新调度将其唤醒,中断上下文不可以被重新调度。 中断处理程序没有自己的堆栈,它会共享被它中断的那个进程的堆栈,如果没有进程正在执行,则占用idle进程的堆栈(每个处理器都有自己的运行队列,队列中都有idle进程,当前运行队列都dequeue时则运行idle进程)

  Linux中断编程

  中断申请(申请IRQ)-----request_irq()

  释放IRQ------free_irq()

  使能和屏蔽IRQ

  disable_irq() disable_irq_nosync() enable_irq()

  底半部机制:Linux实现底半部机制主要方式有 tasklet 工作队列 软中断

标签:

版权声明:转载此文是出于传递更多信息之目的。若有来源标注错误或侵犯了您的合法权益,请作者持权属证明与本网联系,我们将及时更正、删除,谢谢您的支持与理解。