中断处理函数所作的第一件事情是什么?
答案是屏蔽中断,所以要屏蔽中断,是因为新的中断会再次调用中断处理函数,导致原来中断处理现场的破坏。因为中断,它是把原来的上下文都存起来,如果是多级中断的话,它需要存多级的上下文,除非Linux能存多级上下文,感觉是能多存的。如果只能存一级,那必然是要屏蔽中断,不然上下文就会覆盖丢失。
另外,既然屏蔽了,就会有新的问题->中断丢失,解决方法就是将中断函数与中断接收区分开,中断函数另开一个线程做,那么中断接收马上返回,这样就不会中断丢失(否则你的中断请求多频繁啊?那不可能)这样是多线程机才会实现对不对,Linux就是多线程的。或者怎么说呢,我们把系统和其他函数叫做主进程,中断处理叫做中断进程。
我们再仔细了解一下内核运行原理吧:我们确定这里就一个CPU,每次只能执行一条汇编代码,那么,内核就是一个由interrupt驱动的程序。那么一个用户程序运行的时候,Linux就在内存里呆着,等着一个中断的到来(往往是程序的一个时间片,或者其他中断)。在这个中断的处理过程中,来做“调度”。
有个ID号为0的进程,循环调用puase()函数,这个函数可以让CPU休息,调用电源管理,给 CPU降频。而puase()又会调用schedule()函数,就是休息的时候也不忘警惕,schedule()函数会检查是否有能用的进程,有就调度,没有就又返回,然后再puase()。0 号进程并不负责调度其它进程。它也会调用 scheduler。而且 scheduler 还可以被时钟中断调起的。
Linux中断下半部处理有三种方式:软中断、tasklet、工作队列。
中断处理过程。中断接收在屏蔽中断的情况下完成;中断处理在时能中断的情况下完成,这部分被称为中断下半部。作为一个操作系统显然不能任由每个中断都各自为政,统一管理是必须的。
软中断用轮询的方式处理。假如正好是最后一种中断,则必须循环完所有的中断类型,才能最终执行对应的处理函数。显然当年开发人员为了保证轮询的效率,于是限制中断个数为32个。随着中断数的不停增加,软中断不够用了,为了提高中断处理数量,顺道改进处理效率,于是产生了tasklet机制。Tasklet采用无差别的队列机制,有中断时才执行,免去了循环查表之苦。
由于中断程序是串行执行,因此只要有一个处理时间较长,则会导致其他中断响应的延迟。为了能并行处理中断,于是出现了工作队列。工作队列是一组内核线程。多个中断可以放在一个线程中,也可以每个中断分配一个线程。
Linux内核的主要组件有:系统调用接口、进程管理、内存管理、虚拟文件系统、网络堆栈、设备驱动程序、硬件架构的相关代码。
由于中断会打断内核中进程的正常调度运行,所以要求中断服务程序尽可能的短小精悍;但是在实际系统中,当中断到来时,要完成工作往往进行大量的耗时处理。因此期望让中断处理程序运行得快,并想让它完成的工作量多,这两个目标相互制约,诞生——顶/底半部机制。这种设计可以使系统处于中断屏蔽状态的时间尽可能的短,以此来提高系统的响应能力。顶半部只有中断处理程序机制,而底半部的实现有软中断,tasklet和工作队列实现。
软中断作为下半部机制的代表,是随着SMP(share memory processor)的出现应运而生的,它也是tasklet实现的基础(tasklet实际上只是在软中断的基础上添加了一定的机制)。软中断一般是“可延迟函数”的总称,有时候也包括了tasklet(请读者在遇到的时候根据上下文推断是否包含tasklet)。它的出现就是因为要满足上面所提出的上半部和下半部的区别,使得对时间不敏感的任务延后执行,软中断执行中断处理程序留给它去完成的剩余任务,而且可以在多个CPU上并行执行,使得总的系统效率可以更高。
软中断用轮询的方式处理。可能就是,每隔一段时间,32个项都要查一遍,而tasklet维护了一个队列,只查第一个就行,而工作队列由于有多个线程,可以一次查好几个。
可延迟函数运行在中断上下文中,则它们不可挂起,也就是说软中断不能睡眠、不能阻塞,原因是由于中断上下文出于内核态,没有进程切换,所以如果软中断一旦睡眠或者阻塞,将无法退出这种状态,导致内核会整个僵死。工作队列则能运行在进程上下文,它将工作给一个内核线程,作为中断守护线程来使用。多个中断可以放在一个线程中,也可以每个中断分配一个线程。我们用结构体workqueue_struct表示工作者线程,工作者线程是用内核线程实现的。而工作者线程是如何执行被推后的工作——有这样一个链表,它由结构体work_struct组成,而这个work_struct则描述了一个工作,一旦这个工作被执行完,相应的work_struct对象就从链表上移去,当链表上不再有对象时,工作者线程就会继续休眠。
软中断和tasklet运行在中断上下文,工作队列运行在进程上下文。如果需要休眠则选择工作队列,否则选择tasklet;如果对性能要求较高则选择软中断。