Linux内核中的活动
linux是支持多任务的操作系统,即多个应用程序可以在系统中同时运行。在多处理器环境下,执行多个应用程序的进程可以被并行处理,但进程并不是内核中能执行的唯一活动。内核中还存在几种其他形式的活动,在系统的运行股构成中起着重要作用。
进程和系统调用
什么是进程?进程(process)是一个正在执行的程序实例,各进程拥有自己独立的地址空间。进程通常在执行某个应用程序时启动,应用程序执行完成后结束。创建,空值和结束进程是操作系统内核的一项重要任务。在用户地址空间执行的进程是互斥的,他们只能访问系统分配给他们的存储空间。用户地址空间的进程也不能直接访问内核功能。
当用户进程需要访问设备或使用操作系统内核的功能时,必须通过系统调用(system call)来完成。系统调用将处理器切换到保护模式,随后访问内核的地址空间,子啊保护模式下,所有的设备和内存资源通过内核实现API访问。
除了常规的进程和系统调用外,在内核中还包含了几种其他的活动,这几种活动对网络子系统而言尤其重要,因为网络功能就是在内核中处理的:
内核线程(kernel thread)
中断(硬件中断)
软件中断
tasklet
bottom half
在设计内核活动时,最重要的一点是使这些活动能并行执行;另一方面,在多处理器环境下也要考虑同一种活动的同一实例是否可以在不同处理器上并行运行,或同一种活动在两个不同的实例是否可以同时在不同处理器上运行
在这些活动中,另一个需要明确的事,哪种活动的优先级更高,即一种活动是否可以被其他的活动中断。
硬件中断
外部设备用硬件中断来通知操作系统有重要的事件发生,中断发生后,CPU会暂时停止当前程序的执行,转去执行中断处理程序,中断处理程序结束后在恢复原来被停止程序的执行。
硬件中断是一种系统资源,当我们为设备编写中断处理程序来处理外部事件时,要向系统申请中断资源(即硬件中断信号线,通常称为中断号),并将中断处理程序与中断源相关联。我们可以在运行时用内核提供是得一对函数来申请和释放中断资源。
int request_irq(unsigned int irq,irq_handler_t handler,unsigned long flags,const char *devname,void *dev_id)
函数request_irq申请中断号为irq的资源,将申请到的中断号irq与设备名为devname,设备索引号为dev_id设备的中断处理程序handler相连。该设备的中断类型为flags。
voidfree_irq(unsigned int irq,void *dev_id)
函数free_irq释放中断资源
在这里需要对中断类型标志flags做进一步说明,网络子系统中,我们主要区分两类中断类型(虽然在内核中还有其他的中断类型)
a.快速中断
快速中断(fast interrup)的中断处理程序运行时间非常短,所以当前被打断的活动暂停时间也很短。快速中断特点是,屏蔽当前运行中断处理程序CPU的其他中断,这样中断处理程序的执行就不会被别的中断打断。要将中断申请注册为快速中断,需在申请中断资源时将中断类型标志flags设为SA_INTERRUPT
b.慢速中断
慢速中断(slow interrupt)的中断处理程序在执行期间可以被别的中断打断。慢速中断处理程序执行的时间场(相对快速中断而言),所以占用CPU的时间也长。
中断处理程序的执行通常可以暂停所有别的活动。不同的中断在几个CPU上可以同时运行,单某个中断的处理程序一次只能在一个CPU上执行
如果你想查看当前CPU是否在中断活动中,则可以调用内核的API
in_irq() //include/asm/hardirq.h
c.top half 和bottom half
硬件中断可以打断当前CPU上所有其他的活动,并会屏蔽CPU其他硬件中断。硬件中断是系统中有限的资源之一,硬件中断处理程序应尽可能的执行完。在执行中断处理程序期间,如果设备有其他的外部事件发生,由于当前中断资源和CPU已被占用,其他的外部事件就不能得到CPU的响应,所以中断处理程序的执行要尽可能的快。单不是所有事件处理都可以在很短事件内完成,例如网络数据包得接受处理,从网络适配器接受到的数据包到将数据包传送到用户接受进程,需要几千个CPU始终才能完成。接受网络数据包这类事件虽然是由中断除非,但对网络数据包的处理却不能全部放在中断处理程序中来做。
为了节省系统资源,使中断处理程序的运行时间尽可能短,像上述这类费时的时间处理在linux内核中将其分成两个部分来完成。
a.top half
top half指完成中断触发后最重要的任务处理,这里top half就对应中断处理程序。在第五章我们分析网络设备驱动程序的中断处理程序时会看到,网络适配器的中断处理程序,只将收到的数据包复制到内核的缓冲区后就立即结束返回,释放占有的中断和CPU。对数据包的协议分析和处理不在中断处理程序中进行。
b.bottom half
bottom half完成所有非紧急部分的处理。bottom half代码由top half调度,放在以后某个安全的时间运行。比如上述的网络数据包复制到内核以后的分析处理,就在这部分代码中完成。
bottom half与top half最大的区别是,在bottom half执行期间,打开所有硬件中断。他们之间的关系是:top half将在设备缓冲区的数据复制到内核地址空间缓冲区,调度bottom half后退出,这个过程非常快。bottom half执行余下的处理任务,这样的bottom half工作过程中,CPU可以响应新的外部中断请求。linux中有两种不同的机制来实现bottom half过程:tasklet和workqueue。