linux中断处理原理分析

首先需要了解一下中断的概念:一个“中断”仅仅是一个信号,当硬件需要获得处理器对它的关注时,就可以发送这个信号。内核维护了一个中断信号线的注册表,该注册表类似于I/O端口的注册表。

模块在使用中断前要先请求一个中断通道(或中断请求IRQ),然后在使用后释放该通道。用到的API就是request_irq()以及free_irq()。注意在调用request_irq()和free_irq()的时机最好是在设备第一次打开和最后一次关闭之后。

对于中断处理例程来讲,它的一个典型的任务就是:如果中断通知进程所等待的事件已经发生,比如新的数据到达就会唤醒在该设备上休眠的进程。无论是快速还是慢速处理例程,程序员都应该编写执行事件尽可能短的处理例程。如果需要执行一个长时间的计算任务,做好的办法就是使用上下半部处理机制,以便让工作在更安全的时间里调度计算任务。

上半部的功能是响应中断。当中断发生时,它就把设备驱动程序中中断处理例程的下半部挂到设备的下半部执行队列中去,然后继续等待新的中断到来。这样一来,上半部的执行速度就会很快,它就可以接受更多它负责的设备所产生的中断了。上半部之所以快,是因为它是完全屏蔽中断的,如果它没有执行完,其他中断就不能及时地处理,只能等到这个中断处理程序执行完毕以后。所以要尽可能多的对设备产生的中断进行服务和处理,中断处理程序就一定要快。

下半部的功能是处理比较复杂的过程。下半部和上半部最大的区别是可中断,而上半部却不可中断。下半部几乎完成了中断处理程序所有的事情,因为上半部只是将下半部排到了它们所负责的设备中断的处理队列中去,然后就不做其它的处理了。下半部所负责的工作一般是查看设备以获得产生中断的事件信息,并根据这些信息(一般通过读设备上的寄存器得来)进行相应的处理。下半部是可中断的,所以在运行期间,如果其它设备产生了中断,这个下半部可以暂时的中断掉,等到那个设备的上半部运行完了,再回头运行这个下半部。

这上面大多数都是我们在查阅资料和听老师讲课获取的知识内容但是具体是如何实现的呢?

也许我们也知道tasklet和work_queue。知道这两个是完成下半部的。在具体的过程中我们将如何实现呢?

此处就是通过创建工作队列的方式我们把初始化的操作都放在irq之前完成,在irq_handler()中将具体的工作提交到工作队列中。使用的API为queue_work()。具体的细节问题希望读者能够查阅资料自行完成。

Tasklet作为一种新机制,显然可以承担更多的优点。正好这时候SMP越来越火了,因此又在tasklet中加入了SMP机制,保证同种中断只能在一个cpu上执行。在软中断时代,显然没有这种考虑。因此同一种中断可以在两个cpu上同时执行,很可能造成冲突。

Linux中断下半部处理有三种方式:软中断、tasklet、工作队列。

曾经有人问我为什么要分这几种,该怎么用。当时用书上的东西蒙混了过去,但是自己明白自己实际上是不懂的。最近有时间了,于是试着整理一下linux的中断处理机制,目的是起码从原理上能够说得通。

一、最简单的中断机制

最简单的中断机制就是像芯片手册上讲的那样,在中断向量表中填入跳转到对应处理函数的指令,然后在处理函数中实现需要的功能。类似下图:

这种方式在原来的单片机课程中常常用到,一些简单的单片机系统也是这样用。

它的好处很明显,简单,直接。

二、下半部

中断处理函数所作的第一件事情是什么?答案是屏蔽中断(或者是什么都不做,因为常常是如果不清除IF位,就等于屏蔽中断了),当然只屏蔽同一种中断。之所以要屏蔽中断,是因为新的中断会再次调用中断处理函数,导致原来中断处理现场的破坏。即,破坏了 interrupt context。

随着系统的不断复杂,中断处理函数要做的事情也越来越多,多到都来不及接收新的中断了。于是发生了中断丢失,这显然不行,于是产生了新的机制:分离中断接收与中断处理过程。中断接收在屏蔽中断的情况下完成;中断处理在时能中断的情况下完成,这部分被称为中断下半部。

从上图中看,只看int0的处理。Func0为中断接收函数。中断只能简单的触发func0,而func0则能做更多的事情,它与funcA之间可以使用队列等缓存机制。当又有中断发生时,func0被触发,然后发送一个中断请求到缓存队列,然后让funcA去处理。

由于func0做的事情是很简单的,所以不会影响int0的再次接收。而且在func0返回时就会使能int0,因此funcA执行时间再长也不会影响int0的接收。

三、软中断

下面看看linux中断处理。作为一个操作系统显然不能任由每个中断都各自为政,统一管理是必须的。

我们不可中断部分的共同部分放在函数do_IRQ中,需要添加中断处理函数时,通过request_irq实现。下半部放在do_softirq中,也就是软中断,通过open_softirq添加对应的处理函数。

四、tasklet

旧事物跟不上历史的发展时,总会有新事物出现。

随着中断数的不停增加,软中断不够用了,于是下半部又做了进化。

软中断用轮询的方式处理。假如正好是最后一种中断,则必须循环完所有的中断类型,才能最终执行对应的处理函数。显然当年开发人员为了保证轮询的效率,于是限制中断个数为32个。

为了提高中断处理数量,顺道改进处理效率,于是产生了tasklet机制。

Tasklet采用无差别的队列机制,有中断时才执行,免去了循环查表之苦。

总结下tasklet的优点:

(1)无类型数量限制;

(2)效率高,无需循环查表;

(3)支持SMP机制;

五、工作队列

前面的机制不论如何折腾,有一点是不会变的。它们都在中断上下文中。什么意思?说明它们不可挂起。而且由于是串行执行,因此只要有一个处理时间较长,则会导致其他中断响应的延迟。为了完成这些不可能完成的任务,于是出现了工作队列。工作队列说白了就是一组内核线程,作为中断守护线程来使用。多个中断可以放在一个线程中,也可以每个中断分配一个线程。

工作队列对线程作了封装,使用起来更方便。

因为工作队列是线程,所以我们可以使用所有可以在线程中使用的方法。

Tasklet其实也不一定是在中断上下文中执行,它也有可能在线程中执行。

假如中断数量很多,而且这些中断都是自启动型的(中断处理函数会导致新的中断产生),则有可能cpu一直在这里执行中断处理函数,会导致用户进程永远得不到调度时间。

为了避免这种情况,linux发现中断数量过多时,会把多余的中断处理放到一个单独的线程中去做,就是ksoftirqd线程。这样又保证了中断不多时的响应速度,又保证了中断过多时不会把用户进程饿死。

问题是我们不能保证我们的tasklet或软中断处理函数一定会在线程中执行,所以还是不能使用进程才能用的一些方法,如放弃调度、长延时等。

六、使用方式总结

Request_irq挂的中断函数要尽量简单,只做必须在屏蔽中断情况下要做的事情。

中断的其他部分都在下半部中完成。

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

工作队列也要少用,如果不是必须要用到线程才能用的某些机制,就不要使用工作队列。其实对于中断来说,只是对中断进行简单的处理,大部分工作是在驱动程序中完成的。所以有什么必要非使用工作队列呢?

除了上述情况,就要使用tasklet。

即使是下半部,也只是作必须在中断中要做的事情,如保存数据等,其他都交给驱动程序去做。

版权声明:本文为【借你一秒】原创文章,转载请标明出处。

时间: 2024-10-05 04:58:32

linux中断处理原理分析的相关文章

linux系统调用原理分析

自己想看看别人开发的项目,吸收下经验,然后找到开源中国,有些网上的大牛自己也开发出了开源中国的客户端 在网上看到很多网友说,下载下来安装不了之类的东西,在我这里我带个路,希望对那些朋友有些帮助. https://github.com/jimneylee/JLRubyChina-iPhone   开源中国源码地址 界面如下: 很多的朋友会直接点击Download ZIP,然后下载下来,打开,打开后就直接CocoaPods更新运行如下命令行 $ pod install 下载了其他的sdk下来后,以为

linux中mmap系统调用原理分析与实现

参考文章:http://blog.csdn.net/shaoguangleo/article/details/5822110 linux中mmap系统调用原理分析与实现 1.mmap系统调用(功能)      void* mmap ( void * addr , size_t len , int prot , int flags ,int fd , off_t offset )      内存映射函数mmap, 负责把文件内容映射到进程的虚拟内存空间, 通过对这段内存的读取和修改,来实现对文件的

嵌入式linux QT开发(三)——GUI原理分析

嵌入式linux QT开发(三)--GUI原理分析 一.命令行程序 命令行程序是面向过程的程序设计. 命令行程序的特点: A.基于顺序结构执行 B.程序执行过程中不需与用户交互 C.程序执行结束给出最终运行结果 命令行程序适用场合: A.单任务场合 B.无交互.简单交互场合 C.服务器应用场合 二.GUI程序 GUI程序的特点: A.基于消息驱动模型的程序 B.程序执行依赖用户交互过程 C.程序执行过程中实时响应用户操作 D.一般程序执行后不会主动退出 GUI程序适用场合: A.多任务场合 B.

linux下编译原理分析

linux下编译hello.c 程序,使用gcc hello.c,然后./a.out就可以运行:在这个简单的命令后面隐藏了许多复杂的过程,这个过程包括了下面的步骤: ====================================================================================== 预处理: 宏定义展开,所有的#define 在这个阶段都会被展开 预编译命令的处理,包括#if #ifdef 一类的命令 展开#include 的文件,像上面h

《Linux内核原理与分析》教学进程

目录 2019-2020-1 <Linux内核原理与分析>教学进程 考核方案 第一周: 第二周: 第三周: 第四周: 第五周 第六周 第七周: 第八周 第九周 第十周 第十一周: 第十二周 第十三周 2019-2020-1 <Linux内核原理与分析>教学进程 考核方案 采取过程化考核,平时成绩占100分,成绩计算:30+30+15+25=100: 翻转课堂基础考核10次: 3*10 = 30 每次考试20-30道题目,考试成绩规格化成3分(比如总分30分就除以10) 翻转课堂测试

linux用户进程分析

       经过实验3的介绍,我们需要来点实在的,所以将我们理解的流程用于linux系统的分析.换句话说,通过类比的方式去进行描述与理解linux相关的部分.本节的内容很详实,而且也分析了很久,所以长话短说,静静的去感受与理解linux内核代码的实现.当然,我们实验的系统代码很简单而且直接,但是linux内核经过20多年的发展,更有成千上万的开发者共同维护,所以对于代码的书写会更加精练,对于基础相对薄弱的程序员去理解有一些障碍,但是反过来说,更有利于我们语言知识的提高. 如下的介绍方法是对

2017-2018-1 20179205《Linux内核原理与设计》第九周作业

<Linux内核原理与设计>第九周作业 视频学习及代码分析 一.进程调度时机与进程的切换 不同类型的进程有不同的调度需求,第一种分类:I/O-bound 会频繁的进程I/O,通常会花费很多时间等待I/O操作的完成:CPU-bound 是计算密集型,需要大量的CPU时间进行运算,使得其他交互式进程反应迟钝,因此需要不同的算法来使系统的运行更高效,以及CPU的资源最大限度的得到使用.第二种分类包括批处理进程(batch process):实时进程(real-time process)以及交互式进程

深入剖析Linux IO原理和几种零拷贝机制的实现

深入剖析Linux IO原理和几种零拷贝机制的实现 来源 https://zhuanlan.zhihu.com/p/83398714 零壹技术栈      公众号[零壹技术栈] 前言 零拷贝(Zero-copy)技术指在计算机执行操作时,CPU 不需要先将数据从一个内存区域复制到另一个内存区域,从而可以减少上下文切换以及 CPU 的拷贝时间.它的作用是在数据报从网络设备到用户程序空间传递的过程中,减少数据拷贝次数,减少系统调用,实现 CPU 的零参与,彻底消除 CPU 在这方面的负载.实现零拷贝

linux串口驱动分析

linux串口驱动分析 硬件资源及描写叙述 s3c2440A 通用异步接收器和发送器(UART)提供了三个独立的异步串行 I/O(SIO)port,每一个port都能够在中断模式或 DMA 模式下操作.UART 使用系统时钟能够支持最高 115.2Kbps 的波特率.每一个 UART 通道对于接收器和发送器包含了 2 个 64 位的 FIFO. 寄存器 名称 地址 在linux中的描写叙述 (2410 和 2440 处理器对内存地址映射关系同样) UART 线性控制寄存器(ULCONn) ULC