1. 什么是中断
  简单来说中断就是硬件设备与处理器的一种交流方式,比如当我按下一个键时,只有当处理器知道我按下了这个键并且做出相应的处理时,按键这个操作才是有效的。我们知道处理器的速度远远高于外围设备的速度,处理器与外设选择合适的交流方式就格外重要。轮询是一种方式,这种方式是内核周期性地对设备状态进行查询并作出相应的的动作,但这种方式会让内核做大量的无用功,这显然是不明智的。更好的方式是让外设在其需要的时候向内核发送信号,这就是中断机制。
  
  2.中断处理程序
  当一个中断发生时,内核应该有相应的处理方法,这个方法就是中断处理程序,一个中断处理程序对应一个中断号。中断处理程序是管理硬件的驱动程序的一部分,如果设备需要中断,相应的设备驱动程序就需注册中断处理程序。注册方式:使用request_irq()函数
  
 - int
- request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),unsigned long irqflags, const char * devname, void *dev_id)
  函数参数: 
 irq:表示要分配的中断号 
 handler:函数指针,指向中断的实际中断处理函数 
 irqflags:中断处理程序的标志,举例来说: IRQF_DISABLED被设置后内核在处理中断处理程序本身期间要禁止所有的其他中断。 
 devname:与中断相关的设备的ASCII文本表示 
 dev_id:用于共享中断线,当一个中断处理程序需要释放时,dev_id提供唯一的标志信息。
  
  3.中断服务例程
  一条中断线对应一个中断一个中断处理程序,而多个设备可能共享一条中断线,那么如何让中断处理程序为不同的设备提供不同的处理方法。这就引出了中断服务例程。一个中断处理程序对应若干个中断服务例程。
  中断处理程序就相当于某个中断向量的总的处理程序,比如IRQ0x09_interrupt()是中断号为9的总处理程序,假如这个9号中断由5个设备共享,那么这5个设备都分别有其对应的中断服务例程。也就是说当有多个设备需要共享某个中断线时,中断处理程序必须要调用ISR,此时会调用handle_IRQ_event()
  
  4.request_irq函数分析
  
 - int
- request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
-      unsigned long irqflags, const char * devname, void *dev_id)
- {
-  int retval;
-  struct irqaction * action;
-  if (irq >= ACTUAL_NR_IRQS)  //中断号是否超过最大值
-   return -EINVAL;
-  if (!handler)  //函数指针是否为空
-   return -EINVAL;
- #if 1
-  /*
-   * Sanity-check: shared interrupts should REALLY pass in
-   * a real dev-ID, otherwise we'll have trouble later trying
-   * to figure out which interrupt is which (messes up the
-   * interrupt freeing logic etc).
-   */
-  if ((irqflags & SA_SHIRQ) && !dev_id) {       //若中断共享但dev_id为NULL则出错
-   printk(KERN_ERR
-          "Bad boy: %s (at %p) called us without a dev_id!\n",
-          devname, __builtin_return_address(0));
-  }
- #endif
-  action = (struct irqaction *)
-    kmalloc(sizeof(struct irqaction), GFP_KERNEL);   //创建irqaction结构体
-  if (!action)
-   return -ENOMEM;
-  action->handler = handler;  //将函数参数传给结构体
-  action->flags = irqflags;
-  cpus_clear(action->mask);
-  action->name = devname;
-  action->next = NULL;
-  action->dev_id = dev_id;
- #ifdef CONFIG_SMP
-  select_smp_affinity(irq);
- #endif
-  retval = setup_irq(irq, action); //注册中断irqaction结构体
-  if (retval)
-   kfree(action);
-  return retval;
- }
  
 - struct irqaction {
-     irqreturn_t (*handler)(int, void *, struct pt_regs *);//具体的中断服务例程
-     unsigned long flags;//一组中断标志
-     cpumask_t mask;
-     const char *name;//中断设备名称
-     void *dev_id;指定设备的主设备号和次设备号
-     struct irqaction *next;//指向共享中断线的下一个 irqaction结构体
-     int irq;//申请的中断号
-     struct proc_dir_entry *dir;
- };