《Linux内核设计与实现》——中断和中断处理

一、中断

 1、中断本质上是一种特殊的电信号,由硬件设备发向处理器。处理器接收到中断后,会马上向操作系统反应此信号的到来,然后就由操作系统负责处理这些新到来的数据。


 2、不同的设备对应的中断不同,而每个中断都通过一个唯一的数字标志。这些中断值通常被称为中断请求(IRQ)线,每个IRQ线都会被关联一个数值量。



二、中断处理程序

 1、再响应一个特定中断的时候,内核会执行一个函数,该函数叫做中断处理程序或中断服务例程(ISR)。

   1)、产生中断的每个设备都有一个相应的中断处理程序。

   2)、一个设备的中断处理程序是它设备驱动程序的一部分——设备驱动程序是用于对设备进行管理的内核代码。


 2、中断处理程序与其他内核函数的真正区别在于:中断处理程序是被内核调用来响应中断的,而他们运行在中断上下文中,中断上下文也称原子上下文。



三、上半部和下半部的对比

 1、中断处理切为两个部分

   1)、中断处理程序是上半部——接收到一个中断,它就立即开始执行,但制作严格限时的工作。

   2)、能够被允许稍后完成的工作会推迟到下半部去。此后,在合适的时机,下半部会被开中断执行。



四、注册中断处理程序

 1、驱动程序可以通过requeset_irq()函数注册一个中断处理程序,并激活给定的中断线:

       int  requeset_irq(unsigned  int  irq,  irq_handler_t  handler,

                                       unsigned  long  flags,  const  char  *name,  void  *dev);

       I、参数irq表示要分配的中断号。

       II、参数handler是一个指针,指向处理这个中断的实际中断处理程序。


 2、中断处理程序标志

   1)、参数flags可以为0,也可以是一个或多个标志的位掩码。

       I、IRQF_DISABLED——该标志被设置后,意味着内核在处理程序本身期间,要禁止所有的其他中断。

       II、IRQF_SAMPLE_RANDOM——此标志表明这个设备产生的中断对内核熵池有贡献。

       III、IRQF_TIMER——此标志是特别位系统定时器的中断处理而准备的。

       IV、IRQF_SHARED——此标志表明可以在多个终端处理程序之间共享中断线。

   2)、参数name是与中断有关的的设备的ASCII文本表示。

   3)、参数dev用于共享中断线。


 3、一个中断例子


 4、释放中断处理程序

   1)、卸载驱动程序时,需要注销相应的中断处理程序,并释放中断线:

      void  free_irq(unsigned  int  irq,  void  *dev);

      I、如果指定的中断线不是共享的,那么,该函数删除处理程序的同时将禁用这条中断线。

      II、如果中断线是共享的,则仅删除dev所对应的处理程序,而这条中断线本省只有在删除了最后一个处理程序时才会被禁用。



五、编写中断处理程序

 1、一个中断处理程序声明:

       static  irqreturn_t  intr_hanler(int  irq,  void  *dev);

       I、此函数的类型与request_irq()参数中的healer所要求的参数类型匹配。

       II、第一个参数irq就是处理程序要响应的中断的中断号。

       III、第二个参数dev是一个用用指针,它与中断处理程序注册时传递给request_irq()的参数dev必须一致。

       IV、中断处理程序的返回值类型是irqreturn_t。中断处理程序可能返回两个特殊值:IRQ_NONE和IRQ_HANDLED。


 2、共享的中断处理程序

   1)、共享的处理程序与非共享的处理程序在注册和运行方式上比较相似,但差异主要有一下三处:

      I、request_irq()的参数flags必须设置IRQF_SHARED标志。

      II、对于每个注册的中断处理程序来说,dev参数必须唯一。

      III、中断处理程序必须能够区分它的设备是否产生了中断。

   2)、指定IRQF_SHARED标志以调用request_irq()时,只有在以下两种情况才能够成功:

      I、中断线当前未被注册。

      II、在该线上的所有已注册处理程序都指定了IRQF_SHARED。


 3、中断处理程序实例



六、中断上下文

 1、当执行一个中断处理程序时,内核处于中断上下文中。


 2、中断上下文具有较为严格的时间限制,因为它打断了其他的代码。中断上下文中的代码应当迅速、简洁、尽量不要使用循环去处理繁重的工作。


 3、中断处理程序栈是一个配置选项。



七、中断处理机制的实现

 1、中断处理系统在Linux中的实现非常依赖于体系结构,实现依赖于处理器、所使用的中断控制器的类型、体系结构的设计及及机器本身。


 2、中断从硬件到内核的路由(P100  图7-1)

   1)、在内核中,中断开始于预定义的入口点。对于每条中断线,处理器都会跳到对应的一个惟一的位置。

   2)、初始入口点只是在栈中保存这个号,并存放当前寄存器的值;然后,内核调用函数do_IRQ()。

           unsigend  int  do_IRQ(struct  pt_regs  regs)

   3)、pt_regs结构包含原始寄存器的值。中断的值也会得以保存,所以,do_IRQ()可以将它提取出来。

   4)、计算出中断号之后,do_IRQ()对所接收的中断进行应答,禁止这条线上的中断。

   5)、接下来,do_IRQ()需要确保在这条中断线上有一个有效的处理程序,而且这个程序已经启动,但是当前并没有执行。如是如此,do_IRQ()就调用handle_IRQ_event()来

             运行为这条中断线安装的中断处理程序。



八、/proc/interrupts

 1、procfs是一个虚拟文件系统,它只存在内核内存中,一般安装于/proc目录。在procfs中读写文件都要调用内核函数,这些函数模拟从真实文件中读写。



九、中断控制

 1、禁止和激活中断

   1)、用于禁止当前处理器上的本地中断,随后又激活它们的语句为:

       local_irq_disable();

       local_irq_enable();

       I、在X86中,local_irq_disable()仅仅是cli指令,local_irq_enable()仅仅是sti指令。cli和sti分别是对clear和set允许中断标志的会变调用。

       II、如果在调用local_irq_disable()例程之前已经禁止了中断,那么该例程往往会带来潜在的危险;同样相应的local_irq_enable()例程也存在潜在危险。

   2)、在禁止中断之前保存中断系统的状态会更加安全一些。相反,在准备激活中断时,只需要把中断恢复到他们原来的状态:

       unisgend   long  flags;

       local_irq_save(flags);

       /*  .  .  .  */

       local_irq_restore(flags);


 2、禁止指定中断

   1)、对中断状态操作之前禁止设备中断的传递。LInux提供了四个接口:

      void  disable_irq(unsigned  int  irq);

      void  disable_irq_nosync(unsigned  int  irq);

      void  enable_irq(unsigned  int  irq);

      void  synchronize_irq(unsigned  int  irq);

      I、disable_irq和disable_irq_nosync禁止中断控制器上指定的中断线,即禁止给定中断向系统所有处理器的传递。此外函数只有在当前正在执行的所有处理器程序完成

           后,disable_irq才会返回。disable_irq_nosync不会等待当前中断处理程序执行完毕。

      II、函数synchronize_irq等待一个特定的中断处理程序的退出。如果该处理程序正在执行,那么该函数必须退出之后才能返回。

      III、这些函数可以嵌套。但是记住在一条指定的中断线上,对disable_irq和disable_irq_nosync的每次调用,都需要相应的调用一次enable_irq。

      IV、以上函数可以从中断或进程上下文中调用,而且不会休眠。但是从中断上下文中调用必须注意。

   2)、禁止多个中断处理程序共享的中断时不合适的。禁止中断线也就禁止了这条线上所有设备的中断传递。


 3、中断系统的状态

   1)、irqs_disable()定义在<asm/aystem.h>中。如果本地处理器上的中断系统被禁止,则它返回非0,否则返回0。

   2)、在<linux/hardirq.h>中定义的两个宏提供一个用来检查内核的当前上下文的接口:

      in_interrupt()

      in_irq()

      I、in_interrupt:如果内核处于任何类型的中断处理中,它返回非0,说明内核此刻正在执行中断处理程序或正在执行下半部处理程序。

      II、in_irq:只有在内核确实正在执行中断处理程序时才会返回非0。

   3)、中断控制方法列表(P106  表7-2)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值