linux中断控制之总章
来源:互联网 发布:校园网网络波动大 编辑:程序博客网 时间:2024/04/28 23:19
程序运行期间,遇到某些特殊情况,需要CPU暂停当前正在执行的程序,转去处理突发事件,处理完后又返回原程序被中断的位置继续运行,这种情况就是中断。
中断源:引起中断的原因或发出中断请求的设备
中断服务程序:要处理的突发事件程序
中断的分类:
1.来源
硬中断(外部中断):通过外部设备接口,向CPU的中断请求引脚INT和NMI发中断请求产生
软中断(内部中断):CPU内部执行中断指令,或由运算溢出,TF(Trap Falg,每执行一条指令,自动产生一个内部中断去执行一个中断服务程序)标志而产生
2.可否能屏蔽
可屏蔽中断(INT)
不可屏蔽中断(NMI)
3.入口跳转
向量中断:不同的中断分配不同的中断号,有不同的入口地址,硬件提供
非向量中断:多个中断共享一个入口地址,再通过中断标志识别具体哪个中断,软件提供
中断程序架构
linux中断程序不一定要分为顶半部(tophalf)和底半部(bottom half),通常为什么要分呢?
因为中断处理程序是在关掉其他所有中断的情况下进行,执行于硬件相关的处理要求快,而有些驱动在中断处理程序中又需要完成大量的工作,这就矛盾了。这需要在这两者间找到一个平衡点,所以分解为两个部分。
顶半部的功能是“登记中断”。顶半部尽可能快的完成比较急的功能,往往只是简单的读取寄存器中的中断状态并清除中断标志后进行“登记中断”即中断例程的底半部挂到该设备的底半部执行队列中去。这样顶半部执行的速度很快,能服务更多的中断请求。
底半部来完成中断事件的绝大多数使命。
顶半部与底半部最大的不同是,底半部是可中断的,顶半部不可中断。
顶半部机制
申请和释放中断函数request_irq() 和 free_irq()
int request_irq(unsigned int irq,
irq_handler_t handler,unsigned long irqflags,const char * devname,void *dev_id);
irq是要申请的硬件中断号。handler是向系统登记的中断处理函数。这是一个回调函数,中断发生时,系统调用这个函数,传入的参数包括硬件中断号,device id,寄存器值。dev_id就是下面的request_irq时传递给系统的参数dev_id。irqflags是中断处理的一些属性。比较重要的有标明中断处理程序是快速处理程序(设置IRQF_DISABLED)还是慢速处理程序(不设置IRQF_DISABLED)。快速处理程序被调用时屏蔽所有中断。慢速处理程序不屏蔽。还有一个IRQF_SHARED属性,设置了以后运行多个设备共享中断。dev_id在中断共享时会用到。一般设置为这个设备的 device结构本身或者NULL。
中断处理程序可以用dev_id找到相应的控制这个中断的设备,或者用irq2dev_map找到中断对应的设备。
void free_irq(unsigned int irq,void *dev_id);
使能和屏蔽中断
void disable_irq(int irq)
void disable_irq_nosync(int irq)
void enable_irq(int irq)
disable_irq()和disable_irq_nosync()的区别在于,后者立即返回,而且前者等待目前的中断处理完成。
如果enable_irq()函数会引起系统死锁,这种情况下,只能使用disable_irq_nosync()
local_irq_save(flags)
local_irq_restore(flags)
注意:保存的是数值,不是指针,因为flags是unsigned long类型,所以这对中断函数要在同一个函数中使用
底半部机制
linux实现底半部的机制主要有软中断,工作队列,tasklet。
软中断:
1.软中断是在编译期间静态分配的
2.最多可以有32个软中断
3.软中断不会抢占另外一个软中断,唯一可以抢占软中断的是中断处理程序
4.可以并发运行在多个CPU上(即使同一类型的也可以)。所以软中断必须设计为可重入的函数(允许多个CPU同时操作),因此也需要使用自旋锁来保护其数据结构
5.目前只有两个子系直接使用软中断:网络和SCSI
6.执行时间有:从硬件中断代码返回时、在ksoftirqd内核线程中和某些显示检查并执行软中断的代码中
tasklet:
1.tasklet是使用两类软中断实现的:HI_SOFTIRQ和TASKLET_SOFTIRQ
2.可以动态增加减少,没有数量限制
3.同一类tasklet不能并发执行
4.不同类型可以并发执行
5.大部分情况使用tasklet
工作队列:
1.由内核线程去执行,换句话说总在进程上下文执行
2.可以睡眠,阻塞
tasklet会在很短的时间内很快执行,并且以原子模式执行,而工作队列函数可以具有更长的延迟并且不必原子化
用例:
void my_tasklet_func(unsigned long); //定义一个处理函数:
DECLARE_TASKLET(my_tasklet,my_tasklet_func,data); //定义一个tasklet结构my_tasklet,与my_tasklet_func(data)函数相关联
……
tasklet_schedule(&my_tasklet); //调度tasklet
在linux中,可以查看系统中中断的统计信息
[wang@localhost kernel]$ cat /proc/interrupts
CPU0
0: 1238 IO-APIC-edge timer
1: 76229 IO-APIC-edge i8042
3: 8 IO-APIC-edge
4: 115306 IO-APIC-edge
7: 0 IO-APIC-edge parport0
8: 20 IO-APIC-edge rtc0
9: 0 IO-APIC-fasteoi acpi
12: 696238 IO-APIC-edge i8042
14: 0 IO-APIC-edge ata_piix
15: 2532908 IO-APIC-edge ata_piix
16: 348132 IO-APIC-fasteoi Ensoniq AudioPCI
17: 359979 IO-APIC-fasteoi ehci_hcd:usb1, ioc0
18: 248 IO-APIC-fasteoi uhci_hcd:usb2
19: 2183 IO-APIC-fasteoi vmxnet ether
……
NMI: 0 Non-maskable interrupts
LOC: 20587881 Local timer interrupts
RES: 0 Rescheduling interrupts
CAL: 0 Function call interrupts
TLB: 0 TLB shootdowns
TRM: 0 Thermal event interrupts
SPU: 0 Spurious interrupts
ERR: 0
MIS: 0
- linux中断控制之总章
- linux并发控制之总章
- linux并发控制之总章
- linux进程调度之总章:一些片汤话
- linux中断控制之软中断
- linux中断控制之tasklet
- linux并发控制之中断屏蔽
- linux中断控制之工作队列
- linux并发控制之中断屏蔽
- linux并发控制之中断屏蔽
- 总章
- Eclipse重构之总章
- S3C2440之中断控制
- qnx之中断控制
- linux中断之中断注册
- linux中断之中断注册
- 中断控制之工作队列
- DSP 之中断控制(Interrupt)
- Socket 通信(Linux)
- DXperience Winforms12.2版的中文使用手册
- 自然语言也支持泛型
- 我在互联网创业失败的启思录(十四) –--敢梦想,敢追寻
- .net页面定时刷新的几种简单方式
- linux中断控制之总章
- socket编程之addrinfo结构体与getaddrinfo函数
- 一个及其简单的卸载linux的方法
- 如何搭建android开发环境
- 安装qc后配置连接DB2
- iOS运行回路(RunLoop)总结
- jquery+.net 实现动态瀑布流
- MYSQL数据文件--.frm文件(表结构恢复)
- 图像分割之(四)OpenCV的GrabCut函数使用和源码解读