linux内核下半部:软中断、tasklet、工作队列

#软中断tasklet和工作队列是linux中存在的关于中断下半部的机制,更早之前的内核中的“小半部”(bottom half)演变而来
(1)、 中断上半部和小半部的区别
上半部是指中断处理程序,其对于时间敏感,如键盘事件需要能立即响应,应用中断实现。下半部是指一些虽然与中断相关但是可以延后处理的程序。如网络传输中,网卡收到数据包事件不一定需要马上被处理。
两者区别:中断不能被相同类型的中断打断,而下半部依然可以被中断打断;中断对于时间非常敏感,而下半部基本上都是一些可以延迟的工作。由于二者的这种区别,所以对于一个工作是放在上半部还是放在下半部去执行,可以参考下面四条:
a)如果一个任务对时间非常敏感,将其放在中断处理程序中执行。
b)如果一个任务和硬件相关,将其放在中断处理程序中执行。
c)如果一个任务要保证不被其他中断(特别是相同的中断)打断,将其放在中断处理程序中执行。
d)其他所有任务,考虑放在下半部去执行
(2)、软中断
软中断使用得比较少,tasklet是下半部更常用的一种形式,tasklet是通过该软中断实现的,软中断由softirq_action结构表示,其定义于。主要用于网络和SCSI两个子系统中。
a)产生后并不是马上可以执行,必须要等待内核的调度才能执行。软中断不能被自己打断,只能被硬件中断打断(上半部)
b)可以并发运行在多个CPU上(即使同一类型的也可以)。所以软中断必须设计为可重入的函数(允许多个CPU同时操作),因此也需要使用自旋锁来保护其数据结构
(3)、tasklet
tasklet是通过软中断实现的,tasklet由两类软中断代表HI_SOFTIRQ和TASKLET_SOFTIRQ,其中HI_SOFTIRQ类型的软中断优先级高于TASKLET_SOFTIRQ

在这里插入代码片
#include 
#include 
#include 
#include 
#include 
#include 
#include  

static struct tasklet_struct my_tasklet;  
static void tasklet_handler (unsigned long data)
{
        printk(KERN_ALERT "tasklet_handler is running.\n");
} 

static int hello_init(void)
{
	printk(KERN_EMERG "HELLO WORLD enter!\n");
	tasklet_init(&my_tasklet, tasklet_handler, 0);
        tasklet_schedule(&my_tasklet);
	return 0;
}

static void hello_exit(void)
{
	printk(KERN_EMERG "HELLO WORLD exit!\n");
	tasklet_kill(&my_tasklet);
}

module_init(hello_init);
module_exit(hello_exit);

(3)、工作队列
在2.6版的内核中出现了在内核态运行的工作队列(替代了2.4内核中的任务队列)。它也具有一些可延迟函数的特点(需要被激活和延后执行),但是能够能够在不同的进程间切换,以完成不同的工作。

你可能感兴趣的:(内核,linux,队列)