Linux中断处理过程浅析

合集下载

完整的中断处理过程的教学探讨

完整的中断处理过程的教学探讨

完整的中断处理过程的教学探讨作者:黄涛来源:《城市建设理论研究》2012年第31期摘要:计算机系统对意外事件的处理是通过中断技术来实现。

对一具体中断事件的处理划分为中断响应、中断服务及中断返回三个过程,在专业教学中学生对此很容易理解,但对中断系统在操作系统中的组织、具体处理过程及过程间的衔接常常感到不解,本文以Linux系统为例作了较了详细的介绍。

关键词:中断中断向量中断描述符中图分类号:G424.21 文献标识码:A 文章编号:在i386中根据CPU和中断源间的时序关系,将中断分为同步中断和异步中断两大类。

同步中断称为异常(Exception),是指CPU执行指令时所产生的中断;异步中断称为中断(Interrupt),是指由I/O设备随机产生的中断。

异常和中断在操作系统中没有本质上的差异,二者间的差异主要在于中断向量的形成方式不同。

中断系统的软硬件组织:1、中断系统的硬件组织现代计算机中中断硬件系统是由I/O设备、中断控制器及CPU组成的三级层次结构。

逻辑结构如下所示:中断控制器的主要功能是将I/O设备的IRQ中断请求信号转换为CPU的中断请求信号;向CPU提供I/O设备的中断向量以找到中断服务程序。

在现代微机中一般采用8259A芯片。

2、Linux系统中断的软件组织(1)中断向量每一个异常和中断都有一个唯一的编号,称为中断向量,在Linux中使用0~255之间的无符号整数来表示。

在Linux中具体分配如下:0~31用于异常和不可屏蔽中断;32~47用于可屏蔽中断;48~255用于软中断。

(2)中断描述符中断描述符主要用来反映中断向量与中断服务程序间的对应关系。

中断描述符共占用8个字节,其格式如下:15~0位偏移量15~0位选择器0 0 0 字计数 P DPL 0 类型31~16位偏移量其中:字计数表示参数数量,5位;P是存在位;DPL是描述符特权级,2位;类型占用4位,共有任务门、调用门、中断门、陷阱门四种。

Linux中request_irq()中断申请与处理说明

Linux中request_irq()中断申请与处理说明

Linux中request_irq()中断申请与处理说明1、中断的理解中断你可以理解为就是⼀种电信号,是由硬件设备产⽣的然后发送给处理器,处理器接收到中断后,就会马上向操作系统反映此信号,之后就是系统的⼯作了。

这⾥有两个注意的地⽅,第⼀中断是随时都可以产⽣,意味着中断的处理程序随时都可以执⾏,所以得保证中断处理程序能够快速执⾏,才可能尽快的恢复中断代码执⾏,所以中断代码尽量简短。

第⼆每⼀个中断都有⾃⼰唯⼀的数字标记,这样操作系统才能对症下药2、注册中断中断处理程序中断处理程序是管理硬件的驱动程序的组成部分,每⼀设备都有相关的驱动程序,驱动程序可以通过request_irq()函数注册⼀个中断处理程序,并且激活给定的中断线,来处理指定的中断,原型如下:int request_irq(unsigned int irq,irq_handler_t handler,unsigned long flags, const char *devname, void *dev_id)第⼀个参数irq表⽰要分配的中断号,就我⽬前所接触的都是预先已经预定好的,还没试着通过探测或者动态来确定中断号第⼆个参数handler是⼀个指针,指向处理这个中断的实际中断处理程序,只要操作系统⼀接收到中断,该函数就被调⽤,这个函数稍后讨论第三个参数flags中断处理程序的标志,这个标志可以是⼀个也可以是多个,列举⼏个最重要的标志:IRQF_DISABLED: 该标志被设置后,意味内核在处理中断处理程序本⾝的时候,禁⽌了其他所有的中断。

如果不设置,中断处理程序可以与除本⾝之外的其他任何中断同时运⾏。

显⽽易见我们⼀般不去这么野蛮的设置这个标志IRQF_TIMER:为系统定时器的中断处理⽽准备的IRQF_SHARED:这个中断标志经常能遇见,这个标志意思就是多个中断处理程序之间可以共享中断线,概括起来就是没有这个标志就只能独⾃⼀个⼈占⽤,标志了,就是很多⼈可以占⽤这个中断号来第四个才参数就是⾃定义与中断设备相关的⽂本了第五个参数dev,看到第三个参数中IRQF_SHARED时候,你会不会有这样的疑问,假如现在我要释放当前共享的指定这个中断程序时候,我如何释放?会不会把其他占⽤也会删除掉,这就是第五个参数的意义,如果中断线是共享的,那么就必须传递能够代表当前设备的唯⼀信息request_irq()成功返回0,如果返回⾮0,就表⽰有错误发⽣,这个时候你可以考虑当前中断是否被占⽤了,所以可以加上IRQF_SHARED标志3、中断处理程序这⾥延续上⾯的handler指针,原型如下:Static irqreturn_t intr_handler(int irq, void *dev)这⾥唠叨⼀下,不知道⼤家⾯试时候有没有遇到像这样的题⽬__interrupt double compute_area (double radius){double area = PI * radius * radius;printf(" Area = %f", area);return area;},指出上⾯中断函数出现的错误,不知道的就认真看下⾯的 O(∩_∩)O第⼀个参数irq就是这个处理程序要响应的中断号,这个我认为现在没有多⼤意义了,因为上⾯有讲述到第五个参数的意义第⼆个参数dev是⼀个通⽤的指针,同样的,还是将上⾯讲述到的第五个参数拿过来理解。

Linux中断处理流程

Linux中断处理流程

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内核中断处理流程

x86 linux内核中断处理流程

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操作系统是一种开源的、自由的、类Unix操作系统,它的内核是由Linus Torvalds和全球志愿者团队开发的。

Linux内核的一个重要功能是处理中断,它可以使操作系统在执行某个任务时,直接响应外部的事件,如键盘输入、网络数据传输等。

本文将详细介绍Linux操作系统处理中断的过程。

1. 中断的概念中断是指计算机在执行某个任务时,被外部事件所打断,暂停当前任务的执行,转而去处理其他任务的一种机制。

中断可以分为硬件中断和软件中断两种。

硬件中断是指计算机硬件设备发出的中断信号,如键盘、鼠标、网络接口卡等。

当硬件设备发出中断信号时,CPU会暂停当前任务的执行,跳转到中断服务程序中去执行处理,处理完中断后再返回原来的任务。

软件中断是指操作系统内核发出的中断信号,可以通过系统调用的方式触发,如定时器中断、系统调用等。

软件中断和硬件中断的处理方式是相同的。

2. 中断的分类根据中断的优先级,中断可以分为以下几类:① 外部中断:由硬件设备发出,如键盘输入、鼠标移动、网络数据传输等,优先级最高。

② 内部中断:由软件程序触发,如定时器中断、系统调用等,优先级次之。

③ 异常中断:由于程序执行错误或硬件故障等原因而发生的中断,优先级最低。

3. 中断的处理过程在Linux操作系统中,中断处理的过程可以分为以下几个步骤:① 中断请求:当硬件设备发出中断请求信号时,会将中断请求信号发送给中断控制器,中断控制器会将中断请求信号发送给CPU。

② 中断响应:CPU接收到中断请求信号后,会暂停当前任务的执行,跳转到中断服务程序中去执行处理。

在跳转之前,CPU会将当前任务的上下文保存到内存中,以便后续恢复任务的执行。

③ 中断处理:中断服务程序会根据中断类型进行相应的处理,如读取键盘输入、发送网络数据等。

在处理过程中,中断服务程序可以访问进程内存空间、内核内存空间等,并可以与其他设备进行交互。

10-5 Linux操作系统 - 中断、异常及系统调用

10-5 Linux操作系统 - 中断、异常及系统调用

10.5.4 中断上半部分的处理 一、 中断控制器 •每个硬件设备控制器都能通过中断请求线 发出中断请求(简称IRQ) •所有设备的中断请求线又连到中断控制器 的输入端。 •在x86单CPU的机器上采用两个8259A芯片作 为中断控制器,一主一从。
•当8259A有中断信号输入同时中断信号不被 屏蔽时,主8259A向CPU发出 INT信号,请求 中断。这时如果CPU是处于允许中断状况, CPU就会发信号给8259A进入中断响应周期。 •在对8259A芯片的初始化过程中,第n号中 断在IDT表中的向量号为 n+32
•IDT中向量号的使用情况如下: 0-31 异常与非屏蔽中断使用。 32-47 可屏蔽中断使用32至47 128(0x80)实现系统调用。 其余 未使用 •保存现场 发生异常时在核心栈的程序计数器eip的 值取决于具体情况。一般情况下eip保存的 下一条指令的地址,但对于页面异常,保存 的产生异常的这条指令的地址而不是下一条 指令的地址
中断向量表IDT •IDT是中断/异常处理在内核的入口。IDT表 项还记录了一些其它信息用以安全检查。 •IDT在系统初始化时创建。 •每个中断/异常都有一个向量号,该号的值 在0-255之间,该值是中断/异常在IDT中的 索引。 •每个中断/异常均有其相应的处理函数,中 断/异常在使用前必须在IDT中注册信息以保 证发生中断/异常时能找到相应的处理函数。
struct hw_interrupt_type { const char * typename; 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 (*end)(unsigned int irq); void (*set_affinity)(unsigned int irq, unsigned long mask); };

linux中断处理流程

linux中断处理流程

linux中断处理流程Linux中断处理流程Linux中断处理是操作系统中的一个重要组成部分,用于响应硬件设备的事件。

在Linux中,中断可以是外部中断,如硬件设备发送的中断信号,也可以是内部中断,如软件产生的异常或系统调用。

中断处理的目的是及时响应硬件设备的事件,并采取相应的措施来处理这些事件。

一、中断的触发中断是由硬件设备发送的一个信号,用于通知操作系统某个事件的发生。

这个信号可以是一个电平的变化,一个特定的数据包,或者一个指定的硬件寄存器的变化。

当硬件设备检测到某个事件发生时,它会向处理器发送一个中断信号,处理器会立即停止当前正在执行的任务,保存当前的上下文,并跳转到中断处理程序的入口点。

二、中断处理程序的执行中断处理程序是一个特殊的函数,负责处理中断事件。

当中断发生时,处理器会跳转到中断处理程序的入口点,并执行相应的代码。

中断处理程序的执行过程可以分为以下几个步骤:1. 保存上下文:在执行中断处理程序之前,处理器需要保存当前任务的上下文,包括程序计数器、寄存器和堆栈指针等。

这样可以确保在中断处理程序执行完成后,能够正确地返回到原来的任务。

2. 中断处理程序的执行:一旦保存了上下文,处理器就会执行中断处理程序的代码。

中断处理程序根据中断的类型,执行相应的操作。

例如,对于外部中断,中断处理程序可能需要读取硬件设备的状态,处理数据包或执行特定的操作。

对于内部中断,中断处理程序可能需要处理异常或系统调用。

3. 中断处理程序的结束:当中断处理程序执行完成后,处理器会恢复之前保存的上下文,并将控制权返回给原来的任务。

这样原来的任务就可以继续执行,而不会受到中断的影响。

三、中断处理的优先级在Linux中,中断处理有不同的优先级。

这是为了确保对于紧急事件的及时处理。

中断的优先级由硬件设备决定,通常是通过一个优先级编码器来实现的。

当多个中断同时发生时,处理器会按照优先级的顺序来处理中断。

高优先级的中断会立即被处理,而低优先级的中断则会被推迟到稍后处理。

linux系统中断详解

linux系统中断详解

linux系统中断详解最近为了解决风控问题,⼀直在研究linux的系统内核,经过⼀段时间的学习,先整理出⼀份关于linux中断的⼩记。

1.什么是中断?计算机cpu在执⾏task时,不可能每次都将任务执⾏完毕,会因为各种不同的场景⽽暂停执⾏,所谓中断就是这个暂停执⾏的过程。

2.中断算是⼀种错误吗?严格来说,中断当然算是运⾏错误的⼀种,但是,由于其不可避免,程序开发者⾃然可以将其视为⼀种机制,加以运⽤,反⽽更容易帮助我们完成现实功能的实现。

3.中断的分类从产⽣原因上看,中断可以分为软件中断和硬件中断,⽽从类别划分上看,也可以氛围有出错码中断和⽆出错码中断。

⼆者并不排斥,⽐如说,中断分类存在int0~int255中,其中int0 ~ int31 表⽰软件中断,int32 ~ int255: 可由⽤户⾃⼰设置。

其中int32 ~ int47 对应8259A的IRQ0 ~ IRQ15中断。

需要注意的是,int128 为系统调⽤中断(system_call)。

如果⼤家有看过内核源码或者其他汇编代码,会发现汇编语⾔在调⽤c函数时,就是使⽤system_call,由此可见,调⽤其他函数,也是⼀种中断。

这⾥不⽌局限于linux系统,其中中断逻辑囊括所有计算机逻辑执⾏逻辑,其最基础的实现逻辑就是计算机0/1与或逻辑,属于机器语⾔中最低级也是最⾼效的展现形式。

4.中断时堆栈变化情况堆栈相关知识此处不做介绍,不了解的同学可以⾃⾏查找⼀下相关资料。

上图可以⾮常清楚的展⽰中断发⽣时堆栈的变化情况。

即中断发⽣前,需要将图中的信息按照先后顺序,压⼊中断处理程序的堆栈中。

下⾯进⾏具体的分析:SS(stack segment): 堆栈段ESP(extended stack pointer): 堆栈指针EFLAGS : 状态标志寄存器CS(code segment): 代码段EIP(extended instruction pointer) : 中断后要执⾏的下⼀条指令的地址1)有/⽆出错码:我们只需知道,对于某些中断,⽐如:int0(⽆错误码)是不需要保存出错码的,⽽像int8等中断是需要保存出错码的。

中断处理流程

中断处理流程

中断处理流程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内核中断处理的irq_thread机制 -回复

linux内核中断处理的irq_thread机制 -回复

linux内核中断处理的irq_thread机制-回复Linux内核中断处理的irq_thread机制是一种处理中断请求的机制,旨在提高中断处理的效率和可扩展性。

在本文中,我们将详细介绍irq_thread 的原理和实现细节,并分析其对系统性能的影响。

一、引言随着计算机系统的发展,硬件设备的种类和数量不断增加,从而引发了对中断处理的需求。

在传统中断处理模式下,Linux内核需要通过一个叫做中断处理程序(interrupt handler)的功能模块来处理硬件设备发出的中断请求。

然而,这种模式在多核系统和高速设备的环境下往往存在性能瓶颈和可扩展性问题。

为了解决这些问题,Linux内核引入了irq_thread机制。

二、irq_thread机制的原理irq_thread机制的核心思想是将中断处理程序从内核上下文中移出,转而在用户态创建一个专门的线程来处理中断请求。

这个线程被称为irq_thread。

irq_thread在内核注册的中断向量表中占据一个特殊的槽位,当对应的硬件设备发生中断时,硬件会触发相应的中断请求,并将中断处理程序的控制权交给irq_thread。

在irq_thread的实现中,内核通过分配一个独立的线程栈和一组寄存器保存irq_thread的上下文。

同时,irq_thread中还有一个运行队列,用于保存需要处理的中断任务。

当一个中断请求到达时,irq_thread会从硬件设备读取中断状况,并将相应的中断任务放入运行队列。

三、irq_thread机制的实现细节1. 中断控制器:irq_thread机制需要硬件支持,其中关键的组件是中断控制器(interrupt controller)。

中断控制器是一种硬件设备,用于管理和分发中断请求。

在Linux内核中,主流的中断控制器有APIC(Advanced Programmable Interrupt Controller)和IOAPIC(Input/Output Advanced Programmable Interrupt Controller)等。

简述中断处理的过程

简述中断处理的过程

简述中断处理的过程
中断处理是计算机系统中非常重要的一部分。

当计算机系统收到一个中断信号时,会暂时中断当前正在执行的程序,转而执行一个特定的中断处理程序来处理中断事件。

中断处理的过程一般包括以下几个步骤:
1. 中断请求:当外部设备或其他内部事件需要处理时,会发送一个中断请求信号给中央处理器(CPU)。

这个中断请求信号会触发中断控制器,向CPU发送中断信号。

2. 中断响应:CPU接收到中断信号后,会立即停止当前正在
执行的指令,并保存当前的执行状态(包括程序计数器、寄存器状态等),以便稍后能够恢复执行。

3. 中断处理程序调用:CPU根据中断信号的种类和优先级,
选择相应的中断处理程序。

中断处理程序是预先定义好的一段代码,用来处理特定的中断事件。

4. 中断处理程序执行:CPU跳转到相应的中断处理程序,开
始执行具体的中断处理操作。

中断处理程序可能需要和外部设备进行交互,或者处理一些必要的操作,例如保存当前上下文、保存中断源的信息等。

5. 中断处理完成:中断处理程序执行完毕后,CPU会恢复之
前保存的执行状态,包括程序计数器、寄存器状态等。

然后,CPU继续执行被中断的程序,从中断之前的位置继续执行。

需要注意的是,中断处理过程中可能还包括一些其他的操作,例如中断屏蔽、中断优先级处理等,以保证系统能够正确处理多个中断事件。

同时,不同的操作系统和硬件平台可能会有一些差异,但是大致的处理流程是相似的。

linux 软中断原理

linux 软中断原理

linux 软中断原理Linux软中断是操作系统中一种用于处理紧急任务的机制。

它采用的是一种特殊的中断方式,可以在用户态和内核态之间切换,以提供高效的中断处理能力。

在Linux内核中,软中断是一种特殊的中断处理机制。

相比硬中断,软中断的处理过程更加高效,可以在短时间内完成中断处理,并且不会占用过多的系统资源。

软中断的原理是通过将中断处理函数放入一个队列中,然后由内核线程负责依次执行队列中的中断处理函数。

在Linux内核中,每个软中断都有一个唯一的标识符,并且有一个对应的中断处理函数。

当某个软中断被触发时,中断处理函数会被调用。

这样,操作系统就可以根据不同的软中断来执行相应的中断处理操作。

软中断的使用可以提高系统的响应速度和处理能力。

在Linux内核中,有一些常用的软中断,如定时器中断、网络中断等。

这些软中断可以及时地处理系统中的紧急任务,并且不会对系统的正常运行产生太大的影响。

软中断的原理是基于内核线程的机制实现的。

在Linux内核中,有一个特殊的内核线程,称为软中断处理线程。

这个线程会不断地检查软中断队列,如果队列中有待处理的中断,就会调用相应的中断处理函数。

软中断的实现需要考虑到多核处理器的情况。

在多核处理器中,每个CPU核心都有自己的软中断处理队列和软中断处理线程。

这样,每个CPU核心都可以独立地处理软中断,提高系统的并发处理能力。

软中断的使用可以提高系统的可靠性和稳定性。

在Linux内核中,软中断可以用于处理系统中的紧急任务,如定时器中断、网络中断等。

这些紧急任务需要及时地处理,以保证系统的正常运行。

Linux软中断是一种高效的中断处理机制,可以提高系统的响应速度和处理能力。

它通过将中断处理函数放入一个队列中,然后由专门的内核线程负责执行,可以及时地处理系统中的紧急任务,并且不会对系统的正常运行产生太大的影响。

通过软中断的使用,可以提高系统的可靠性和稳定性,保证系统的正常运行。

简述中断处理的过程

简述中断处理的过程

简述中断处理的过程中断是计算机系统中常见的一种机制,用于处理外部事件或错误条件。

当系统遇到需要立即处理的事件时,会触发中断,暂停当前任务的执行,转而执行中断处理程序。

中断处理的过程可以概括为以下几个步骤:1. 中断触发中断可以由外部设备发出,如键盘输入、鼠标移动等;也可以由内部事件引发,如除零错误、内存溢出等。

无论何种情况,一旦中断事件发生,计算机系统就会暂停当前任务的执行,转而处理中断。

2. 保存现场在开始执行中断处理程序之前,系统需要保存当前任务的执行状态,以便在处理完中断后能够恢复到原来的状态。

这包括保存当前的程序计数器值、寄存器状态、堆栈指针等信息。

3. 中断向量表计算机系统通常会预先定义一张中断向量表,其中记录了每种中断类型对应的中断处理程序的入口地址。

当中断发生时,系统根据中断类型查找中断向量表,找到对应的中断处理程序的入口地址。

4. 中断处理程序的执行系统根据中断向量表中找到的入口地址,开始执行对应的中断处理程序。

中断处理程序是预先编写好的一段代码,用于处理特定的中断事件。

它可以读取输入设备的数据、更新相关状态、进行必要的计算等操作。

5. 中断处理程序的结束一旦中断处理程序执行完毕,系统需要恢复之前保存的执行状态。

这包括恢复原来的程序计数器值、寄存器状态、堆栈指针等信息。

6. 重新执行原任务当中断处理程序结束后,系统回到原来的任务继续执行。

由于中断的处理是在一个独立的上下文中进行的,所以原任务的执行状态不会受到中断的影响,可以无缝地继续执行。

在中断处理的过程中,需要注意以下几点:1. 中断处理程序的设计需要高效且可靠。

由于中断可能会频繁发生,所以中断处理程序的执行时间应尽可能短,以免影响其他任务的执行。

同时,中断处理程序要能够正确地处理中断事件,并根据需要进行必要的操作。

2. 中断处理程序需要与操作系统和硬件设备紧密配合。

操作系统负责管理中断的注册和分发,硬件设备负责产生中断信号。

linux共享中断处理程序,一种Linux下共享中断的处理方法

linux共享中断处理程序,一种Linux下共享中断的处理方法

linux共享中断处理程序,⼀种Linux下共享中断的处理⽅法前段时间调试⼀款芯⽚的时候,碰到⼀个奇怪的问题:只要在板卡上插⼊⼀个PS2键盘,启动内核时系统就可能会进⼊串⼝中断函数去执⾏,过⼀会系统就panic不往下继续执⾏。

后来经过分析出现问题时的panic的堆栈,借助EJTAG⼯具,读到这个时候的串⼝的中断状态位,竟然发现串⼝并没有真正产⽣中断。

那么,串⼝本⾝没有中断,内核怎么⼜会跑到串⼝的中断服务函数去执⾏呢?我们知道Linux的中断可以分为I/O 中断 、时钟中断和处理器核间中断。

其中I/O中断是Linux 系统响应外部IO事件的重要⽅式。

尽管不同的平台和体系结构实现的⽅法不⼀样,但是都⽀持不同的设备共享同⼀个中断向量 。

例如在PCI的总线结构中,⼏个设备可以共享同⼀个IRQ线,也即它们共享⼀个中断号,各⾃的中断服务例程挂在这个中断号上。

当CPU响应这个IRQ时,会逐⼀检查挂在这个中断向量上的例程,并且执⾏那些真正有中断的例程。

但是串⼝明显不属于PCI,不可能⽤到PCI的中断线和中断引脚寄存器,那⼜是什么原因导致kernel panic呢?带着上⾯的这些问题,和硬件⼯程师和芯⽚设计的同事深⼊讨论了各种可能性,最后结合芯⽚板卡原理图,发现这个板⼦上的低速设备都集成在芯⽚内部,这些低速设备包括串⼝、LPC只是控制器、SPI控制、I2C控制器、NAND控制器等,其中CPU UART和LPC的中断信号都路由到同⼀个CPU的中断引脚。

具体的连接图如下所显:通过上图最左侧的部分可以看到,CPU UART和CPU LPC控制器的中断请求信号经过逻辑或后,输出到了CPU 芯⽚内Interrupt Pending Bit2。

⼀旦CPU检测到任何⼀个Interrupt Pending位被设置起来,它就会根据约定的顺序逐⼀查询各个Interrupt Pending Bit,并且执⾏中断路由到这个bit上的设备驱动的中断服务例程。

ARM Linux对中断的处理

ARM Linux对中断的处理
int (*set_wake)(unsigned int irq, unsigned int on);
void (*bus_lock)(unsigned int irq);
void (*bus_sync_unlock)(unsigned int irq);
/* Currently used only by UML, might disappear one day.*/
kstat_irqs: irq stats per cpu
irq_2_iommu: iommu with this irq
handle_irq:高层的irq时间处理程序(如果为NULL,则默认调用__do_IRQ())
chip:底层的中断硬件访问,指向PIC对象(irq_chip结构),它服务于IRQ线,Linux中断管理系统使用该成员来进行中断控制器的访问。
struct proc_dir_entry *dir;
#endif
const char *name;
}____cacheline_internodealigned_in_smp;
irq_desc结构体(中断描述符)中各个字段说明:
irq:中断描述符的中断号
timer_rand_state: pointer to timer rand state struct
#endif
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 */

linux内核中断处理的irq_thread机制

linux内核中断处理的irq_thread机制

Linux内核中断处理的irq_thread机制是一种将中断处理任务分配给单独线程的方法,以提高Linux内核中断处理的irq_thread机制是一种将中断处理任务分配给单独线程的方法,以提高系统的性能和响应速度。

在传统的中断处理模型中,中断处理程序(IRQ handler)是在中断发生时由内核直接调用的,这会导致CPU上下文切换,从而影响系统性能。

而使用irq_thread机制,可以将中断处理任务分配给一个专门的线程来执行,从而减少上下文切换的次数,提高系统的响应速度。

irq_thread机制的主要步骤如下:
1. 当中断发生时,内核首先将中断处理程序标记为可运行状态。

2. 然后,内核启动一个新的线程来执行这个中断处理程序。

这个线程通常被称为irq_thread。

3. irq_thread线程在执行过程中会调用do_IRQ()函数来处理实际的中断事件。

4. do_IRQ()函数会根据中断类型调用相应的硬件抽象层(HAL)中的处理函数,以完成对硬件设备的操作。

5. 最后,irq_thread线程会返回到用户空间,继续执行之前的程序。

通过使用irq_thread机制,Linux内核可以在多个处理器核心之间实现高效的中断处理,从而提高系统的整体性能。

同时,这种机制还可以简化中断处理程序的设计,使其更加模块化和易于维护。

Exynos4412中断处理流程详解

Exynos4412中断处理流程详解

Exynos4412中断处理流程详解 Linux 中,当外设触发中断后,⼤体处理流程如下: a -- 具体CPU architecture相关的模块会进⾏现场保护,然后调⽤machine driver对应的中断处理handler; b -- machine driver对应的中断处理handler中会根据硬件的信息获取HW interrupt ID,并且通过irq domain模块翻译成IRQ number; c -- 调⽤该IRQ number 对应的high level irq event handler,在这个high level的handler中,会通过和interupt controller交互,进⾏中断处理的flow control(处理中断的嵌套、抢占等),当然最终会遍历该中断描述符的IRQ action list,调⽤外设的specific handler来处理该中断; d -- 具体CPU architecture相关的模块会进⾏现场恢复; 总结下来,整个过程可以分为三部分:1、硬件处理部分;2、汇编处理部分;3、C 处理部分; 下⾯我们来追踪⼀下代码,了解当中断发⽣时,Linux 是如何处理的,前⾯的⼀些中断初始化部分就不再这⾥详述了,下⾯开始具体分析: ⼀、硬件处理部分 当⼀切准备好之后,⼀旦打开处理器的全局中断就可以处理来⾃外设的各种中断事件了。

当外设(SOC内部或者外部都可以)检测到了中断事件,就会通过interrupt requestion line上的电平或者边沿(上升沿或者下降沿或者both)通知到该外设连接到的那个中断控制器,⽽中断控制器就会在多个处理器中选择⼀个,并把该中断通过IRQ(或者FIQ,本⽂不讨论FIQ的情况)分发给该processor。

ARM处理器感知到了中断事件后,会进⾏下⾯⼀系列的动作(硬件处理部分): 1、切换处理器模式 修改 CPSR 寄存器中的 M[4:0],切换处理器模式位 IRQ Mode(这⾥M[4:0] 所添值为 10010); 2、保护现场 保存发⽣中断时,CPSR值与PC值(为恢复现场做准备);这⾥要注意,此时中断可能发⽣在 usr mode (⽤户空间),也可能发⽣在 SVC mode(内核空间); 3、mask IRQ exception 关闭IRQ中断,也就是设定CPSR.I = 1; 4、设定PC值为IRQ exception vector 实现向异常向量表的跳转,ARM处理器会跳转到IRQ的exception vector地址,到这硬件所做的⼯作就结束了,下⾯就是软件⾏为了。

IA32上Linux内核中断机制分析

IA32上Linux内核中断机制分析
426movl%esp,%eax;\
427callsmp_/**/name;\
428jmpret_from_intr;
其中,SAVE_ALL宏就是用来保存寄存器的。
内核书籍中经常提到的中断上下文,指的是内核正在运行中断服务程序或softirq,无法代表当前进程的情形。中断上下文没有自己专有的堆栈,相反,它借用被中断进程的内核堆栈──IA-32上的Linux默认这个堆栈只有8k大小,而且很可能在处理中断的过程中又被另一个中断源中断。因此如果你自己编写中断处理程序,递归层次太深或者函数局部变量太大,都有可能导致栈溢出。(i386有一个4KStacks补丁,如果编译时打开该选项,则中断上下文使用独立的栈,而不占用被中断进程的。)
2)陷阱(Trap)。陷阱处理返回时,不重新执行引发陷阱的那条指令。
3)中止(Abort)。中止是严重的异常,将导致任务的中止而不会返回。
还有一种是程序产生的异常,如INT3指令、BOUND指令等。CPU把这种异常当作是陷阱来处理。
5,中断描述表IDT
异常与中断发生时,都需要到IDT中查找相关信息,以找到对应的处理程序以及其他动作。需要注意的是,保护模式下发生权限提升时,中断穿越的是中断门,而异常穿越的是陷阱门。二者的区别是:当CPU穿越中断门时,是自动关中断的;而穿越异常门则不会。
return1;
}
spin_lock(&desc->lock);
desc->handler->ack(irq);/*给i8259A或APIC应答信号*/
/*
*REPLAYiswhenLinuxresendsanIRQthatwasdroppedearlier
*WAITINGisusedbyprobetomarkirqsthatarebeingtested

linux以太网中断处理流程

linux以太网中断处理流程

linux以太网中断处理流程English Answer:1. Interrupt Generation.The network interface controller (NIC) detects a packet arrival on the wire.The NIC issues an interrupt to the CPU.2. Interrupt Handling in the Kernel.The kernel interrupt handler is invoked.The handler identifies the source of the interrupt and handles it accordingly.For Ethernet interrupts, the kernel invokes the Ethernet driver.3. Ethernet Driver Processing.The Ethernet driver reads the packet from the NIC's receive buffer.The driver checks the packet's integrity using the checksum.If the checksum fails, the packet is dropped.4. Network Stack Processing.The driver passes the valid packet to the network stack.The network stack processes the packet based on its destination IP address.The stack routes the packet to the appropriate upper-layer protocol (e.g., TCP, UDP).5. Upper-Layer Protocol Processing.The upper-layer protocol processes the packet and generates a response if necessary.The response is passed back to the network stack.6. Packet Transmission.The network stack sends the response packet to the Ethernet driver.The driver writes the packet to the NIC's transmit buffer.The NIC sends the packet out on the wire.7. Interrupt Exit.The kernel interrupt handler returns control to the interrupted process.Chinese Answer:1. 中断生成。

linux内核中断处理流程

linux内核中断处理流程

Linux内核中断处理流程一、中断概述在计算机系统中,中断是一种重要的机制,它允许处理器暂停当前的程序执行,转而处理更为紧急的事件。

Linux内核作为操作系统的核心,负责管理和处理系统中的各种中断。

中断可以分为外中断(硬件中断)和内中断(软件中断或陷阱),它们在Linux内核中有不同的处理流程。

二、中断处理流程1. 中断请求(IRQ)的接收当中断控制器接收到一个外部设备的中断请求时,它会根据优先级等信息决定是否向CPU发送中断信号。

如果决定发送,CPU会暂停当前的执行流程,开始中断处理。

2. 中断向量的确定每个中断都有一个唯一的中断向量与之对应。

中断向量是中断处理程序的入口点。

在x86架构中,中断向量表(Interrupt Descriptor Table,IDT)存储了系统中所有中断处理程序的地址信息。

CPU根据中断向量从IDT中找到对应的中断处理程序入口。

3. 中断处理程序的执行一旦确定了中断处理程序的入口点,CPU会跳转到该程序并执行。

中断处理程序通常被称为中断服务例程(Interrupt Service Routine,ISR)。

ISR负责处理中断事件,如读取设备数据、更新系统状态等。

4. 中断上下文的保存与恢复在执行ISR之前,CPU需要保存当前执行上下文(包括寄存器状态、程序计数器等),以便在中断处理完成后能够恢复到原来的执行状态。

同样,当中断处理完成时,CPU需要恢复被中断程序的执行上下文。

5. 嵌套中断的处理在某些情况下,一个中断处理程序可能会被另一个更高优先级的中断打断。

这种情况称为嵌套中断。

Linux内核通过中断优先级管理和中断屏蔽等技术来处理嵌套中断,确保系统的稳定性和实时性。

6. 中断结束与返回当中断处理程序执行完毕时,它会通过一条特殊的指令(如iret在x86架构中)来通知CPU中断处理已完成。

CPU随后会恢复被中断程序的执行上下文,并继续执行被中断的程序。

三、软件中断(软中断)和任务调度除了硬件中断外,Linux内核还支持软件中断(Softirqs)和任务调度(Tasklets)机制。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

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_undefinstr2、arch/arm/mm/fault.c与内存访问相关的异常,总入口函数为do_DataAbort, do_PretftchAbort3. arch/arm/mm/irq.c中断处理函数在这个文件中定义,总入口函数为asm_do_IRQ4. arch/arm/kernel/call.sswi异常处理比如说:sys_read, sys_open等.5. 没有使用的异常除了IRQ中断外(FIG中断linux一般不使用),所有的异常内核都定义了细致而完备的处理函数. 所以我们这里关心的也只是上面红色部分,即:IRQ中断.Init_IRQ函数(arch/arm/kernel/irq.c),被用来初使化中断的处理框架,设置各种中断的默认处理函数.Linux内核将所有中断统一编号,使用irq_desc结构来描述中断:每个数组项对应一个中断(也可能是一组中断,它们使用共同的中断号),里面记录了中断的名称,中断状态,中断标记,并提供硬件访问函数(清除,屏蔽,使能中断),提供了这个中断的处理函数的入口,通过它可以调用用户注册的中断处理函数include/linux/irq.h{.........irq_flow_handler_t handle_irq; //当前的中断处理函数入口struct irq_chip *chip; //底层的硬件访问..........struct irqaction *action; //用户提供的中断处理函数链表unsigned int status; //IRQ状态...........const char *name; //中断名称} ____cacheline_internodealigned_in_smp;Handle_irq是这个或者这组中断的处理函数入口.当中断发生时总中断入口函数asm_do_IRQ将根据中断号调用相应irq_desc数组中的handle_irq函数,handle_irq使用chip结构中的函数来清除,屏蔽,使用中断,还会一一调用用户在action链表中注册的中断处理函数.Struct irq_chip{const char *name; //启动中断,如果不设置,缺省为"enable"unsigned int (*startup)(unsigned int irq); //启动中断,如果不设置,缺省为"enable" void (*shutdown)(unsigned int irq); //关闭中断,如果不设置,缺省为"disable"void (*enable)(unsigned int irq); //使能中断,如果不设置,缺省为unmaskvoid (*disable)(unsigned int irq); //禁止中断如果不设置,缺省为"mask"void (*ack)(unsigned int irq); //响应中断,通常是清除当前中断使得可以接收下一个中断void (*mask)(unsigned int irq); //屏蔽中断源void (*mask_ack)(unsigned int irq); //屏蔽和响应中断void (*unmask)(unsigned int irq); //开启中断源..........}struct irqaction *action; 结构类型在include/linux/interrupt..h中定义.用户注册的每一个中断处理函数都用一个irqaction结构表示,一个中断(比如共享中断)可以有多个处理函数,它们的irqacion结构链接成一个链表,以action为表头.struct irqaction {irq_handler_t handler; //用户注册的中断处理函数unsigned long flags;//中断标志,比如是否为共享中断,电平触发还是边沿触发const char *name; //用户注册的中断名字void *dev_id; //用户供给的handle参数,还可以区分共享中断struct irqaction *next;int irq; //中断号struct proc_dir_entry *dir;irq_handler_t thread_fn;struct task_struct *thread;unsigned long thread_flags;};Irq_desc结构数组中:"irq_flow_handler_thandle_irq" , "struct irq_chip *chip " , "struct ,ir qaction *action"这三种数据结构构成了中断处理体系结构.很明显,中断需要用户处理的只有最后一步,就是用户的action中断处理函数.所以我们需要告诉内核我们相应的中断处理函数在哪里,中断注册:reguest_irq, 相对应的中断卸载: free_irq.int request_irq(unsigned int irq, //中申请中断的中断号,可以根据不用的引脚到irqs.h里面查找irqreturn_t (*handler)(int, void *, struct pt_regs *),//用户写的中断处理函数unsigned long irqflags,//中断触发方式(高电平触发,低电平触发,上升沿,下降沿等)const char *devname,//中断名字(自己取名)void *dev_id); //dev_id(共享中断时,用于识别倒里是哪个硬件产生的中断)//同一中断的不同处理函数必须用dev_id来区分,//共享中断之间既可使用同一中断处理函数,也可使用不同中断处理函数,都需要dev_id区分.中断注册做了三件事:1.提供用户action中断处理函数链接2.中断触发方式是什么3.中断使能Void free_irq(unsigned int irq, //中断号与注册时对应void *dev_id) //共享中断时用于区分不同硬件与注册时对应中断卸载和注册相反:1.根据中断号irq,dev_id从action链表中找到表项,将它删除2.如果它是唯一表项,还要调用IRQ_DESC[IRQ].CHIP->SHUTDOWN或DESC[IRQ].CHIP->DISABLE来关闭中断.所以很显然,用户要自己写一个中断程序,只需要实现三步,1.向内核申请注册中断2.实现用户中断处理函数3.在不需要该中断的时候卸载中断附上一个例子:按键的中断程序驱动程序:#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/delay.h>#include <asm/irq.h>#include <linux/interrupt.h>#include <asm/uaccess.h>#include <asm/arch/regs-gpio.h>#include <asm/hardware.h>#define DEVICE_NAME "buttons" /* 加载模式后,执行”cat /proc/devices”命令看到的设备名称*/#define BUTTON_MAJOR 232 /* 主设备号*/struct button_irq_desc {unsigned long flags;char *name;};/* 用来指定按键所用的外部中断引脚及中断触发方式, 名字*/static struct button_irq_desc button_irqs [] = {{IRQ_EINT19, IRQF_TRIGGER_FALLING, "KEY1"}, /* K1 */{IRQ_EINT11, IRQF_TRIGGER_FALLING, "KEY2"}, /* K2 */{IRQ_EINT2, IRQF_TRIGGER_FALLING, "KEY3"}, /* K3 */{IRQ_EINT0, IRQF_TRIGGER_FALLING, "KEY4"}, /* K4 */};/* 按键被按下的次数(准确地说,是发生中断的次数) */static volatile int press_cnt [] = {0, 0, 0, 0};/* 等待队列:* 当没有按键被按下时,如果有进程调用s3c24xx_buttons_read函数,* 它将休眠*/static DECLARE_WAIT_QUEUE_HEAD(button_waitq);/* 中断事件标志, 中断服务程序将它置1,s3c24xx_buttons_read将它清0 */ static volatile int ev_press = 0;static irqreturn_t buttons_interrupt(int irq, void *dev_id){volatile int *press_cnt = (volatile int *)dev_id;*press_cnt = *press_cnt + 1; /* 按键计数加1 */ev_press = 1; /* 表示中断发生了*/wake_up_interruptible(&button_waitq); /* 唤醒休眠的进程*/return IRQ_RETVAL(IRQ_HANDLED);}/* 应用程序对设备文件/dev/buttons执行open(...)时,* 就会调用s3c24xx_buttons_open函数*/static int s3c24xx_buttons_open(struct inode *inode, struct file *file) {int err;for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {// 注册中断处理函数err = request_irq(button_irqs[i].irq, buttons_interrupt, button_irqs[i] .flags,button_irqs[i].name, (void *)&press_cnt[i]);if (err)break;}if (err) {// 释放已经注册的中断i--;for (; i >= 0; i--)free_irq(button_irqs[i].irq, (void *)&press_cnt[i]);return -EBUSY;}return 0;}/* 应用程序对设备文件/dev/buttons执行close(...)时,* 就会调用s3c24xx_buttons_close函数*/static int s3c24xx_buttons_close(struct inode *inode, struct file *file){int i;for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {// 释放已经注册的中断free_irq(button_irqs[i].irq, (void *)&press_cnt[i]);}return 0;}/* 应用程序对设备文件/dev/buttons执行read(...)时,* 就会调用s3c24xx_buttons_read函数*/static int s3c24xx_buttons_read(struct file *filp, char __user *buff,size_t count, loff_t *offp){unsigned long err;/* 如果ev_press等于0,休眠*/wait_event_interruptible(button_waitq, ev_press);/* 执行到这里时,ev_press等于1,将它清0 */ev_press = 0;/* 将按键状态复制给用户,并清0 */err = copy_to_user(buff, (const void *)press_cnt, min(sizeof(press_cnt), co unt));memset((void *)press_cnt, 0, sizeof(press_cnt));return err ? -EFAULT : 0;}/* 这个结构是字符设备驱动程序的核心* 当应用程序操作设备文件时所调用的open、read、write等函数,* 最终会调用这个结构中的对应函数*/static struct file_operations s3c24xx_buttons_fops = {.owner = THIS_MODULE, /* 这是一个宏,指向编译模块时自动创建的__this_module变量*/.open = s3c24xx_buttons_open,.release = s3c24xx_buttons_close,.read = s3c24xx_buttons_read,};/** 执行“insmod s3c24xx_buttons.ko”命令时就会调用这个函数*/static int __init s3c24xx_buttons_init(void){int ret;/* 注册字符设备驱动程序* 参数为主设备号、设备名字、file_operations结构;* 这样,主设备号就和具体的file_operations结构联系起来了,* 操作主设备为BUTTON_MAJOR的设备文件时,就会调用s3c24xx_buttons_fops中的相关成员函数* BUTTON_MAJOR可以设为0,表示由内核自动分配主设备号*/ret = register_chrdev(BUTTON_MAJOR, DEVICE_NAME, &s3c24xx_buttons_fops);if (ret < 0) {printk(DEVICE_NAME " can't register major number\n");return ret;}printk(DEVICE_NAME " initialized\n");return 0;}/** 执行”rmmod s3c24xx_buttons.ko”命令时就会调用这个函数*/static void __exit s3c24xx_buttons_exit(void){/* 卸载驱动程序*/unregister_chrdev(BUTTON_MAJOR, DEVICE_NAME);}/* 这两行指定驱动程序的初始化函数和卸载函数*/module_init(s3c24xx_buttons_init);module_exit(s3c24xx_buttons_exit);/* 描述驱动程序的一些信息,不是必须的*/MODULE_AUTHOR(""); // 驱动程序的作者MODULE_DESCRIPTION("S3C2410/S3C2440 BUTTON Driver"); // 一些描述信息MODULE_LICENSE("GPL"); // 遵循的协议///。

相关文档
最新文档