当前位置:文档之家› linux中断底半部机制对比(任务队列,工作队列,软中断)--由linux RS485引出的血案-ispsubb-ChinaUnix博客

linux中断底半部机制对比(任务队列,工作队列,软中断)--由linux RS485引出的血案-ispsubb-ChinaUnix博客

ARM-Linux下的GPIO中断程序.

ARM-Linux下的GPIO中断程序 [日期:2011-03-22] 来源:Linux社区作者:cskywit 今日为了调试ARM板上的GPIO引脚中断效果,以便在后续项目使用ARM与ZLG7290按键LED中断芯片连接中随意选择空闲的GPIO引脚来作为ZLG7290的中断信号线,特意编写了一个小的Linux GPIO中断驱动程序下载到开发板上做实验。经验证,这种软件中断方式也还差强人意。下面贴出自己编写的不成熟的代码,见笑(<-_->)。 实验的硬件电路为ARM GPIO的PB17连接一个共阴LED,PB18与PB19连接,PB18由中断驱动设置为低电平触发,PB19由GPIO驱动程序控制,上层应用程序通过驱动控制PB19高低电平变化,从而引发PB18发生中断,中断程序中控制PB17的LED亮和灭。 Linux中断驱动部分: /* * PB18_IRQTest.c * This is a test program for sam9260, using PB19(J5_18 pin) input a signal to PB18(J5_16 pin), * PB18 receive this signal as IRQ and make the LED linking on PB17((J5_14 pin)) turn on or turn off * * @Author: Cun Tian Rui * @Date :March.18.2011 */ #include #include #include #include #include #include #include #include #include #include #include #include #include

armlinux内核中ARM中断实现详解.

linux-2.6.26内核中ARM中断实现详解(1) 作者:刘洪涛,华清远见嵌入式学院金牌讲师,ARM ATC授权培训讲师。 看了一些网络上关于linux中断实现的文章,感觉有一些写的非常好,在这里首先感谢他们的无私付出,然后也想再补充自己对一些问题的理解。先从函数注册引出问题吧。 一、中断注册方法 在linux内核中用于申请中断的函数是request_irq(),函数原型在 Kernel/irq/manage.c中定义: int request_irq(unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id) irq是要申请的硬件中断号。 handler是向系统注册的中断处理函数,是一个回调函数,中断发生时,系统调用这个函数,dev_id参数将被传递给它。 irqflags是中断处理的属性,若设置了IRQF_DISABLED (老版本中的 SA_INTERRUPT,本版zhon已经不支持了),则表示中断处理程序是快速处理程序,快速处理程序被调用时屏蔽所有中断,慢速处理程序不屏蔽;若设置了IRQF_SHARED (老版本中的SA_SHIRQ),则表示多个设备共享中断,若设置了IRQF_SAMPLE_RANDOM(老版本中的 SA_SAMPLE_RANDOM),表示对系统熵有贡献,对系统获取随机数有好处。(这几个flag是可以通过或的方式同时使用的) dev_id在中断共享时会用到,一般设置为这个设备的设备结构体或者NULL。 devname设置中断名称,在cat /proc/interrupts中可以看到此名称。 request_irq()返回0表示成功,返回-INVAL表示中断号无效或处理函数指针为NULL,返回-EBUSY表示中断已经被占用且不能共享。 关于中断注册的例子,大家可在内核中搜索下request_irq。 在编写驱动的过程中,比较容易产生疑惑的地方是: 1、中断向量表在什么位置?是如何建立的? 2、从中断开始,系统是怎样执行到我自己注册的函数的? 3、中断号是如何确定的?对于硬件上有子中断的中断号如何确定? 4、中断共享是怎么回事,dev_id的作用是? 本文以2.6.26内核和S3C2410处理器为例,为大家讲解这几个问题。

linux中断总结

1.Linux中断的注册与释放: 在, , 实现中断注册接口: int request_irq(unsigned int irq,irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *dev_name, void *dev_id); void free_irq(unsigned int irq, void *dev_id); 函数参数说明 unsigned int irq:所要注册的中断号 irqreturn_t (*handler)(int, void *, struct pt_regs *):中断服务程序的入口地址。unsigned long flags:与中断管理有关的位掩码选项,有三组值: 1. SA_INTERRUPT :快速中断处理程序,当使用它的是后处理器上所有的其他中断都被禁用。 2. SA_SHIRQ :该中断是在设备之间可共享的 3. SA_SAMPLE_RANDOM :这个位表示产生的中断能够有贡献给 /dev/random 和 /dev/urandom 使用的加密池.(此处不理解) const char *dev_name:设备描述,表示那一个设备在使用这个中断。 void *dev_id:用作共享中断线的指针. 它是一个独特的标识, 用在当释放中断线时以及可能还被驱动用来指向它自己的私有数据区(来标识哪个设备在中断) 。这个参数在真正的驱动程序中一般是指向设备数据结构的指针.在调用中断处理程序的时候它就会传递给中断处理程序的void *dev_id。(这是我的理解)如果中断没有被共享, dev_id 可以设置为 NULL, 但是使用这个项指向设备结构不管如何是个好主意. 我们将在"实现一个处理"一节中看到dev_id 的一个实际应用。 中断号的查看可以使用下面的命令:“cat /proc/interrupts”。 /proc/stat 记录了几个关于系统活动的低级统计量, 包括(但是不限于)自系统启动以来收到的中断数. stat 的每一行以一个文本字串开始, 是该行的关键词; intr 标志是我们在找的. 第一个数是所有中断的总数, 而其他每一个代表一个单个 IRQ 线, 从中断 0 开始. 所有的计数跨系统中所有处理器而汇总的. 这个快照显示, 中断号 4 已使用 1 次, 尽管当前没有安装处理. 如果你在测试的驱动请求并释放中断在每个打开和关闭循环, 你可能发现/proc/stat 比 /proc/interrupts 更加有用. 以下是一个统计中断时间间隔的中断服务程序。 irqreturn_t short_interrupt(int irq, void *dev_id, struct pt_regs *regs) { static long mytime=0; static int i=0; struct net_device *dev=(struct net_device *)dev_id; if(i==0){ mytime=jiffies; }else if(i<20){ mytime =jiffies- mytime; printk("Request on IRQ %d time %d\n",irq , mytime); mytime=jiffies;

LINUX内核时钟中断机制

Linux内核的时钟中断机制 opyright © 2003 by 詹荣开 E-mail:zhanrk@https://www.doczj.com/doc/013343309.html, Linux-2.4.0 Version 1.0.0,2003-2-14 摘要:本文主要从内核实现的角度分析了Linux 2.4.0内核的时钟中断、内核对时间的表示等。本文是为那些想要了解Linux I/O子系统的读者和Linux驱动程序开发人员而写的。 关键词:Linux、时钟、定时器 申明:这份文档是按照自由软件开放源代码的精神发布的,任何人可以免费获得、使用和重新发布,但是你没有限制别人重新发布你发布内容的权利。发布本文的目的是希望它能对读者有用,但没有任何担保,甚至没有适合特定目的的隐含的担保。更详细的情况请参阅GNU 通用公共许可证(GPL),以及GNU自由文档协议(GFDL)。 你应该已经和文档一起收到一份GNU通用公共许可证(GPL)的副本。如果还没有,写信给:The Free Software Foundation, Inc., 675 Mass Ave, Cambridge,MA02139, USA 欢迎各位指出文档中的错误与疑问。 前言 时间在一个操作系统内核中占据着重要的地位,它是驱动一个OS内核运行的“起博器”。一般说来,内核主要需要两种类型的时间: (1)、在内核运行期间持续记录当前的时间与日期,以便内核对某些对象和事件作时间标记(timestamp,也称为“时间戳”),或供用户通过时间syscall进行检索。 (2)、维持一个固定周期的定时器,以提醒内核或用户一段时间已经过去了。 PC机中的时间是有三种时钟硬件提供的,而这些时钟硬件又都基于固定频率的晶体振荡

Linux中断处理流程

Linux中断处理流程 先从函数注册引出问题吧。 一、中断注册方法 在linux内核中用于申请中断的函数是request_irq(),函数原型在Kernel/irq/manage.c中定义: int request_irq(unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id) irq是要申请的硬件中断号。 handler是向系统注册的中断处理函数,是一个回调函数,中断发生时,系统调用这个函数,dev_id参数将被传递给它。 irqflags是中断处理的属性,若设置了IRQF_DISABLED (老版本中的SA_INTERRUPT,本版zhon已经不支持了),则表示中断处理程序是快速处理程序,快速处理程序被调用时屏蔽所有中断,慢速处理程 序不屏蔽;若设置了IRQF_SHARED (老版本中的SA_SHIRQ),则表示多个设备共享中断,若设置了IRQF_SAMPLE_RANDOM(老版本中的 SA_SAMPLE_RANDOM),表示对系统熵有贡献,对系统获取随机数有好处。(这几个flag是可以通过或的方式同时使用的) dev_id在中断共享时会用到,一般设置为这个设备的设备结构体或者NULL。devname设置中断名称,在cat /proc/interrupts中可以看到此名称。 request_irq()返回0表示成功,返回-INVAL表示中断号无效或处理函数指针为NULL,返回-EBUSY表示中断已经被占用且不能共享。 关于中断注册的例子,大家可在内核中搜索下request_irq。 在编写驱动的过程中,比较容易产生疑惑的地方是: 1、中断向量表在什么位置?是如何建立的? 2、从中断开始,系统是怎样执行到我自己注册的函数的? 3、中断号是如何确定的?对于硬件上有子中断的中断号如何确定? 4、中断共享是怎么回事,dev_id的作用是? 本文以2.6.26内核和S3C2410处理器为例,为大家讲解这几个问题。 二、异常向量表的建立 在ARM V4及V4T以后的大部分处理器中,中断向量表的位置可以有两个位置:一个是0,另一个是0xffff0000。可以通过CP15协处理器c1寄存器中V位(bit[13])控制。V和中断向量表的对应关系如下: V=0 ~ 0x00000000~0x0000001C V=1 ~ 0xffff0000~0xffff001C arch/arm/mm/proc-arm920.S中 .section ".text.init", #alloc, #execinstr __arm920_setup: ...... orr r0, r0, #0x2100 @ ..1. ...1 ..11 (1) //bit13=1 中断向量表基址为0xFFFF0000。R0的值将被付给CP15的C1.

linux中断实例

你的第一个中断程序: 本文通过一个简单的中断程序来描述一般中断程序的基本框架。完整代码在这里。 中断程序一般会包含在某个设备的驱动程序中,因此,接下来的程序本质上还是一个内核模块。说到内核模块,你应该知道首先去看什么了吧?对了,就是内核模块加载函数。 view source print? 01 static int __init myirq_init() 02 { 03 printk("Module is working..\n"); 04 if(request_irq(irq,myirq_handler,IRQF_SHARED,devname, &mydev)!=0) 05 { 06 printk("%s request IRQ:%d failed..\n",devname,irq); 07 return -1; 08 } 09 printk("%s rquest IRQ:%d success..\n",devname,irq); 10 return 0; 11 } 在内核加载函数中,我们除了显示一些信息外,最重要的工作就是申请一根中断请求线,也就是注册中断处理程序。很明显,这一动作是通过 request_irq函 数来完成的。这个函数的原型如下: view source print? 1 static int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,const char *name, void *dev); 第一个参数是中断号,这个中断号对应的就是中断控制器上IRQ线的编号。 第二个参数是一个irq_handler_t类型个函数指针: view source print? 1 typedef irqreturn_t (*irq_handler_t)(int, void *); handler所指向的函数即为中断处理程序,需要具体来实现。 第三个参数为标志位,可以取IRQF_DISABLED、IRQF_SHARED和 IRQF_SAMPLE_RANDOM之一。在本实例程序中取 IRQF_SHARED,该标志表示多个 设备共享一条IRQ线,因此相应的每个设备都需要各自的中断服务例程。一般某个中断线上的中断服务程序在执行时会屏蔽请求该线的其他中断,如果取

linux 中断分析

Linux系统中有很多不同的硬件设备。你可以同步使用这些设备,也就是说你可以发出一个请求,然后等待 一直到设备完成操作以后再进行其他的工作。但这种方法的效率却非常的低,因为操作系统要花费很多的等待时间。一个更为有效的方法是发出请求以后,操作系统继续其他的工作,等设备完成操作以后,给操作系统发送一个中断,操作系统再继续处理和此设备有关的操作。 在将多个设备的中断信号送往CPU的中断插脚之前,系统经常使用中断控制器来综合多个设备的中断。这样即可以节约CPU的中断插脚,也可以提高系统设计的灵活性。中断控制器用来控制系统的中断, 它包括屏蔽和状态寄存器。设置屏蔽寄存器的各个位可以允许或屏蔽某一个中断,状态寄存器则用来返回系统中正在使用的中断。 大多数处理器处理中断的过程都相同。当一个设备发出中段请求时,CPU停止正在执行的指令,转而跳到包括中断处理代码或者包括指向中断处理代码的转移指令所在的内存区域。这些代码一般在CPU的中断方式下运行。在此方式下,将不会再有中断发生。但有些CPU的中断有自己的优先权,这样,更高优先权的中断则可以发生。这意味着第一级的中断处理程序必须拥有自己的堆栈,以便在处理更高级别的中断前保存CPU的执行状态。当中断处理完毕以后,CPU将恢复到以前的状态,继续执行中断处理前正在执行的指令。 中断处理程序十分简单有效,这样,操作系统就不会花太长的时间屏蔽其他的中断。 [设置Softirq] cpu_raise_softirq是一个轮训,唤醒ksoftirqd_CPU0内核线程, 进行管理 cpu_raise_softirq |__cpu_raise_softirq |wakeup_softirqd |wake_up_process ·cpu_raise_softirq [kernel/softirq.c] ·__cpu_raise_softirq [include/linux/interrupt.h] ·wakeup_softirq [kernel/softirq.c]

Linux中断(interrupt)子系统之一:arch相关的硬件封装层

Linux中断(interrupt)子系统之一:arch相关的硬件封装层Linux的通用中断子系统的一个设计原则就是把底层的硬件实现尽可能地隐藏起来,使得驱动程序的开发人员不用关注底层的实现,要实现这个目标,内核的开发者们必须把硬件相关的内容剥离出来,然后定义一些列标准的接口供上层访问,上层的开发人员只要知道这些接口即可完成对中断的进一步处理和控制。对底层的封装主要包括两部分: 实现不同体系结构中断入口,这部分代码通常用asm实现; 中断控制器进行封装和实现; 本文的内容正是要讨论硬件封装层的实现细节。我将以ARM体系进行介绍,大部分的代码位于内核代码树的arch/arm/目录内。 1. CPU的中断入口 我们知道,arm的异常和复位向量表有两种选择,一种是低端向量,向量地址位于0x00000000,另一种是高端向量,向量地址位于0xffff0000,Linux选择使用高端向量模式,也就是说,当异常发生时,CPU会把PC指针自动跳转到始于0xffff0000开始的某一个地址上: ARM的异常向量表地址异常种类FFFF0000复位FFFF0004未定义指令FFFF0008软中断(swi)FFFF000CPrefetch abortFFFF0010Data abortFFFF0014保留FFFF0018IRQFFFF001CFIQ 中断向量表在arch/arm/kernel/entry_armv.S中定义,为了方便讨论,下面只列出部分关键的代码: [plain] view plain copy .globl __stubs_start __stubs_start: vector_stub irq, IRQ_MODE, 4 .long __irq_usr @ 0 (USR_26 / USR_32) .long __irq_invalid @ 1 (FIQ_26 / FIQ_32) .long __irq_invalid @ 2 (IRQ_26 / IRQ_32)

Linux中断处理过程浅析

linux中断响应和处理过程: 首先中断属于异常的一种。异常,就是可以打断CPU正常运行流程的一些事情,比如说外部中断,未定义的指定,试图修改只读数据,执行SWI指定(software interrupt instructin,软件中断指令,比如说上层调用sys_read,sys_write就会产生swi)等。 内核启动时在start_kernel函数(init/main.c)中调用trap_init , init_IRQ两个函数来设置异常的处理函数。 trap_init函数(arch/arm/kernel/traps.c) void_init trap_init(void) { ...... memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start); memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start); ....... } 上面两条定义的是异常向量的存放地方,即:__stubs_start~~~~~ __stubs_end之间就是异常向量. 接下来我们看异常向量之间的定义:(arch/arm/kernel/entry-armv.s) .equ stubs_offset, __vectors_start + 0x200 - __stubs_start .globl __vectors_start __vectors_start: ARM( swi SYS_ERROR0 ) //复位时.CPU交执行这条指令 THUMB( svc #0 ) THUMB( nop ) W(b) vector_und + stubs_offset //未定义异常时,CPU将执行这条跳转指令 W(ldr) pc, .LCvswi + stubs_offset //swi异常 W(b) vector_pabt + stubs_offset //指令预取止 W(b) vector_dabt + stubs_offset //数据访问中止 W(b) vector_addrexcptn + stubs_offset //没有用到 W(b) vector_irq + stubs_offset //irq中断 W(b) vector_fiq + stubs_offset //fig中断(快速中断) .globl __vectors_end __vectors_end: 各种异常的处理函数可以分为五类,分别分布在下面不同的文件中: 1、arch/arm/kernel/traps.c中 处理未定义指令异常,总入口函数为do_undefinstr

细说Linux内核中断架构

细说Linux内核中断架构 分类:网络Unix/Linux内核学习2012-06-14 17:59 38人阅读评论(0) 收藏举报 中断和异常 一、什么是中断? 中断通常被定义为一个事件,该事件改变处理器执行的指令顺序。这样的事件与CPU芯片内外部硬件电路产生的电信号相对应。 中断通常分为同步中断和异步中断: 2同步中断是当指令执行时由CPU控制单元产生的,之所以称为同步,是因为只有在一条指令终止执行后CPU才会发出中断。 ◎异步中断是由其他硬件设备依照CPU时钟信号随机产生的。 在Intel微处理器手册中: ◎把同步中断称为异常(exception) ◎把异步中断称为中断(interrupt) 这两类中断的共同特点是什么?如果CPU当前不处于核心态,则发起从用户态到核心态的切换。接下来,在内核中执行一个专门的例程,称为中断服务例程(interrupt service routine)。或中断处理程序(interrupthandler) 另一方面,异常是由程序的错误产生的,或者是由内核必须处理的异常条件产生的。第一种情况下,内核通过发送一个每个Unix/Linux程序员都熟悉的信号来处理异常。第二种情况下,内核执行恢复异常需要的所有步骤,例如缺页异常等。 二、中断信号的作用 中断信号提供了一种特殊的方式,使处理器转而去运行正常控制流之外的代码。当一个中断信号达到时,CPU必须停止它当前正在做的事情,并且切换到一个新的活动。为了这做到这

一点,就要在内核态堆栈保存程序计数器的当前值(即EIP和CS寄存器的内容),并把与中断类型相关的一个地址放进程序计数器。 这可能会让我们想起系统调度的进程切换,发生在内核用一个进程替换另一个进程时。但是中断处理与进程切换有一个明显的差异:由中断或异常处理程序执行的代码不是一个进程。更准确的说,它是一个内核控制路径,代表中断发生时正在运行的进程执行。作为一个内核控制路径,中断处理程序比一个进程要“轻”(中断的上下文很少,建立或终止中断处理需要的时间也很少) 中断处理是由内核执行的最敏感的任务之一,因为它必须满足下列约束: ◎当内核正打算去完成一些别的事情时,中断随时会到来。因此,内核的目标就是让中断尽可能快地处理完,尽其所能把更多的处理向后推迟。因此,内核响应中断后需要进行的操作分为两部分:关键而紧急的部分,内核立即执行;其余推迟的部分,内核随后执行。 ◎因为中断随时会到来,所以内核可能正在处理其中的一个中断时,另一个不同类型的中断又发生了。内核应该尽可能地允许这种情况发生,因为这能维持更多的I/O设备得到处理的机会。因此,中断处理程序必须编写成使相应的内核控制路径能以嵌套的方式执行。当最后一个内核控制路径终止时,内核必须能恢复被中断进程的执行,或者,如果中断信号已导致了重新调度,内核也应能切换到另外的进程。 ◎尽管内核在处理前一个中断时可以接受一个新的中断,但在内核代码中还是存在一些临界区,在临界区中,中断必须被禁止。必须尽可能地限制这样的临界区,因为根据以前的要求,内核,尤其是中断处理程序,应该在大部分时间内以开中断的方式运行。 三、IRQ和中断 中断这个名词使用得并不是很谨慎,为什么?由于中断是用来表示由CPU和外部硬件发出的信号所产生的。但是中断不能由处理器外部的外设直接产生,而必须借助于一个称为可编

Linux下的一个使用中断的按键驱动程序v

Linux下的一个使用中断的按键驱动程序(S3C2440)#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*timer*/ #define BUTTON_IRQ IRQ_EINT8 //申请的中断号 #define DEVICE_NAME "button" //设备名字 #define BUTTONMINOR 0

#define DELAY (HZ/100) //延时100MS DECLARE_WAIT_QUEUE_HEAD(wq); //申请一个wq等待队列并初始化, //wait_queue_heat_t wq; //也可用两句来替换(申请初始化一个等待队列)//int_waitqueue_heat(&wq); static unsigned char key_down_cnt=0; //中断计数 static int ev_press=0; //唤醒等待的条件 static int button_Major; struct timer_list timer; //定时器链表 void timer_function()//定时产生后的处理函数 { int down; if(down = !s3c2410_gpio_getpin(BUTTON_IRQ)) //如果按键按下执行以下程序{ key_down_cnt++; //来一次,中断计数加一 ev_press = 1; //表示中断发生了 wake_up_interruptible(&wq); } //唤醒休眠的进程 return 0; } static irqreturn_t button_irq_ser(int irq,void *dev_id,struct pt_regs *regs) //中断服务程序 { //初始化定时器链表 init_timer(&timer); timer.data=0; timer.expires=jiffies+DELAY;

linux中断cpu负担均衡

现实中的问题 随着硬件成本的降低,我们服务器配置也越来越“上流”了,可是单台服务器的包处理能力还是很有限,经常看到cpu负载很高,linux内核自从2.4版本之后就引入了netfilter框架,网络数据包的处理能力很大程度上是以并发连接数来衡量的,每一个连接在内核中实际上是做了很多处理的。特别是有大量udp包处理的情况,这些udp包多是短连接,并发量又大,也就是说对cpu的耗费是非常大的。mpstat -P ALL 1: 我们从图中可以看出cpu0处于比较繁忙的状态,占用率在60%-70%,已经是高负载,实际上linux内核从2.4开始就已经支持中断数在各个cpu上的负载均衡了,很显然我们没有充分利用已有的多cpu资源。 解决之道 我们知道,任何外设(如磁盘,网卡等)需要cpu服务时,都会抛出一个中断,中断告诉cpu 发生了什么事情,cpu就要停止目前的工作来处理这个中断。比如当网卡收到包时,假如cpu 正在执行某个应用进程处理程序,此刻就会被网卡中断所打断执行中断处理程序。每个外设对应的中断处理程序自然是不同的,因此为了进行区分,防止多个设备发出相同的中断请求,系统中的每个设备都被分配了一个独一无二的IRQ(Interupt Request)。 每个设备对应的IRQ信息可以从/proc/interrupts中读取: 第一列即为每台设备对应的IRQ,这个在不同机器上可能会不同,该图中我们可以看出网卡eth1对应的IRQ为16。 第二列到第五列分别对应cpu0-cpu3已经处理的关于某个IRQ(对应某设备)的中断数量。这是我做过优化之后的截图,可以看到各个cpu都处理了大概一样多的eth1网卡中断。 第六列对应中断控制器。 第七列就是具体的设备了。

armlinux内核中arm中断实现详解

linux-2.6.26 内核中ARM中断实现详解(1) 作者:刘洪涛,华清远见嵌入式学院金牌讲师,ARM AT(授权培训讲师。 看了一些网络上关于linux 中断实现的文章,感觉有一些写的非常好,在这里首先感谢他们的无私付出,然后也想再补充自己对一些问题的理解。先从函数注册引出问题吧。 一、中断注册方法 在linux 内核中用于申请中断的函数是request_irq (),函数原型在 Kernel/irq/manage.c 中定义: int request_irq(unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id) irq 是要申请的硬件中断号。 handler 是向系统注册的中断处理函数,是一个回调函数,中断发生时,系统调用这个函数,dev_id 参数将被传递给它。 irqflags 是中断处理的属性,若设置了IRQF_DISABLED (老版本中的 SA_INTERRUPT本版zhon已经不支持了),贝J表示中断处理程序是快速处理程序,快速处理程序被调用时屏蔽所有中断,慢速处理程序不屏蔽;若设置了IRQF_SHARE (老版本中的SA_SHIRQ,则表示多个设备共享中断,若设置了IRQF_SAMPLE_RAND老版本中的SA_SAMPLE_RANDQM表示对系统熵有贡献,对系统获取随机数有好处。(这几个flag 是可以通过或的方式同时使用的)dev_id 在中断共享时会用到,一般设置为这个设备的设备结构体或者NULL。 devname设置中断名称,在cat /proc/interrupts 中可以看到此名称。 request_irq()返回0表示成功,返回-INVAL表示中断号无效或处理函数指针为NULL返回-EBUSY表示中断已经被占用且不能共享。 关于中断注册的例子,大家可在内核中搜索下request_irq 。 在编写驱动的过程中,比较容易产生疑惑的地方是: 1、中断向量表在什么位置?是如何建立的? 2、从中断开始,系统是怎样执行到我自己注册的函数的? 3 、中断号是如何确定的?对于硬件上有子中断的中断号如何确定? 4、中断共享是怎么回事,dev_id 的作用是?本文以2.6.26内核和S3C2410处理器为例,为大家讲解这几个问题

超强的Linux中断分析

超强的Linux中断分析[日期:2008-09-13] 来源:作者: 1) IPI中断的初始化。 intr_init_hook调用apic_intr_init(),后者再调用──如果CONFIG_SMP──smp_intr_init(), 这个函数设置IPI中断的处理,然后,apic_intr_init()为另外两个IPI:SPURIOUS_APIC_VECTOR和 ERROR_APIC_VECTOR设置ISR。 2) irq_desc[NR_IRQS] struct irq_desc,亦即irq_desc_t,描述了一个irq的属性,如irqaction、depth、 pending_mask等。 include/linux/irq.h: struct irq_desc { 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 int irqs_unhandled; spinlock_t lock; #ifdef CONFIG_SMP cpumask_t affinity; unsigned int cpu; #endif #if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE) cpumask_t pending_mask; #endif #ifdef CONFIG_PROC_FS struct proc_dir_entry *dir; #endif

Linux实现时钟中断的全过程

Linux实现时钟中断的全过程 1.可编程定时/计数器的初始化 IBM PC中使用的是8253或8254芯片。有关该芯片的详细知识我们不再详述,只大体介绍以下它的组成和作用,如下表5.1所示: 表5.1 8253/8254的组成及作用 计数器0的输出就是图5.3中的Out0,它的频率由操作系统的设计者确定,Linux对8253的初始化程序段如下(在/arch/i386/kernel/i8259.c的init_IRQ ()函数中): set_intr_gate(ox20, interrupt[0]); /*在IDT的第0x20个表项中插入一个中断门。这个门中的段选择符设置成内核代码段的选择符,偏移域设置成0号中断处理程序的入口地址。*/ outb_p(0x34,0x43); /* 写计数器0的控制字:工作方式2*/ outb_p(LATCH & 0xff , 0x40); /* 写计数初值LSB 计数初值低位字 节*/ outb(LATCH >> 8 , 0x40); /* 写计数初值MSB 计数初值高位字节*/ LATCH(英文意思为:锁存器,即其中锁存了计数器0的初值)为计数器0的计数初值,在/include/linux/timex.h中定义如下:

#define CLOCK_TICK_RATE 1193180 /* 图5.3中的输入脉冲 */ #define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* 计数器0的计数初值 */ CLOCK_TICK_RATE是整个8253的输入脉冲,如图5.3中所示为1.193180MHz,是近似为1MHz的方波信号,8253内部的三个计数器都对这个时钟进行计数,进而产生不同的输出信号,用于不同的用途。 HZ表示计数器0的频率,也就是时钟中断或系统时钟的频率,在 /include/asm/param.h中定义如下: #define HZ 100 2.与时钟中断相关的函数 下面我们看时钟中断触发的服务程序,该程序代码比较复杂,分布在不同的源文件中,主要包括如下函数: 时钟中断程序:timer_interrupt( ); 中断服务通用例程do_timer_interrupt(); 时钟函数:do_timer( ); 中断安装程序:setup_irq( ); 中断返回函数:ret_from_intr( ); 前三个函数的调用关系如下: timer_interrupt( ) do_timer_interrupt()

08实验八 Linux环境下的中断实验

实验八 Linux环境下的中断实验 一、实验目的 1、了解中断的原理,加深对中断向量表的理解。 2、理解系统是如何响应外部中断的。 3、学习设置中断,注册中断以及清除中断等函数的使用。 二、实验内容 1、编写程序实现Linux下的外部中断; 2、编写Makefile生成可执行文件; 3、验证中断功能。 三、实验设备 1、硬件: PC机; DM2410实验系统; 串口线; 机对机网线; 2、软件: PC机操作系统(WINDOWS2000,REDHATLinux并使用KDE界面); Linux下ARMGCC交叉编译环境; 实验系统附带文件; 四、预备知识 1、了解Linux操作系统的原理; 2、掌握Linux操作系统的使用; 3、掌握实验一和实验二的内容。 五、基础知识 中断概念 1、基本定义 计算机系统的“中断”是指中央处理器CPU正在处理某件事情的时候,发生了异常事件(如定时器溢出等),产生一个中断请求信号,请求CPU迅速去处理。CPU暂时中断当前的工作,转入处理所发生的事件,处理完以后,再回到原来被中断的地方继续原来的工作,这样的过程称为中断,实现这种功能的部件称为中断系统,产生中断的部件或设备称为中断源。 一个计算机系统一般有多个中断请求源。当多个中断源同时向CPU请求中断时,就存在CPU优先响应哪一个中断请求源的问题。一般根据中断源(所发生的事件)的轻重缓急,规定中断源的优先级,CPU优先响应中断优先级高的中断源请求。 当CPU正在处理一个中断请求时,又发生了另外的中断请求,如果CPU能暂时中止对原中断的处理,转去处理优先级更高的中断请求,待处理完以后,再继续处理原来的中断事件,这样的过程称为中断嵌套。这样的中断系统称为多级中断系统。而没有中断嵌套功能的系统称为单级中断系统。 2、中断向量 每个中断都可以用一个无符号整数来标识,称之为“中断向量(Interrupt Vector)”。所有的ARM系统都有一张中断向量表,当出现中断需要处理时,必须调用向量表。向量表一般要位于0地址处。

linux内核--中断处理程序

linux内核--中断处理程序 https://www.doczj.com/doc/013343309.html,/linux-unix/1440113.html一个设备的中断处理程序是它设备驱动程序的一部分--设备驱动程序是用于对设备进行管理的内核代码。中断处理程序与其他内核函数的真正区别在于,中断处理程序是被内核调用来响应中断的,而它们运行于我们称之为中断上下文的特殊上下文中。中断与定时器:中断的概念:指CPU在执行过程中,出现某些突发事件急待处理,CPU暂停执行当前程序,转去处理突发事件,处理完后CPU又返回原程序被中断的位置继续执行中断的分类:内部中断和外部中断内部中断:中断源来自CPU内部(软件中断指令、溢出、触发错误等)外部中断:中断源来自CPU外部,由外设提出请求屏蔽中断和不可屏蔽中断:可屏蔽中断:可以通过屏蔽字被屏蔽,屏蔽后,该中断不再得到响应不可屏蔽中断:不能被屏蔽向量中断和非向量中断:向量中断: CPU通常为不同的中断分配不同的中断号,当检测到某中断号的中断到来后,就自动跳转到与该中断号对应的地址执行非向量中断:多个中断共享一个入口地址。进入该入口地址后再通过软件判断中断标志来识别具体哪个是中断也就是说向量中断由软件提供中断服务程序入口地址,非向量中断由软件提供中断入口地址/*典型的非向量中断首先会判断中断源,然后调用不同中断源的中断处理

程序*/irq_handler(){...int int_src = read_int_status();/*读硬件 的中断相关寄存器*/switch(int_src){//判断中断标志case DEV_A:dev_a_handler();break;case DEV_B:dev_b_handler();break;...default:break;}...}定时器中断原理:定时器在硬件上也以来中断,PIT(可编程间隔定时器)接收一个时钟输入,当时钟脉冲到来时,将目前计数值增1并与已经设置的计数值比较,若相等,证明计数周期满,产生定时器中断,并复位计数值。如下图所示:Linux中断处理程序架构:Linux将中断分为:顶半部(top half)和底半部(bottom half)顶半部: 完成尽可能少的比较紧急的功能,它往往只是简单的读取寄存器中的中断状态并清除中断标志后就进行“登记中断”(也就是将底半部处理程序挂在到设备的底半部执行队列中)的工作特点:响应速度快底半部: 中断处理的大部分工作都在底半部,它几乎做了中断处理程序的所有事情。特点:处理相对来说不是非常紧急的事件小知识:Linux中查看/proc/interrupts文件可以获得系统中断的 统计信息。如下图所示:第一列是中断号第二列是向CPU产生该中断的次数介绍完相关基础概念后,让我们一起来探讨一下Linux中断编程Linux中断编程:内核维护了一个中断信号线的注册表,该注册表类似于I/O端口的注册表。驱动模块在使用中断前要先请求一个中断通道(或者中断请求IRQ),然后在使用后释放该通道。在头文件

Windows&Linux中断、异常处理机制分析

一、引言 处理器的速度跟外围硬件设备的速度往往不在一个数量级上,因此,如果内核采取让处理器向硬件发出一个请求,然后专门等待回应的办法,显然差强人意。既然硬件的响应这么慢,那么内核就应该在此期间处理其他事务,等到硬件真正完成了请求的操作之后,再回过头来对它进行处理。想要实现这种功能,轮询(polling)可能会是一种解决办法。可以让内核定期对设备的状态进行查询,然后做出相应的处理。不过这种方法很可能会让内核做不少无用功,因为无论硬件设备是正在忙碌着完成任务还是已经大功告成,轮询总会周期性地重复执行。更好的办法是由我们来提供一种机制,让硬件在需要的时候再向内核发出信号(变内核主动为硬件主动),这就是中断机制。 众所周知,在C++中有着较为完善的异常处理机制,同样在C语言中也有很不错的异常处理机制来支持,另外在其它许多现代编程语言中,也都有各自的异常处理编程机制,如Ada语言等。但我们更应该知道这些编程语言所提供的异常处理机制的实现,都是建立在操作系统中所提供的异常处理机制之上,如Windows平台上的VC编译器所实现的C++异常处理模型,它就是建立在SEH机制之上的。如果没有采用这种方式,比如Linux操作系统上的gcc就没有采用到操作系统中所提供的异常处理机制,这样就会有一个很大的缺点,那就是对于应用程序的开发者而言,它不能够很好在自己的应用程序中,来有效控制操作系统中所出现的一些意外的系统异常,例如程序执行过程中可能出现的段错误,被零除等计算异常,以及其它许多不同类型的系统异常等。所以Linux操作系统上的gcc编译的程序中,它只能捕获程序中,曾经被自己显式地抛出来的异常,而对于系统异常,catch block则毫无办法。 因此,操作系统平台中所提供的中断、异常处理机制是非常有必要的。它除了能够帮助开发人员发现和解决软件中的错误外,还被广泛应用于软件保护技术、软件漏洞利用等方面。因此,深入研究中断、异常处理机制的原理和实现以扩展其应用的范围是有必要的。 二、中断处理方式 Ⅰ、WINDOWS系统的中断处理方式 Windows内核对于中断使用了陷阱派发机制,它使用中断陷阱处理器来响应设备的中断,中断陷阱处理器或者将控制权给负责处理中断的外部例程(中断服务程序,ISR),或者传递给一个响应该中断的内部内核例程。设备驱动程序提供了ISR来处理设备中断,内核为其他类型的中断提供了ISR。 Windows的中断主要有硬件中断和软件中断,通过Windows核心我们可以禁止软件中断和硬件中断。软件中断主要引发对线程的调度以及以异步方式打断一个线程执行的机制。而硬件中断主要是为了实现处理器和设备并行工作。对于硬件中断,Windows 将硬件中断转化为能够触发执行的驻留在不同虚拟机中的ISR(中断服务程序)事件,这是一个较好的中断处理方法。下面我们来讨论一下Windows 系统的硬件终端处理机制。 在Windows系统下,处理器可以在不同的状态(V86、实模式和保护模式)下运行。当DOS运行时,则处理器运行V86模式。当Windows 执行时或当DOS VM已经切换进保护模式时,处理器则运行Ring3保护模式。当VMM(虚拟机管理器)或VXD (虚拟设备驱动程序)执行时,处理器则运行在Ring0 保护模式。在Windows系统环境中,Windows将所有的IDT入口指向VMM 中的一个函数。VMM会判断出来自

相关主题
文本预览
相关文档 最新文档