kernel中断 linux_linux kernel 中断 - CSDN
精华内容
参与话题
  • Kernel中断处理模型

    2011-04-08 10:34:00
    Kernel中断处理模型 Kernel中断处理模型 内核版本: Linux 2.6.18_pro500 (Montavista) Kernel中断处理模型结构图如下:

    Kernel中断处理模型

     
     

    Kernel中断处理模型

    内核版本: Linux 2.6.18_pro500 (Montavista)

    Kernel中断处理模型结构图如下:

    clip_image001

    下面简单介绍一下:

    1. Linux定义了名字为irq_desc的中断例程描述符表:(include/linux/irq.h)

    struct irqdesc irq_desc[NR_IRQS];

    NR_IRQS表示中断源的数目。

    2. irq_desc[]是一个指向irq_desc_t结构的数组, irq_desc_t结构是各个设备中断服务例程的描述符。Irq_desc_t结构体中的成员action指向该中断号对应的irqaction结构体链表。Irqaction结构体定义如下:

    /* include/linux/interrupt.h */
    struct irqaction {
        irq_handler_t handler; /* 指向中断服务程序 */
    unsigned long flags; /* 中断标志 */
    unsigned long mask; /* 中断掩码 */
    const char *name; /* I/O设备名
        void *dev_id;            /* 设备标识 */
    struct irqaction *next; /* 指向下一个描述符 */
    int irq; /* IRQ线 */
    struct proc_dir_entry *dir; /* 指向IRQn相关的/proc/irq/n目录的描述符 */
    };

    其中关键的handler成员指向了该设备的中断服务程序,由执行request_irq时建立。

    3. 在驱动程序初始化时,若使用到中断,通常调用函数request_irq()建立该驱动程序对应的irqaction结构体,并把它登记到irq_desc [irq_num]->action链表中。Iqr_num为驱动程序申请的中断号。

    request_irq()函数的原型如下:

    /* kernel/irq/manage.c */
    int request_irq(unsigned int irq,
            irqreturn_t (*handler)(int, void *, struct pt_regs *),
    unsigned long irqflags,
            const char *devname,
            void *dev_id);

    参数irq是设备中断求号,在向irq_desc []数组登记时,它做为数组的下标。把中断号为irq的irqaction结构体的首地址写入irq_desc [irq]->action。这样就把设备的中断请求号与该设备的中断服务例程irqaction联系在一起了。

    这样当CPU接收到中断请求后,就可以根据中断号通过irq_desc []找到该设备的中断服务程序。流程如上图所示。

    4. 关于共享中断

    共享中断的不同设备的iqraction结构体都会添加进该中断号对应的irq_desc结构体的action成员所指向的irqaction链表内。当内核发生中断时,它会依次调用该链表内所有的handler函数。因此,若驱动程序需要使用共享中断机制,其中断处理函数必须有能力识别是否是自己的硬件产生了中断。通常是通过读取该硬件设备提供的中断flag标志位进行判断。

    展开全文
  • http://www.wowotech.net/linux_kenrel/irq-domain.html
    展开全文
  • Kernel 中断处理图 1. Linux 定义了名字为irq_desc 的中断例程描述符表:(include/linux/irq.h)  struct irqdesc irq_desc[NR_IRQS]; NR_IRQS 表示中断源的数目。 include/asm/irq.h中定义了各中断号...

    Kernel 中断处理图


    1. Linux 定义了名字为irq_desc 的中断例程描述符表:(include/linux/irq.h)

        struct irqdesc irq_desc[NR_IRQS];

    NR_IRQS 表示中断源的数目。 include/asm/irq.h中定义了各中断号。

    2. irq_desc []是一个指向irq_desc_t 结构的数组, irq_desc_t 结构是各个设备中断服务例程的描述符。Irq_desc_t 结构体中的成员action 指向该中断号对应的irqaction 结构体链表。Irqaction 结构体定义如下:

    /* include/linux/interrupt.h */ 
    struct irqaction { 
         irq_handler_t handler;    /* 指向中断服务程序 */ 
        unsigned long flags;     /* 中断标志 */ 
        unsigned long mask;      /* 中断掩码 */ 
        const char * name;         
     /* I/O设备名
         void *dev_id;             /* 设备标识 */
     
        struct irqaction * next; /* 指向下一个描述符 */ 
        int irq;                  /* IRQ线 */ 
        struct proc_dir_entry * dir; /* 指向IRQn相关的/proc/irq/n目录的描述符 */ 
    } ;

       其中关键的handler 成员指向了该设备的中断服务程序,由执行request_irq 时建立。

     

    3. 在驱动程序初始化时,若使用到中断,通常调用函数 request_irq ()建立该驱动程序对应的 irqaction结构体,并把它登记到 irq_desc [irq_num]->action 链表中。 Iqr_num 为驱动程序申请的中断号。

    request_irq ()函数的原型如下:

    /* kernel/irq/manage.c */ 
    int request_irq( unsigned int irq, 
             irqreturn_t ( * handler) ( int , void * , struct pt_regs * ) , 
            unsigned long irqflags, 
            const char * devname, 
            void * dev_id) ;

     

    参数 irq 是设备中断求号,在向 irq_desc [] 数组登记时,它做为数组的下标。把中断号为 irq 的irqaction 结构体的首地址写入 irq_desc [irq]->action 。这样就把设备的中断请求号与该设备的中断服务例程 irqaction 联系在一起了。

    这样当 CPU 接收到中断请求后,就可以根据中断号通过 irq_desc [] 找到该设备的中断服务程序。流程如上图所示。

     

    4. 关于共享中断

    共享中断的不同设备的 iqraction 结构体都会添加进该中断号对应的 irq_desc 结构体的 action 成员所指向的 irqaction 链表内。当内核发生中断时,它会依次调用该链表内所有的 handler 函数。因此,若驱动程序需要使用共享中断机制,其中断处理函数必须有能力识别是否是自己的硬件产生了中断。通常是通过读取该硬件设备提供的中断 flag 标志位进行判断。

    展开全文
  • Linux kernel 学习之中断

    千次阅读 2012-02-22 22:13:55
    以前学习计算机组成原理的时候就知道了硬件如果要和cpu进行通信有那么几种方法,其实有程序查询法,中断,DMA,通道等,就记得那么多了,我记得好像还有一个。那个时候书上很形象的把这个过程比作是老师分苹果的故事...


             以前学习计算机组成原理的时候就知道了硬件如果要和cpu进行通信有那么几种方法,其实有程序查询法,中断,DMA,通道等,就记得那么多了,我记得好像还有一个。那个时候书上很形象的把这个过程比作是老师分苹果的故事。程序查询法就是老师每一个小孩子都去问,他们的苹果有没有吃完了,想想这也是一件比较累的事情。中断就比较智能了,就是当小孩子自己吃完了苹果,如果还想要的话就自己去想老师要。DMA好像是老师把这个权利给了一个孩子,如果有人要苹果的时候,这个时候老师就叫一个小孩子过来,说接下来的事情就交给你了,你帮我分苹果,但是还是必须要和我说一下的,但是苹果是你去分。通道好像就是老师这个职位对于分苹果已经不管了,有一个专门的一个人来管理这个事情。不过没有一种方法可以解决所有的问题,因为有的硬件与cpu通信数据量比较大,可以选择是DMA和通道,但是如果硬件本身是一个低速的设备,使用通道和DMA可以说是一种资源的浪费,而这个时候中断也就是最好的解决的方式。你有需要才来告诉我,而不是我(cpu)一直去询问你。这是一种从被动到主动的过程。这样cpu就不用花大量的时间周期去查询你有没有要处理的请求。这样解放了cpu,使cpu有更多的时间去处理它要做的事情。

            首先,中断的过程其实很简单,比如键盘这个中断过程就是,当键盘被按下了,那么就会产生一个电信号(可以认为中断就是一个电信号),这个信号会传到中断控制器,然后中断控制器在上报到cpu,cpu收到这个请求的时候就会中断自己当前的事情来出来出来键盘的输入。其实这是一个很简单的过程。虽然过程很简单,但是操作系统本身要做可没有想象中的那么简单,因为很多东西都是那么容易让人混淆的。

    接下来就对Linux kernel对中断的实现来了解一下中断吧!!!

    1.中断的分类:

    中断可以分为同步中断异步中断,当然我现在要讲述的是异步中断。同步中断其实就是异常,当cpu来执行代码的时候,由于碰到了不能定义的指令(除以0)的时候,就中断当前的指令去处理这些异常。为什么称之为同步中断,因为它是与时钟是同步的,如果理解的简单的话同步中断是软件引起的,而异步中断是硬件引起的。

    2.异步中断:

    一台计算机有很多硬件设备,有在计算机外的,也有在计算机里面的,那么多的外设,cpu到底是怎么样去区别中断是哪个外设产生的,如果同样的外设有很多台,那么又怎么去区别呢?os中给某一种的中断都设定了中断值(IRQ,中断请求线),中断值是唯一的。但是中断值却不是固定不变的,因为计算机永远也不知道他到底要连接多少的外设,所以一些中断值是固定的,但是一些却是动态生成的。

    与中断有关的不单单只是设备,还有中断处理程序(ISR)。中断处理程序与特定的中断连接在一起,而且中断处理程序本身是硬件驱动中的一个部分。不同的硬件设备对中断处理程序都有不同的要求。当硬件本身插入计算机的时候,驱动程序就开始运行,这个时候有一部分工作就是去注册中断处理程序,那样当硬件发出中断的时候,os可以调用这个中断处理程序。

    3.关于中断处理函数

    中断处理函数本身与普通的函数其实也没有什么区别,不过只是它必须按特别的类型去声明。其中最大的区别在于在运行的时候环境上的差别吧,中断处理程序运行在中断上下文中的,而普通的函数是运行在进程上下文中的。关于进程上下文和中断上下文我本身也不是很能理解,书上讲的不是特别好理解。

    关于中断上半部和中断下半部的问题:

    为什么要分为中断上半部和下半部呢?本来也不知道的我,看了书以后我也渐渐的明白了,这可以在编写中断处理程序一个很重要的一点,这也是与普通函数的一个区别。

    1.中断程序程序会打断cpu的执行,而让cpu去执行你的处理程序,那如果处理程序要运行很长时间的话你觉得合理不??如果不是很能明白的话,举个例子就是:别人在讲话,然后你突然打断他的话,然后自己在那里讲了很久很久,你说对方是什么感觉,而且说不定他正在讲很重要的事情,对于人是这样,那么对于cpu本身也是一样的。

    2.中断处理程序的运行一定会伴随了中断请求线的屏蔽,好的话是同一个类的中断请求线屏蔽,最坏就是把当前本地所有的中断请求线全部屏蔽掉。这样的话有可能会妨碍到一些中断的中断处理程序。

    3.中断面向的是硬件的,而有的硬件本身就是高速的,也就是说本身也是有时间的限制的,如果处理的慢的话就可能导致后面的数据被更加后面的数据给覆盖了。网卡就是这样的。


    所以中断处理程序要分为两个过程。上半部必须是快速,简单的,要完成的任务通常也就是给予硬件一个响应,说我已经收到了,你可以继续工作去了。还有就是关于一些数据的复制,以便到下半部进行处理。

    注册中断处理函数

    int request_irq(unsigned int irq, 
    		irqreturn_t (*handler)(int, void *, struct pt_regs *),
    		unsigned long irqflags, 
    		const char * devname,
    		void *dev_id)
    request_irq是用来注册中断处理程序的,是驱动程序中的一部分。

    irq        :中断请求线

    handler:真正的中断处理程序

    irqflags:默认是0,不过可以通过 ‘|’进行多个重合。

    SA_INTERRUPT:快速中断请求,意思就是如果标识了这个的中断,在处理中断的时候会屏蔽一切中断,默认的情况是会屏蔽那个正在运行中断处理程序的中断请求线。

    SA_SAMPLE_RANDOM:这个标识主要是把两个中断产生的之间间断放到随机熵中去而已。

    SA_SHIRQ:看字面意思就是share irq,也就是共享中断请求线。至于怎么去区别当然是有解决方法的。

    devname:设备的名字。想看的话可以去/proc/irq或者/proc/interrupt下面找找看。

    dev_id    :这个就是用来区分的那个值了。如果不是共享的irq的话,这个值通常为NULL。可是如果是共享的IRQ的话这个值就不能是NULL。因为同一条irq上怎么样达到区分不同的中断的效果呢,同样的IRQ值,这个值通常包含了设备的一些信息,可以用来区分不同的设备。对于共享IRQ,发现中断的时候,操作系统会依次调用这个线上的所有的中断处理程序,根据中断处理程序也知道是不是应该这个中断处理程序来负责这个中断。

    request_irq会睡眠所以它不能放在中断上下文或者那种不能被阻断的程序中。


    释放中断处理程序

    void free_irq(unsigned int irq, void *dev_id)
    如果指定的irq不是共享的话,那么free_irq就会删除中断处理程序,并且会禁止这条irq。如果是共享的IRQ,那么free_irq就只会删除中断处理程序。只有当线上的所有的处理程序全部都删除了这irq才会被禁止掉的。

     真正的中断处理程序(handler)


    static irqreturn_t intr_handler(int irq , void *dev_id, struct pt_regs *regs)
    os通过这个函数的返回值来区别是不是有这个处理函数来处理这个中断。使用static这个关键词主要是为了防止别的文件调用中断处理程序。

    进程上下文和中断上下文

    这两个术语其实我并不是很清楚,但是对于书上的解释我也想提出自己不是很懂的地方。

    进程上下文是一种内核所处的操作模式,此时内核是代表这进程执行的。在进程上下文中可以通过current宏关联到当前的进程。因为进程以进程上下文的形式连接到内核中的,所以可以在进程上下文可以睡眠,或者调用调度程序。

    中断上下文:中断上下文和当前进程没任何的关系,与current宏也没有关系(尽管它还会指向中断的进程)。因为进程没有背景,所以中断处理程序是不能睡眠的。这也对中断处理程序中使用的函数做出了限制了。

    不明白就是了,唯一知道的就是进程上下文可以睡眠或者调度,但是中断上下文是不能被中断的。这里的中断上下文是指中断上半部的那个时间,下半部的话就不一定了。


    4.中断处理机制的实现

    在开头的时候就大概说明了中断产生到处理的过程,不过那个很简单。那么Linux本身对这个过程具体是怎么实现的呢???

        步骤:

    1.当中断发生,如果cpu没有禁止相应的中断线的,那么cpu会立即去响应这个中断。它会跳到一个os规定的内存地址,然后开始执行那边的代码。这段代码完成的主要是把IRQ号保存到栈中,然后保存当前的寄存器的值(这个值包含了中断的任务)。

    2.调用do_IRQ()
    int irq = regs.orig_eax & 0xff; /* high bits used in ret_from_ code  */
    	irq_desc_t *desc = irq_desc + irq;
    
            int handle_IRQ_event(unsigned int irq,
    	struct pt_regs *regs, struct irqaction *action)
    {
    	int status = 1;	/* Force the "do bottom halves" bit */
    	int retval = 0;
    
    	if (!(action->flags & SA_INTERRUPT))
    		local_irq_enable();
    
    	do {
    		status |= action->flags;
    		retval |= action->handler(irq, action->dev_id, regs);
    		action = action->next;
    	} while (action);
    	if (status & SA_SAMPLE_RANDOM)
    		add_interrupt_randomness(irq);
    	local_irq_disable();
    	return retval;
    }

    上面的两句话主要是用来取得IRQ值的,这个实现是x86的,不同的体系结构实现是有点区别的。通过得知IRQ值然后通过偏移就可以得知在这个IRQ上有哪些中断处理程序,这样就可以对这些程序进行测试了。
    handle_IRQ_event这个函数是do_IRQ中调用的,而且也完成了do_IRQ中的大部分的功能。首先,如果这个中断没有标志SA_INTERRPUT的话,那么就把中断打开。这也就说在do_IRQ中的时候,函数已经把所有的中断都禁止了。在handle_IRQ_event最后的时候还是把所有的中断给禁止了,这让记起了以前在学习计算机组成原理的时候关于中断的,里面好像有讲过在中断开始的时候,也就是保存现场的时候是禁止所有的中断的,而且在最后恢复中断的时候也是禁止中断的。
    这个函数的第二个部分就是那个循环。这样可以通过循环来对这个IRQ线上的所有的中断处理程序进行测试,如果是的话就执行,如果不是就返回,也不执行。

    3.ret_from_intr()函数
    经过handle_IRQ_event这个函数,如果中断处理程序是配套的话就开始执行,执行完成以后返回到ret_from_intr,这是一个使用汇编写的函数。主要是用来判断是否要进行调度。

    5.总结

    这是关于中断上半部的一些知识点,都是书上看的然后在自己总结的。关于中断下半部准备再过几天在写,这文章写了3个小时,真是有点麻烦的说。



    展开全文
  • 在前面介绍中,我们知道如何对软中断的简单初始化,软中断需要触发,然后软中断处理函数才能被执行:   内核提供__raise_softirq_irqoff()类函数对指定的软中设置标志位。与此相关的函数还有:   raise_softirq_...
  • Linux内核中断机制(一):中断注册方法

    千次阅读 2016-12-27 22:00:29
    linux 内核中用于申请中断的函数是 request_irq(),函数原型在Kernel/irq/manage.c 中定义: int request_irq(unsigned int irq, irq_handler_t handler, unsigned long irqflags, c
  • Linux kernel中断子系统之(六):ARM中断处理过程 作者:linuxer 发布于:2014-8-4 19:26 分类:Linux内核分析 一、前言 本文主要以ARM体系结构下的中断处理为例,讲述整个中断处理过程中的硬件行为和软件...
  •  这里就行了很深入的讨论,值得一看: ... 但是,他们的讨论最后没有得出一个明确的结论。其中, cskyrain在8楼 的思考触及到了一个要点,但是没有深入展开...一直认为中断处理函数不能休眠的是天经地义的,可从没
  • kernel 中断详解

    千次阅读 2012-06-16 21:32:26
    外部设备遇到某一事件发出一个IRQ中断中断控制器,中断控制器对这个IRQ进行硬件上的处理,把一些信息记在中断控制器的寄存器上,然后中断控制器通过IRQ中断线给ARM发一个信号。ARM收到信号,开始进行以下处理:  ...
  • 一个系统中,中断是很重要的组成部分之一,有了中断,系统才可以不用一直轮询(polling)是否有事件发生,系统效率才得以提高,而且对中断的控制又通常分散在各个地方,不同的部分由不同功能的程序控制,做到了...
  • linux性能速查-中断

    千次阅读 2019-04-08 10:31:36
    linux系列博客为自己速查问题而写,比较乱,仅供参考,如有问题,请参考权威书籍或文档,谢谢。 中断是一种处理硬件设备请求的机制,它会打断正常的进程调度和执行,通过调用中断处理程序来响应硬件请求。它还是...
  • linux内核分析--中断的分类

    千次阅读 2014-04-12 15:22:42
    什么是中断 Linux 内核需要对连接到计算机上的所有硬件设备进行管理,毫无疑问这是它的份内事。如果要管理这些设备,首先得和它们互相通信才行,一般有两种方案可实现这种功能: 轮询(polling) 让内核定期对设备...
  • arm中断概念在《ARM体系结构与编程》第9章中说到,ARM 中有个概念叫做“异常中断”,也就是包括外部中断在内的各种异常。显然,ARM体系的“异常中断”概念更加接近MIPS体系中的“异常”概念。 既然更类似MIPS体系...
  • 嵌入式Linux的GPIO中断

    千次阅读 2019-05-29 15:13:06
    做个STM32开发的都知道,通过程序配置让普通的GPIO口具有中断功能。这样对于设备检测某些硬件的自动设备要方便的多。那么在嵌入式的Linux是否具有这样的功能呢?答案是肯定的,下面我们就来介绍一下如何配置嵌入式...
  • 本文用到的缩写词汇: SVC:Supervisor(SVC) Hyp:Hypervisor(Hyp) PC:Program Counter (PC) CPSR:Current Program Status Register (CPSR) SPSRs:Saved Program Status Registers (SPSRs) ...
  • 这3部分是怎么相互协作来构成这个系统的呢? 各自有什么用呢? 三者有什么联系?...下面是笔者针对网上bootloader、linuxkernellinux内核)、rootfile(根文件系统),三者关系的一个总结   1.LINUX中b...
  • Linux 中断处理流程

    2019-03-20 21:09:08
    前言 流程
  • 1、SGI中断(核间通信中断) 在gicv2/gicv3中,SGI中断中断号0-15)是software generate interrupt,用户核间中断。 我们一般将0-7划分给linux中使用,8-15给TEE使用。在smp.c定义了linux中使用的SGI中断kernel/...
  • linux kernel中断子系统之(七):GIC代码分析 作者:linuxer 发布于:2014-9-4 19:59 分类:Linux内核分析 一、前言 GIC(Generic Interrupt Controller)是ARM公司提供的一个通用的中断控制器,其...
1 2 3 4 5 ... 20
收藏数 68,101
精华内容 27,240
关键字:

kernel中断 linux