细说Linux内核中断架构
- 格式:pdf
- 大小:825.36 KB
- 文档页数:33
Linux 内核软中断(softirq)执行分析Author: sinisterEmail: sinister@Homepage:Date: 2007-01-11本文对 Linux 内核软中断的执行流程进行了分析,并尽可能的结合当前运行环境详细地写出我的理解,但这并不表明我的理解一定正确。
这本是论坛里的一篇帖子,发出来是为了抛砖引玉,如果您在阅读本文时发现了我的错误,还望得到您的指正。
今天无意中看了眼 2.6 内核的软中断实现,发现和以前我看到的大不相同(以前也是走马观花,不大仔细),可以说改动很大。
连 softirq 的调用点都不一样了,以前是三个调用点,今天搜索了一下源代码,发现在多出了ksoftirqd 后,softirq 在系统中的调用点仅是在 ISR 返回时和使用了local_bh_enable() 函数后被调用了。
网卡部分的显示调用,我觉得应该不算是系统中的调用点。
ksoftirqd 返回去调用 do_softirq() 函数应该也只能算是其中的一个分支,因为其本身从源头上来讲也还是在 ISR 返回时irq_exit() 调用的。
这样一来就和前些日子写的那份笔记(Windows/Linux /Solaris 软中断机制)里介绍的 Linux 内核部分的软中断有出处了,看来以后讨论 Linux kernel 代码一定要以内核版本为前题,要不非乱了不可。
得买本 Linux 方面的书了,每次上来直接看相关代码也不是回事,时间也不允许。
//// do_IRQ 函数执行完硬件 ISR 后退出时调用此函数。
//void irq_exit(void){account_system_vtime(current);trace_hardirq_exit();sub_preempt_count(IRQ_EXIT_OFFSET);//// 判断当前是否有硬件中断嵌套,并且是否有软中断在// pending 状态,注意:这里只有两个条件同时满足// 时,才有可能调用 do_softirq() 进入软中断。
linux操作系统的结构及详细说明linux的操作系统的结构你了解多少呢?下面由店铺为大家整理了linux操作系统的结构及详细说明的相关知识,希望对大家有帮助!linux操作系统的结构及详细说明:一、 linux内核内核是操作系统的核心,具有很多最基本功能,它负责管理系统的进程、内存、设备驱动程序、文件和网络系统,决定着系统的性能和稳定性。
Linux 内核由如下几部分组成:内存管理、进程管理、设备驱动程序、文件系统和网络管理等。
系统调用接口:SCI 层提供了某些机制执行从用户空间到内核的函数调用。
这个接口依赖于体系结构,甚至在相同的处理器家族内也是如此。
SCI 实际上是一个非常有用的函数调用多路复用和多路分解服务。
在 ./linux/kernel 中您可以找到 SCI 的实现,并在 ./linux/arch 中找到依赖于体系结构的部分。
1. 内存管理对任何一台计算机而言,其内存以及其它资源都是有限的。
为了让有限的物理内存满足应用程序对内存的大需求量,Linux 采用了称为“虚拟内存”的内存管理方式。
Linux 将内存划分为容易处理的“内存页”(对于大部分体系结构来说都是 4KB)。
Linux 包括了管理可用内存的方式,以及物理和虚拟映射所使用的硬件机制。
不过内存管理要管理的可不止 4KB 缓冲区。
Linux 提供了对 4KB 缓冲区的抽象,例如 slab 分配器。
这种内存管理模式使用 4KB 缓冲区为基数,然后从中分配结构,并跟踪内存页使用情况,比如哪些内存页是满的,哪些页面没有完全使用,哪些页面为空。
这样就允许该模式根据系统需要来动态调整内存使用。
为了支持多个用户使用内存,有时会出现可用内存被消耗光的情况。
由于这个原因,页面可以移出内存并放入磁盘中。
这个过程称为交换,因为页面会被从内存交换到硬盘上。
内存管理的源代码可以在 ./linux/mm 中找到。
2 .进程管理进程实际是某特定应用程序的一个运行实体。
Linux中断处理流程1. 中断处理流程 当中断发⽣时,Linux系统会跳转到asm_do_IRQ()函数(所有中断程序的总⼊⼝函数),并且把中断号irq传进来。
根据中断号,找到中断号对应的irq_desc结构(irq_desc结构为内核中中断的描述结构,内核中有⼀个irq_desc结构的数组irq_desc_ptrs[NR_IRQS]),然后调⽤irq_desc中的handle_irq函数,即中断⼊⼝函数。
我们编写中断的驱动,即填充并注册irq_desc结构。
2. 中断处理数据结构:irq_desc Linux内核将所有的中断统⼀编号,使⽤⼀个irq_desc[NR_IRQS]的结构体数组来描述这些中断:每个数组项对应着⼀个中断源(也可能是⼀组中断源),记录中断⼊⼝函数、中断标记,并提供了中断的底层硬件访问函数(中断清除、屏蔽、使能)。
另外通过这个结构体数组项中的action,能够找到⽤户注册的中断处理函数。
struct irq_desc {unsigned int irq;irq_flow_handler_t handle_irq;struct irq_chip *chip;struct msi_desc *msi_desc;void *handler_data;void *chip_data;struct irqaction *action; /* IRQ action list */unsigned int status; /* IRQ status */unsigned int depth; /* nested irq disables */unsigned int wake_depth; /* nested wake enables */unsigned int irq_count; /* For detecting broken IRQs */unsigned long last_unhandled; /* Aging timer for unhandled count */unsigned int irqs_unhandled;spinlock_t lock;const char *name;} ____cacheline_internodealigned_in_smp;(1)handle_irq:中断的⼊⼝函数(2)chip:包含这个中断的清除、屏蔽、使能等底层函数struct irq_chip {const char *name;unsigned int (*startup)(unsigned int irq);void (*shutdown)(unsigned int irq);void (*enable)(unsigned int irq);void (*disable)(unsigned int irq);void (*ack)(unsigned int irq);void (*mask)(unsigned int irq);void (*mask_ack)(unsigned int irq);void (*unmask)(unsigned int irq);void (*eoi)(unsigned int irq);void (*end)(unsigned int irq);void (*set_affinity)(unsigned int irq,const struct cpumask *dest);int (*retrigger)(unsigned int irq);int (*set_type)(unsigned int irq, unsigned int flow_type);int (*set_wake)(unsigned int irq, unsigned int on);/* Currently used only by UML, might disappear one day.*/#ifdef CONFIG_IRQ_RELEASE_METHODvoid (*release)(unsigned int irq, void *dev_id);#endif/** For compatibility, ->typename is copied into ->name.* Will disappear.*/const char *typename;};(3)action:记录⽤户注册的中断处理函数、中断标志等内容struct irqaction {irq_handler_t handler;unsigned long flags;cpumask_t mask;const char *name;void *dev_id;struct irqaction *next;int irq;struct proc_dir_entry *dir;};3. 中断处理流程总结(1)发⽣中断后,CPU执⾏异常向量vector_irq的代码;(2)在vector_irq⾥⾯,最终会调⽤中断处理C程序总⼊⼝函数asm_do_IRQ();(3)asm_do_IRQ()根据中断号调⽤irq_des[NR_IRQS]数组中的对应数组项中的handle_irq();(4)handle_irq()会使⽤chip的成员函数来设置硬件,例如清除中断,禁⽌中断,重新开启中断等;(5)handle_irq逐个调⽤⽤户在action链表中注册的处理函数。
x86 linux内核中断处理流程下载温馨提示:该文档是我店铺精心编制而成,希望大家下载以后,能够帮助大家解决实际的问题。
文档下载后可定制随意修改,请根据实际需要进行相应的调整和使用,谢谢!并且,本店铺为大家提供各种各样类型的实用资料,如教育随笔、日记赏析、句子摘抄、古诗大全、经典美文、话题作文、工作总结、词语解析、文案摘录、其他资料等等,如想了解不同资料格式和写法,敬请关注!Download tips: This document is carefully compiled by theeditor.I hope that after you download them,they can help yousolve practical problems. The document can be customized andmodified after downloading,please adjust and use it according toactual needs, thank you!In addition, our shop provides you with various types ofpractical materials,such as educational essays, diaryappreciation,sentence excerpts,ancient poems,classic articles,topic composition,work summary,word parsing,copy excerpts,other materials and so on,want to know different data formats andwriting methods,please pay attention!深入解析x86 Linux内核中断处理机制在计算机系统中,中断扮演着至关重要的角色,它使得硬件事件能够及时通知操作系统进行相应的处理。
linux中断处理流程Linux中断处理流程Linux中断处理是操作系统中的一个重要组成部分,用于响应硬件设备的事件。
在Linux中,中断可以是外部中断,如硬件设备发送的中断信号,也可以是内部中断,如软件产生的异常或系统调用。
中断处理的目的是及时响应硬件设备的事件,并采取相应的措施来处理这些事件。
一、中断的触发中断是由硬件设备发送的一个信号,用于通知操作系统某个事件的发生。
这个信号可以是一个电平的变化,一个特定的数据包,或者一个指定的硬件寄存器的变化。
当硬件设备检测到某个事件发生时,它会向处理器发送一个中断信号,处理器会立即停止当前正在执行的任务,保存当前的上下文,并跳转到中断处理程序的入口点。
二、中断处理程序的执行中断处理程序是一个特殊的函数,负责处理中断事件。
当中断发生时,处理器会跳转到中断处理程序的入口点,并执行相应的代码。
中断处理程序的执行过程可以分为以下几个步骤:1. 保存上下文:在执行中断处理程序之前,处理器需要保存当前任务的上下文,包括程序计数器、寄存器和堆栈指针等。
这样可以确保在中断处理程序执行完成后,能够正确地返回到原来的任务。
2. 中断处理程序的执行:一旦保存了上下文,处理器就会执行中断处理程序的代码。
中断处理程序根据中断的类型,执行相应的操作。
例如,对于外部中断,中断处理程序可能需要读取硬件设备的状态,处理数据包或执行特定的操作。
对于内部中断,中断处理程序可能需要处理异常或系统调用。
3. 中断处理程序的结束:当中断处理程序执行完成后,处理器会恢复之前保存的上下文,并将控制权返回给原来的任务。
这样原来的任务就可以继续执行,而不会受到中断的影响。
三、中断处理的优先级在Linux中,中断处理有不同的优先级。
这是为了确保对于紧急事件的及时处理。
中断的优先级由硬件设备决定,通常是通过一个优先级编码器来实现的。
当多个中断同时发生时,处理器会按照优先级的顺序来处理中断。
高优先级的中断会立即被处理,而低优先级的中断则会被推迟到稍后处理。
中断处理流程linux中断处理浅析最近在研究异步消息处理, 突然想起linux内核的中断处理, ⾥⾯由始⾄终都贯穿着"重要的事马上做, 不重要的事推后做"的异步处理思想. 于是整理⼀下~第⼀阶段--获取中断号每个CPU都有响应中断的能⼒, 每个CPU响应中断时都⾛相同的流程. 这个流程就是内核提供的中断服务程序.在进⼊中断服务程序时, CPU已经⾃动禁⽌了本CPU上的中断响应, 因为CPU不能假定中断服务程序是可重⼊的.中断处理程序的第⼀步要做两件事情:1. 将中断号压⼊栈中; (不同中断号的中断对应不同的中断服务程序⼊⼝)2. 将当前寄存器信息压⼊栈中; (以便中断退出时恢复)显然, 这两步都是不可重⼊的(如果在保存寄存器值时被中断了, 那么另外的操作很可能就把寄存器给改写了, 现场将⽆法恢复), 所以前⾯说到的CPU进⼊中断服务程序时要⾃动禁⽌中断.栈上的信息被作为函数参数, 调⽤do_IRQ函数.第⼆阶段--中断串⾏化进⼊do_IRQ函数, 第⼀步进⾏中断的串⾏化处理, 将多个CPU同时产⽣的某⼀中断进⾏串⾏化.其⽅法是如果当前中断处于"执⾏"状态(表明另⼀个CPU正在处理相同的中断), 则重新设置它的"触发"标记, 然后⽴即返回. 正在处理同⼀中断的那个CPU完成⼀次处理后, 会再次检查"触发"标记, 如果设置, 则再次触发处理过程.于是, 中断的处理是⼀个循环过程, 每次循环调⽤handle_IRQ_event来处理中断.第三阶段--关中断条件下的中断处理进⼊handle_IRQ_event函数, 调⽤对应的内核或内核模块通过request_irq函数注册的中断处理函数.注册的中断处理函数有个中断开关属性, ⼀般情况下, 中断处理函数总是在关中断的情况下进⾏的. ⽽调⽤request_irq注册中断处理函数时也可以设置该中断处理函数在开中断的情况下进⾏,这种情况⽐较少见, 因为这要求中断处理代码必须是可重⼊的. (另外, 这⾥如果开中断, 正在处理的这个中断⼀般也是会被阻塞的. 因为正在处理某个中断的时候, 硬件中断控制器上的这个中断并未被ack, 硬件不会发起下⼀次相同的中断.)中断处理函数的过程可能会很长, 如果整个过程都在关中断的情况下进⾏, 那么后续的中断将被阻塞很长的时间.于是, 有了soft_irq. 把不可重⼊的⼀部分在中断处理程序中(关中断)去完成, 然后调⽤raise_softirq 设置⼀个软中断, 中断处理程序结束. 后⾯的⼯作将放在soft_irq⾥⾯去做.第四阶段--开中断条件下的软中断上⼀阶段循环调⽤完当前所有被触发的中断处理函数后, do_softirq函数被调⽤, 开始处理软件中断.在软中断机制中, 为每个CPU维护了⼀个若⼲位的掩码集, 每位掩码代表⼀个中断号. 在上⼀阶段的中断处理函数中, 调⽤raise_softirq设置了对应的软中断, 到了这⾥, 软中断对应的处理函数就会被调⽤(处理函数由open_softirq函数来注册).可以看出, 软中断与中断的模型很类似, 每个CPU有⼀组中断号, 中断有其对应的优先级, 每个CPU处理属于⾃⼰的中断. 最⼤的不同是开中断与关中断.于是, ⼀个中断处理过程被分成了两部分, 第⼀部分在中断处理函数⾥⾯关中断的进⾏, 第⼆部分在软中断处理函数⾥⾯开中断的进⾏.由于这⼀步是在开中断条件下进⾏的,这⾥还可能发⽣新的中断(中断嵌套),然后新中断对应的中断处理⼜将开始⼀个新的第⼀阶段~第三阶段。
linux 软中断原理Linux软中断是操作系统中一种用于处理紧急任务的机制。
它采用的是一种特殊的中断方式,可以在用户态和内核态之间切换,以提供高效的中断处理能力。
在Linux内核中,软中断是一种特殊的中断处理机制。
相比硬中断,软中断的处理过程更加高效,可以在短时间内完成中断处理,并且不会占用过多的系统资源。
软中断的原理是通过将中断处理函数放入一个队列中,然后由内核线程负责依次执行队列中的中断处理函数。
在Linux内核中,每个软中断都有一个唯一的标识符,并且有一个对应的中断处理函数。
当某个软中断被触发时,中断处理函数会被调用。
这样,操作系统就可以根据不同的软中断来执行相应的中断处理操作。
软中断的使用可以提高系统的响应速度和处理能力。
在Linux内核中,有一些常用的软中断,如定时器中断、网络中断等。
这些软中断可以及时地处理系统中的紧急任务,并且不会对系统的正常运行产生太大的影响。
软中断的原理是基于内核线程的机制实现的。
在Linux内核中,有一个特殊的内核线程,称为软中断处理线程。
这个线程会不断地检查软中断队列,如果队列中有待处理的中断,就会调用相应的中断处理函数。
软中断的实现需要考虑到多核处理器的情况。
在多核处理器中,每个CPU核心都有自己的软中断处理队列和软中断处理线程。
这样,每个CPU核心都可以独立地处理软中断,提高系统的并发处理能力。
软中断的使用可以提高系统的可靠性和稳定性。
在Linux内核中,软中断可以用于处理系统中的紧急任务,如定时器中断、网络中断等。
这些紧急任务需要及时地处理,以保证系统的正常运行。
Linux软中断是一种高效的中断处理机制,可以提高系统的响应速度和处理能力。
它通过将中断处理函数放入一个队列中,然后由专门的内核线程负责执行,可以及时地处理系统中的紧急任务,并且不会对系统的正常运行产生太大的影响。
通过软中断的使用,可以提高系统的可靠性和稳定性,保证系统的正常运行。
软件中断机制的概念和实例一、前言软件中断机制在现代操作系统和编程语言中的使用十分普遍,是保证计算机正常工作的基础性机制之一。
本文主要介绍了软件中断机制的基本概念、实现方式和实例,希望能够对读者有所帮助。
二、概念软件中断是一种由计算机软件向处理器发送的输入信号,用于打断当前正在运行的程序,并切换到特定的代码段执行特定的指令处理器。
在实际应用中,软件中断通常用于响应一些外部事件或信号,如来自键盘、鼠标、网络等输入以及操作系统内部的系统调用等。
软件中断机制主要包括中断请求、中断响应和中断处理三个部分。
当一个设备产生了中断请求信号时,计算机中断控制器会通知处理器并将中断请求号发送给处理器。
处理器接收到中断请求后,会中止当前正在执行的程序,并将处理器状态保存到寄存器或堆栈中。
接下来,处理器会根据中断请求号查找中断向量表,并跳转到相应的中断处理程序中执行特定的指令,处理完中断后再恢复处理器状态,返回到原来的程序中继续执行。
三、实现方式在不同的编程语言、操作系统和硬件平台上,软件中断机制的实现方式会有所不同。
下面是一些常见的软件中断机制的实现方式。
1.软中断软中断是一种在操作系统内部使用的中断机制,可用于实现系统调用等功能。
在Linux内核中,软中断使用了一组与硬件中断类似的数据结构,包括中断处理函数、中断处理队列、向量表对应数组等。
当需要执行系统调用时,用户态程序会通过软中断接口发起请求,内核会将该请求加入到软中断队列中,随后中断处理程序会处理该请求,最终返回执行结果。
2.信号信号是一种轻量级的软件中断机制,可以用来发送各种事件通知、异常处理等。
在Unix和Linux系统中,用户可以通过kill、sigaction等系统调用发送和接收信号,操作系统会将信号加入到信号处理队列中,并由信号处理程序处理相应的事件。
对于一些信号,如SIGSEGV(段错误)、SIGINT(中断信号)等,操作系统会默认采取一些预先定义好的处理方式,如向进程发送杀死进程、终止进程、跳转到异常处理程序等。
细说Linux内核中断架构分类:网络Unix/Linux内核学习2012-06-14 17:59 38人阅读评论(0) 收藏举报中断和异常一、什么是中断?中断通常被定义为一个事件,该事件改变处理器执行的指令顺序。
这样的事件与CPU芯片内外部硬件电路产生的电信号相对应。
中断通常分为同步中断和异步中断:²同步中断是当指令执行时由CPU控制单元产生的,之所以称为同步,是因为只有在一条指令终止执行后CPU才会发出中断。
◎异步中断是由其他硬件设备依照CPU时钟信号随机产生的。
在Intel微处理器手册中:◎把同步中断称为异常(exception)◎把异步中断称为中断(interrupt)这两类中断的共同特点是什么?如果CPU当前不处于核心态,则发起从用户态到核心态的切换。
接下来,在内核中执行一个专门的例程,称为中断服务例程(interrupt service routine)。
或中断处理程序(interrupthandler)另一方面,异常是由程序的错误产生的,或者是由内核必须处理的异常条件产生的。
第一种情况下,内核通过发送一个每个Unix/Linux程序员都熟悉的信号来处理异常。
第二种情况下,内核执行恢复异常需要的所有步骤,例如缺页异常等。
二、中断信号的作用中断信号提供了一种特殊的方式,使处理器转而去运行正常控制流之外的代码。
当一个中断信号达到时,CPU必须停止它当前正在做的事情,并且切换到一个新的活动。
为了这做到这一点,就要在内核态堆栈保存程序计数器的当前值(即EIP和CS寄存器的内容),并把与中断类型相关的一个地址放进程序计数器。
这可能会让我们想起系统调度的进程切换,发生在内核用一个进程替换另一个进程时。
但是中断处理与进程切换有一个明显的差异:由中断或异常处理程序执行的代码不是一个进程。
更准确的说,它是一个内核控制路径,代表中断发生时正在运行的进程执行。
作为一个内核控制路径,中断处理程序比一个进程要“轻”(中断的上下文很少,建立或终止中断处理需要的时间也很少)中断处理是由内核执行的最敏感的任务之一,因为它必须满足下列约束:◎当内核正打算去完成一些别的事情时,中断随时会到来。
因此,内核的目标就是让中断尽可能快地处理完,尽其所能把更多的处理向后推迟。
因此,内核响应中断后需要进行的操作分为两部分:关键而紧急的部分,内核立即执行;其余推迟的部分,内核随后执行。
◎因为中断随时会到来,所以内核可能正在处理其中的一个中断时,另一个不同类型的中断又发生了。
内核应该尽可能地允许这种情况发生,因为这能维持更多的I/O设备得到处理的机会。
因此,中断处理程序必须编写成使相应的内核控制路径能以嵌套的方式执行。
当最后一个内核控制路径终止时,内核必须能恢复被中断进程的执行,或者,如果中断信号已导致了重新调度,内核也应能切换到另外的进程。
◎尽管内核在处理前一个中断时可以接受一个新的中断,但在内核代码中还是存在一些临界区,在临界区中,中断必须被禁止。
必须尽可能地限制这样的临界区,因为根据以前的要求,内核,尤其是中断处理程序,应该在大部分时间内以开中断的方式运行。
三、IRQ和中断中断这个名词使用得并不是很谨慎,为什么?由于中断是用来表示由CPU和外部硬件发出的信号所产生的。
但是中断不能由处理器外部的外设直接产生,而必须借助于一个称为可编程中断控制器(programmable interrupt controller)的标准组件来请求,该组件存在于每个系统中。
外部设备,会有电路连接到用于向中断控制器发送中断请求的组件。
控制器在执行了各种电工任务之后,将中断请求转发到CPU的中断输入中。
因为外部设备不能直接发出中断,而必须通过中断控制器的标准组件来请求中断,所以这种请求更正确的叫法是IRQ,或中断请求(Interrupt Request)。
每个能够发出中断请求的硬件设备控制器都有这么一条名为IRQ的输出线。
所有现有的IRQ 线都会与这个中断控制器(PIC)的硬件电路的输入引脚相连。
下面来看看这种中断控制器执行下列动作:1) 监视IRQ线,检查产生的信号。
如果有一条或两条以上的IRQ线上产生信号,就选择引脚编号较小的IRQ线。
2) 如果一个引发信号出现在IRQ线上:a) 把接收到的引发信号转换成对应的向量(索引)。
b) 把这个向量存放在中断控器的一个I/O端口,从而允许CPU通过数据总线读取此向量。
c) 把引发信号发送到处理器的INTR引脚,即产生一个中断。
d) 等待,直到CPU通过把这个中断信号写进可编程中断控制器的一个I/O端口来确认它;当这种情况发生时,清INTR线。
3) 返回到第一步。
IRQ线是从0开始顺序编号的,因此,第一条IRQ线通常表示成IRQ0。
与IRQn关联的Intel 缺省向量是n+32。
如前所述,通过向中断控制器端口发布合适的指令,就可以修改IRQ和向量之间的映射。
可以有选择地禁止每条IRQ线。
因此,可以对PIC编程从而禁止IRQ,也就是说,可以告诉PIC停止对给定的IRQ线发布中断,或者激活它们,禁止的中断是丢失不了的,它们一旦激活,PIC就又把它们发送到CPU。
这个特点被大多数中断处理程序使用,因为这允许中断处理程序逐次地处理同一类型的IRQ。
(一)处理中断在CPU得知发生中断后,它将进一步的处理委托给一个软件例程,该例程可能会修复故障、提供专门的处理或将外部事件通知用户进程。
由于每个中断和异常都有唯一的编号,内核使用一个数组项是指向处理程序函数的指针。
相关的中断号根据数组项在数组中位置判断。
如下图所示:1、进入和退出任务如下图,中断处理划分为3部分。
首先,必须建立一个适当的环境,使得处理程序函数能够在其中执行,接下来调用处理程序自身,最后将系统复原到中断之前的状态。
调用中断处理程序前后的两部分,分别称为进入路径和退出路径。
进入和退出任务还负责确保处理器从用户态切换到核心态。
进入路径的一个关键任务是,从用户态栈切换到核心态栈。
但是这一点还不够。
因为内核还要使用CPU资源执行其代码,进入路径必须保存用户应用程序当前的寄存器,以便在中断活动结束后恢复。
这与进程调度间用上下文切换的机制是相同的。
在进入核心态时,只保存整个寄存器集合的一部分。
内核并不使用全部寄存器。
(如内核代码中不使用浮点操作,因而不保存浮点寄存器)。
平台相关的数据结构pt_regs列出了核心态可能修改的所有寄存器,它的定义考虑到了不同的CPU之间的差别。
在退出路径中,内核会检查下列事项。
◎调度器是否应该选择一个新进程代替旧的进程。
◎是否有信号必须投递到原进程从中断返回之后,只有确认了这两个问题,内核才能完成其常规任务,即还原寄存器集合、切换到用户态栈、切换到适用于用户应用程序的适当的处理器状态,或切换到一个不同的保护环。
术语中断处理程序的使用可能引起岐义。
因为它是用于指代CPU对ISR(中断服务程序)的调用,包括了进入/退出路径和ISR本身。
当然,如果只指代在进入路径和退出路径之间进行由C语言实现的例程,将更为准确。
2、数据结构中断技术上的实现有两方面:1) 汇编语言代码:与处理器高度相关,用于处理特定平台上相关的底层细节;2) 抽象接口:是设备驱动程序及其他内核代码安装和管理IRQ处理程序所需的。
描述汇编语言部分的功能会涉及无数细节,可以参考处理器体系方面的手册。
为响应外部设备的IRQ,内核必须为每个潜在的IRQ提供一个函数。
该函数必须能够动态注册和注销。
静态表组织方式是不够的,因为可能为设备编写模块,而且设备可能与系统的其他部分通过中断进行交互。
IRQ相关信息管理的关键点是一个全局数组,每个数组项对应一个IRQ编号。
因为数组位置和中断号是相同的,很容易定位与特定的IRQ相关的数组项:IRQ0在位置0,IRQ15在位置15,等等,IRQ最终映射到哪个处理器中断,在这里不相关的。
尽管各个数组项使用的是一个体系结构无关的数据类型,但IRQ的最大可能数目是通过一个平台相关的常数NR_IRQS指定的,大多数体系结构一,该常数定义在处理器相关的头文件irq.h中。
不同处理器间及同一处理器家庭内,该常数的值变化都很大,主要取决于辅助CPU 管理IRQ的辅助芯片。
与IRQ的最大数目相比,我们对各数组项的数据类型更感兴趣。
在了解细节之前,需要概述内核的IRQ处理子系统。
之前的一些版本包含了大量平台代码来处理IRQ,在许多地方是相同的。
因而,在内核版本2.6开发期间,引入了一个新的通用的IRQ子系统。
它能够以统一的方式处理不同的中断控制器和不同类型的中断。
基本上它由3个抽象层组成。
如下图:◎高层ISR(high-level interrupt service routines):针对设备驱动程序端的中断,执行由此引起的所有必要的工作。
◎中断电流处理(interrupt flow handling):处理不同的中断电流类型之间的各种差别,如边沿触发和电平触发。
边沿触发:意味着硬件通过感知线路上的电位差来检测中断。
电平触发:根据特定的电势值检测中断,与电势是否改变无关。
◎芯片级硬件封装(chip-level hardware encapsulation):需要与电子学层次上产生中断的底层硬件直接通信。
该抽象可以视为中断控制器的某种“设备驱动程序”。
用于表示irq的结构如下:(摘自Linux kernel 3.5)[cpp]view plaincopyprint?1.<span style="font-size:16px;">/**2.*struct irq_desc - interrupt descriptor3.*@irq_data: per irq and chip datapassed down to chip functions4.*@timer_rand_state: pointer to timer randstate struct5.*@kstat_irqs: irq stats per cpu6.*@handle_irq: highlevel irq-eventshandler7.*@preflow_handler: handler called beforethe flow handler (currently used by sparc)8.*@action: the irq action chain9.*@status: status information10.*@core_internal_state__do_not_mess_with_it: core internal status information11.*@depth: disable-depth, for nestedirq_disable() calls12.*@wake_depth: enable depth, for multipleirq_set_irq_wake() callers13.*@irq_count: stats field to detectstalled irqs14.*@last_unhandled: aging timer forunhandled count15.*@irqs_unhandled: stats field forspurious unhandled interrupts16.*@lock: locking for SMP17.*@affinity_hint: hint to user space forpreferred irq affinity18.*@affinity_notify: context fornotification of affinity changes19.*@pending_mask: pending rebalancedinterrupts20.*@threads_oneshot: bitfield to handleshared oneshot threads21.*@threads_active: number of irqactionthreads currently running22.*@wait_for_threads: wait queue for sync_irqto wait for threaded handlers23.*@dir: /proc/irq/ procfs entry24.*@name: flow handler name for/proc/interrupts output25.*/26.struct irq_desc27.{28.struct irq_data irq_data;29.struct timer_rand_state *timer_rand_state;30.unsigned int __percpu *kstat_irqs;31.irq_flow_handler_t handle_irq;32.#ifdef CONFIG_IRQ_PREFLOW_FASTEOI33.irq_preflow_handler_t preflow_handler;34.#endif35.struct irqaction *action; /* IRQ action list*/36.unsigned int status_use_accessors;37.unsigned int core_internal_state__do_not_mess_with_it;38.unsigned int depth; /* nested irqdisables */39.unsigned int wake_depth; /* nested wake enables */40.unsigned int irq_count; /* For detectingbroken IRQs */41.unsigned long last_unhandled; /* Aging timer for unhandled count */42.unsigned int irqs_unhandled;43.raw_spinlock_t lock;44.struct cpumask *percpu_enabled;45.#ifdef CONFIG_SMP46.const struct cpumask *affinity_hint;47.struct irq_affinity_notify *affinity_notify;48.#ifdef CONFIG_GENERIC_PENDING_IRQ49.cpumask_var_t pending_mask;50.#endif51.#endif52.unsigned long threads_oneshot;53.atomic_t threads_active;54.wait_queue_head_t wait_for_threads;55.#ifdef CONFIG_PROC_FS56.struct proc_dir_entry *dir;57.#endif58.struct module *owner;59.const char *name;60.} ____cacheline_internodealigned_in_smp;</span>1.<span style="font-size:16px;">/**2.*struct irq_data - per irq and irq chip data passed down to chip functions3.*@irq: interrupt number4.*@hwirq: hardware interrupt number,local to the interrupt domain5.*@node: node index useful forbalancing6.*@state_use_accessors: status information for irq chip functions.7.* Use accessor functions to deal with it8.*@chip: low level interrupt hardwareaccess9.*@domain: Interrupt translationdomain; responsible for mapping10.* between hwirq number and linux irq number.11.*@handler_data: per-IRQ data for theirq_chip methods12.*@chip_data: platform-specificper-chip private data for the chip13.* methods, to allow shared chip implementations14.*@msi_desc: MSI descriptor15.*@affinity: IRQ affinity on SMP16.*17.*The fields here need to overlay the ones in irq_desc until we18.*cleaned up the direct references and switched everything over to19.*irq_data.20.*/21.struct irq_data22.{23.unsigned int irq;24.unsigned long hwirq;25.unsigned int node;26.unsigned int state_use_accessors;27.struct irq_chip *chip;28.struct irq_domain *domain;29.void *handler_data;30.void *chip_data;31.struct msi_desc *msi_desc;32.#ifdef CONFIG_SMP33.cpumask_var_t affinity;34.#endif35.};</span>◎action提供了一个操作链,需要在中断发生时执行。