当前位置:首页 > Linux内核中断管理和延迟函数(BH)
Linux Interrupt Management
}; IPI_RESCHEDULE, IPI_CALL_FUNC, IPI_CALL_FUNC_SINGLE, IPI_CPU_STOP, January 1, 2013
发送IPI使用如下函数:
void send_ipi_message(const struct cpumask *mask, enum ipi_msg_type msg) 1.8 MSI和MSI-X中断
MSI全称Message Signaled Interrupt。当设备向一个特殊地址写入时,会向CPU产生一个中断,即也MSI中断。
MSI能力最初在PCI 2.2里定义,在PCI 3.0里被强化,使得每个中断都可以单独控制。PCI 3.0还引入了MSI-X能力,相比MSI,每个设备可以支持更多的中断,并且可以独立配置。设备可以同时支持MSI和MSI-X,但同一时刻只能使能其中一种。
1.8.1 为什么使用MSI
与传统引脚中断相比,有三个方面的优势。
基于引脚的PCI中断经常在几个设备间共享,内核必须调用与该中断相关的每一个中断处理函数,降低了效率。MSI不是共享的,所以不存在这个问题。
当设备向内存写入数据,然后发起引脚中断时,有可能在CPU收到中断时,数据还未到达内存(在PCI-PCI桥后的设备更有可能如此)。为了保证数据已达 内存,中断处理程序必须轮询产生该中断的设备的一个寄存器,PCI事务保序规则会确保所有数据到达内存后,寄存器才会返回值。
使用MSI时,产生中断的写不能越过数据写,因而避免了这个问题。当中断产生时,驱动可以确信所有数据已经到达内存。
PCI的每个功能设备只支持一个基于引脚的中断,驱动常常需要查询设备来确定发生的事件,降低了中断处理的效率。通过MSI,一个设备可以支持多个中断,这样可以为不同的使用不同的中断。比如:
1. 给不常发生的事件(如错误)指定独立的中断,这样驱动可以正常中断路径进行更有效的处理。
2. 给网卡的每个报文队列或者存储控制器的每个端口分配中断。
44
Linux Interrupt Management January 1, 2013
1.8.2 如何使用MSI
PCI设备初始化为使用基于引脚的中断,设备驱动需要将设备配置为使用MSI或MSI-X。不是所有的设备可以完整支持MSI,下面有些API就直接返回失败,因此仍然使用基于引脚的中断。
1.8.3 内核提供MSI支持
内核需要配置CONFIG_PCI_MSI以支持MSI或者MSI-X,该配置是否可以配置受架构和其它一些配置的影响。
大部分工作在PCI层的驱动里完成,只需要请求PCI层为设备设置MSI能力即可。
int pci_enable_msi(struct pci_dev *dev) int pci_enable_msi_block(struct pci_dev *dev, int count) void pci_disable_msi(struct pci_dev *dev) 1.8.4 MSI-X
MSI-X能力比MSI更为灵活,它支持2048个中断,每个中断都可以单独控制。要支持这种能力,驱动必须使用结构数组struct msix_entry。
int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec) void pci_disable_msix(struct pci_dev *dev) 1.9 典型的中断处理方式实例
/* intrpt.c - An interrupt handler. * * Copyright (C) 2001 by Peter Jay Salzman */ /* The necessary header files */ /* Standard in kernel modules */ #include
Linux Interrupt Management January 1, 2013
/* We want an interrupt */ #include
Linux Interrupt Management January 1, 2013
* such as us, we have to disable it (free its IRQ) before we do * anything. Since we don't know where it is, there's no way to * reinstate it later - so the computer will have to be rebooted * when we're done. */ free_irq(1, NULL); /* Request IRQ 1, the keyboard IRQ, to go to our irq_handler. * SA_SHIRQ means we're willing to have othe handlers on this IRQ. * SA_INTERRUPT can be used to make the handler into a fast interrupt. */ return request_irq(1, /* The number of the keyboard IRQ on PCs */ irq_handler, /* our handler */ SA_SHIRQ, \} /* Cleanup */ void cleanup_module() { /* This is only here for completeness. It's totally irrelevant, since * we don't have a way to restore the normal keyboard interrupt so the * computer is completely useless and has to be rebooted. */ free_irq(1, NULL); } 2 可延迟函数
2.1 软中断 - BH(Bottom Half) 2.1.1 实现
软中断是利用硬件中断的概念,用软件方式进行模拟,实现宏观上的异步执行效果。很多情况下,软中断和\信号\有些类似,同时,软中断又是和硬中断相对应的,\硬中断是外部设备对CPU的中断\,\软中断通常是硬中断服务程序对内核的中断\,\信号则是由内核(或其他进程)对某个进程的中断\。
软中断是静态分配的; tasklet也是一个软中断,在它上面的函数的分配和初始化可以动态进行。
可延迟函数基本操作:初始化、激活、屏蔽、执行 Linux 2.6 使用的软中断:
/*他们的优先级递减(即由软中断编码决定)*/ enum { HI_SOFTIRQ=0, 47
共分享92篇相关文档