Linux的中断

参考 http://www.yesky.com/20010813/192117.shtml

结构化程序设计思想认为:程序 = 数据结构 + 算法。数据结构体现了整个系统的构架,所以数据结构通常都是代码分析的很好的着手点,对Linux内核分析尤其如此。

比如,把进程控制块结构分析清楚了,就对进程有了基本的把握;

再比如,把页目录结构和页表结构弄懂了,两级虚存映射和内存管理也就掌握得差不多了。

为了体现循序渐进的思想,在这我就以Linux对中断机制的处理来介绍这种方法。

首先,必须指出的是:在此处,中断指广义的中断概义,它指所有通过idt进行的控制转移的机制和处理;它覆盖以下几个常用的概义:中断、异常、可屏蔽中断、不可屏蔽中断、硬中断、软中断 … … …

I、硬件提供的中断机制和约定

一.中断向量寻址:

  硬件提供可供256个服务程序中断进入的入口,即中断向量;

中断向量在保护模式下的实现机制是中断描述符表idt,idt的位置由idtr确定,idtr是个48位的寄存器,高32位是idt的基址,低16位为idt的界限(通常为2k=256*8);

  idt中包含256个中断描述符,对应256个中断向量;每个中断描述符8位,其结构如图一

二.异常处理机制: 

  Intel公司保留0-31号中断向量用来处理异常事件:当产生一个异常时,处理机就会自动把控制转移到相应的处理程序的入口,异常的处理程序由操作系统提供,中断向量和异常事件对应如表一:

表一、中断向量和异常事件对应表

中断向量号 异常事件 Linux的处理程序
0 除法错误 Divide_error
1 调试异常 Debug
2 NMI中断 Nmi
3 单字节,int 3 Int3
4 溢出 Overflow
5 边界监测中断 Bounds
6 无效操作码 Invalid_op
7 设备不可用 Device_not_available
8 双重故障 Double_fault
9 协处理器段溢出 Coprocessor_segment_overrun
10 无效TSS Incalid_tss
11 缺段中断 Segment_not_present
12 堆栈异常 Stack_segment
13 一般保护异常 General_protection
14 页异常 Page_fault
15   Spurious_interrupt_bug
16 协处理器出错 Coprocessor_error
17 对齐检查中断 Alignment_check

II、Linux的中断处理

  硬件中断机制提供了256个入口,即idt中包含的256个中断描述符(对应256个中断向量)。

  而0-31号中断向量被intel公司保留用来处理异常事件,不能另作它用。对这0-31号中断向量,操作系统只需提供异常的处理程序,当产生一个异常时,处理机就会自动把控制转移到相应的处理程序的入口,运行相应的处理程序;而事实上,对于这32个处理异常的中断向量,此版本(2.2.5)的Linux只提供了0-17号中断向量的处理程序,其对应处理程序参见表一、中断向量和异常事件对应表;也就是说,17-31号中断向量是空着未用的。

  既然0-31号中断向量已被保留,那么,就是剩下32-255共224个中断向量可用。这224个中断向量又是怎么分配的呢?在此版本(2.2.5)的Linux中,除了0x80 (SYSCALL_VECTOR)用作系统调用总入口之外,其他都用在外部硬件中断源上,其中包括可编程中断控制器8259A的15个irq;事实上,当没有定义CONFIG_X86_IO_APIC时,其他223(除0x80外)个中断向量,只利用了从32号开始的15个,其它208个空着未用。

  这些中断服务程序入口的设置将在下面有详细说明。

一.相关数据结构

  1. 中断描述符表idt: 也就是中断向量表,相当如一个数组,保存着各中断服务例程的入口。(详细描述参见图一、中断描述符格式
  2. 与硬中断相关数据结构:

我的理解:handler指的是哪个处理器来处理这个;action是实际的处理例程。action会交给handler处理。不知道对不对。

http://www.yesky.com/20010813/192117_2.shtml

三. Bottom_half处理机制

  在此版本(2.2.5)的Linux中,中断处理程序从概念上被分为上半部分(top half)和下半部分(bottom half);在中断发生时上半部分的处理过程立即执行,但是下半部分(如果有的话)却推迟执行。内核把上半部分和下半部分作为独立的函数来处理,上半部分决定其相关的下半部分是否需要执行。必须立即执行的部分必须位于上半部分,而可以推迟的部分可能属于下半部分。

那么为什么这样划分成两个部分呢?

  • 一个原因是要把中断的总延迟时间最小化。Linux内核定义了两种类型的中断,快速的和慢速的,这两者之间的一个区别是慢速中断自身还可以被中断,而快速中断则不能。因此,当处理快速中断时,如果有其它中断到达;不管是快速中断还是慢速中断,它们都必须等待。为了尽可能快地处理这些其它的中断,内核就需要尽可能地将处理延迟到下半部分执行。
  • 另外一个原因是,当内核执行上半部分时,正在服务的这个特殊IRQ将会被可编程中断控制器禁止,于是,连接在同一个IRQ上的其它设备就只有等到该该中断处理被处理完毕后果才能发出IRQ请求。而采用Bottom_half机制后,不需要立即处理的部分就可以放在下半部分处理,从而,加快了处理机对外部设备的中断请求的响应速度。
  • 还有一个原因就是,处理程序的下半部分还可以包含一些并非每次中断都必须处理的操作;对这些操作,内核可以在一系列设备中断之后集中处理一次就可以了。即在这种情况下,每次都执行并非必要的操作完全是一种浪费,而采用Bottom_half机制后,可以稍稍延迟并在后来只执行一次就行了。

由此可见,没有必要每次中断都调用下半部分;只有bh_mask 和 bh_active的对应位的与为1时,才必须执行下半部分(do_botoom_half)。所以,如果在上半部分中(也可能在其他地方)决定必须执行对应的半部分,那么可以通过设置bh_active的对应位,来指明下半部分必须执行。当然,如果bh_active的对应位被置位,也不一定会马上执行下半部分,因为还必须具备另外两个条件:首先是bh_mask的相应位也必须被置位,另外,就是处理的时机,如果下半部分已经标记过需要执行了,现在又再次标记,那么内核就简单地保持这个标记;当情况允许的时候,内核就对它进行处理。

如果在内核有机会运行其下半部分之前给定的设备就已经发生了100次中断,那么内核的上半部分就运行100次,下半部分运行1次。

内核中的某些底半处理过程是和特定设备相关的,而其他一些则更一般一些。表二列出了内核中通用的底半处理过程。

表二、Linux 中通用的底半处理过程

TIMER_BH(定时器) 在每次系统的周期性定时器中断中,该底半处理过程被标记为活动状态,并用来驱动内核的定时器队列机制。
CONSOLE_BH(控制台) 该处理过程用来处理控制台消息。
TQUEUE_BH(TTY 消息队列) 该处理过程用来处理 tty 消息。
NET_BH(网络) 用于一般网络处理,作为网络层的一部分
IMMEDIATE_BH(立即) 这是一个一般性处理过程,许多设备驱动程序利用该过程对自己要在随后处理的任务进行排队。

四.中断处理全过程

  由前面的分析可知,对于0-31号中断向量,被保留用来处理异常事件;0x80中断向量用来作为系统调用的总入口点;而其他中断向量,则用来处理外部设备中断;这三者的处理过程都是不一样的。

    1. 异常的处理全过程

      对这0-31号中断向量,保留用来处理异常事件;操作系统提供相应的异常的处理程序,并在初始化时把处理程序的入口登记在对应的中断向量表项中。当产生一个异常时,处理机就会自动把控制转移到相应的处理程序的入口,运行相应的处理程序,进行相应的处理后,返回原中断处。当然,在前面已经提到,此版本(2.2.5)的Linux只提供了0-17号中断向量的处理程序。

    2. 中断的处理全过程

        对于0-31号和0x80之外的中断向量,主要用来处理外部设备中断;在系统完成初始化后,其中断处理过程如下:

        当外部设备需要处理机进行中断服务时,它就会通过中断控制器要求处理机进行中断服务。如果 CPU 这时可以处理中断,CPU将根据中断控制器提供的中断向量号和中断描述符表(IDT)中的登记的地址信息,自动跳转到相应的interrupt[i]地址;在进行一些简单的但必要的处理后,最后都会调用函数do_IRQ , do_IRQ函数调用 do_8259A_IRQ 而do_8259A_IRQ在进行必要的处理后,将调用已与此IRQ建立联系irqaction中的处理函数,以进行相应的中断处理。最后处理机将跳转到ret_from_intr进行必要处理后,整个中断处理结束返回。

时间: 2024-09-27 14:14:27

Linux的中断的相关文章

Linux kernel中断子系统之(五):驱动申请中断API

一.前言 本文主要的议题是作为一个普通的驱动工程师,在撰写自己负责的驱动的时候,如何向Linux Kernel中的中断子系统注册中断处理函数?为了理解注册中断的接口,必须了解一些中断线程化(threaded interrupt handler)的基础知识,这些在第二章描述.第三章主要描述了驱动申请 interrupt line接口API request_threaded_irq的规格.第四章是进入request_threaded_irq的实现细节,分析整个代码的执行过程. 二.和中断相关的lin

Linux 内核中断内幕

转自:http://www.ibm.com/developerworks/cn/linux/l-cn-linuxkernelint/index.html#resources Linux 内核中断内幕 本文对中断系统进行了全面的分析与探讨,主要包括中断控制器.中断分类.中断亲和力.中断线程化与 SMP 中的中断迁徙等.首先对中断工作原理进行了简要分析,接着详细探讨了中断亲和力的实现原理,最后对中断线程化与非线程化中断之间的实现机理进行了对比分析. 3 评论 苏 春艳, 在读研究生 杨 小华 ([e

Linux 内核中断内幕【转】

转自:http://www.ibm.com/developerworks/cn/linux/l-cn-linuxkernelint/ 本文对中断系统进行了全面的分析与探讨,主要包括中断控制器.中断分类.中断亲和力.中断线程化与 SMP 中的中断迁徙等.首先对中断工作原理进行了简要分析,接着详细探讨了中断亲和力的实现原理,最后对中断线程化与非线程化中断之间的实现机理进行了对比分析. 3 评论: 苏 春艳, 在读研究生 杨 小华 ([email protected]), 在读研究生 2007 年 5

Linux内核中断引入用户空间(异步通知机制)【转】

转自:http://blog.csdn.net/kingdragonfly120/article/details/10858647 版权声明:本文为博主原创文章,未经博主允许不得转载. 当Linux内核空间发生中断后怎么使用户空间的应用程序运行相应的函数呢,当芯片有数据到来时内核会产生一个中断,但是怎样通知应用程序来取数据,以前这个问题一直困扰我很长时间,后来发现linux中有异步通知机制,在用户程序中用signal注册一个响应SIGIO信号的回调函数,然后在驱动程序中向该进程发出SIGIO信号

Linux内核中断和异常分析(下)

这节,我们继续上,中(以前的日志有)篇目进行分析,结合一个真实的驱动案例来描述linux内核中驱动的中断机制,首先我们先了解一下linux内核中提供的中断接口. 这个接口我们需要包含一个头文件:#include <linux/interrupt.h> 在中断接口中,最重要的是以下的接口函数: 1.这个是请求中断函数 int request_irq(unsigned int irq, irq_handler_t handler, unsigned long irqflags, const cha

Linux下中断程序导致写文件失败的分析

案例: 一个普通linux C程序,执行期间会进行多次printf操作,利用bash脚本重定向功能,将stdout重定向到一个另一个文件中去.在运行途中用ctrl+C终止程序,发现定向文件始终为空,即写失败. 分析: 原本以为是bash重定向机制导致的问题,于是将重定向取消,改为使用fprintf,而非printf.即在C程序内部进行写文件.发现问题依旧.(排除fopen打开失败的因素) 仔细观察,发现问题集中在两个层面,一个是ctrl+c到底做了什么,二是写文件操作为什么失败. 首先,ctrl

linux kernel 中断子系统之(一)-- ARM GIC 硬件

一个系统中,中断是很重要的组成部分之一,有了中断,系统才可以不用一直轮询(polling)是否有事件发生,系统效率才得以提高,而且对中断的控制又通常分散在各个地方,不同的部分由不同功能的程序控制,做到了各司其职,配合无误,系统才能正常工作.一般系统中,中断控制分为三个地方:模块.中断控制器.处理器,模块通常有寄存器可以控制是否使能中断功能,中断触发条件等:中断控制器可以管理中断的优先级等,而处理所有中断的处理器则有寄存器设置是否响应中断. 1. 全景 作为 ARM 系统中通用中断控制器的是 GI

Linux的中断和系统调用 &amp; esp、eip等寄存器

http://www.linuxidc.com/Linux/2012-11/74486.htm 一共三篇 中断一般分为三类: 1.由计算机硬件异常或故障引起的中断,称为内部异常中断: 2.由程序中执行了引起中断的指令而造成的中断,称为软中断(这也是和我们将要说明的系统调用相关的中断): 3.由外部设备请求引起的中断,称为外部中断.简单来说,对中断的理解就是对一些特殊事情的处理. 当发生软件中断时,其他所有的中断都可能发生并被处理:但当发生磁盘中断时,就只有时钟中断和机器错误中断能被处理了. 用户

[linux内核]中断下半部分——tasklet

1,Tasklet的概念 tasklet是利用软中断实现的一种下半部机制,tasklet由两类软中断的代表,HI_SOFTIRQ和TASKLET_SOFTIRQ,这两个的区别是HI_SOFTIRQ类型的软中断先于TASKLET_SOFTIRQ类型的软中断先执行. tasklet由tasklet_struct结构表示,每个结构单独代表一个tasklet,在interrupt.h中定义. [cpp] view plaincopy 420 struct tasklet_struct 421 { 422