网络设备的中断处理

我们这里描述的是硬件中断。 

设备和内核之间的交互有两种方法。 

1 polling(轮询) 

也就是kernel来操作交互,由kernel来检测某一个状态,看是否需要让设备做什么。 

2 interrupt(中断) 

设备来发起交互,设备发出一个硬件中断请求给kernel当他需要kernel的注意时。 


当中断来的时候被调用的函数称为interrupt handler,他必须通过设备的驱动来安装。当一个设备驱动注册一个NIC(Network Interface Card),他请求并标记了一个IRQ,然后他为这个中断请求注册一个回调函数. 

其中注册回调函数与remove回调函数用下面的两个方法。 

Java代码   收藏代码
  1. int request_irq(unsigned int irq,  
  2.         irq_handler_t handler,  
  3.         unsigned long irqflags, const char * devname, void *dev_id)  
  4.   
  5. void free_irq(unsigned int irq, void *dev_id)  


irq也就是中断请求号,handler就是中断抵达时的回调函数。irqflags是中断的类型,比如IRQF_SHARED(中断共享)等。dev_id也就是设备注册时的id。 

NIC的中断的发生一般有下面的几种类型。 

1 互联网帧的到达,也就是NIC接到数据。 

2 传输失败。体现在用户层就是超时,等等。。 

3 DMA传输成功完成。 

比如有数据,通过DMA传递给NIC,由于DMA是异步的,因此设备驱动必须等待从NIC的一个显式的中断。 

4 设备有足够的内存处理一个新的传输。 

当egress queue没有足够的空间,也就是无法放入一帧时,NIC的驱动会关闭掉传输,并要求NIC当有比给定的内存更大的内存时发出一个中断,然后当中断来的时候会重新打开传输。 

这里看一个例子: 

3c509.c中的hard_start_xmit方法 

Java代码   收藏代码
  1. netif_stop_queue (dev);  
  2.   
  3. .................  
  4. if (inw(ioaddr + TX_FREE) > 1536)  
  5.         netif_start_queue(dev);  
  6.     else  
  7.         /* Interrupt us when the FIFO has room for max-sized packet. */  
  8.         outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);  


这里只摘要了主要的代码,第一行停止了设备的传输队列,然后监测是否设备有足够的空间存放一帧(1536字节).如果有的话打开传输队列,否则指示设备当有足够空间的时候产生一个中断(使用outw来操作寄存器).当中断来的时候会调用netif_start_queue. 


共享中断 

共享中断也就是一个中断请求号关联了多个中断处理函数,当没一个设备注册中断请求号时候传递的参数声明是否这个中断能被共享。 

接下来看下中断的数据结构: 


Java代码   收藏代码
  1. struct irq_desc {  
  2.     irq_flow_handler_t  handle_irq;  
  3.     struct irq_chip     *chip;  
  4.     struct msi_desc     *msi_desc;  
  5.     void            *handler_data;  
  6.     void            *chip_data;  
  7.     struct irqaction    *action;    /* IRQ action list */  
  8.     unsigned int        status;     /* IRQ status */  
  9.   
  10.     unsigned int        depth;      /* nested irq disables */  
  11.     unsigned int        wake_depth; /* nested wake enables */  
  12.     unsigned int        irq_count;  /* For detecting broken IRQs */  
  13.     unsigned int        irqs_unhandled;  
  14.     unsigned long       last_unhandled; /* Aging timer for unhandled count */  
  15.     spinlock_t      lock;  
  16. #ifdef CONFIG_SMP  
  17.     cpumask_t       affinity;  
  18.     unsigned int        cpu;  
  19. #endif  
  20. #if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE)  
  21.     cpumask_t       pending_mask;  
  22. #endif  
  23. #ifdef CONFIG_PROC_FS  
  24.     struct proc_dir_entry   *dir;  
  25. #endif  
  26.     const char      *name;  
  27. }  


irq_desc 代表中断的描述符(他是全局的)而且是与平台相关的,因此我们可以看到不同的平台实现了自己的中断处理的相关函数,而中断的处理函数是包含在action中的,其中如果action多于一个元素,就代表这个irq是共享irq。 

Java代码   收藏代码
  1. struct irqaction {  
  2.     irq_handler_t handler; ///中断处理函数  
  3.     unsigned long flags;  
  4.     cpumask_t mask;  
  5.     const char *name;  
  6.     void *dev_id;  
  7.     struct irqaction *next; ///链表的指针  
  8.     int irq; ///中断号  
  9.     struct proc_dir_entry *dir;  
  10. };  


下面的图很好的显示了irq_desc的结构。 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值