23 内核开发- Linux 内核下半段的实现方式
1.定义
下半部,就是执行中断处理密切相关但是中断处理程序本身不执行的工作。
2.为什么要用下半部执行?
- 中断处理程序不在进程上下文中运行,所以他们不能阻塞;
- 为什么要推后执行,已经在什么什么时候执行非常关键,因为需要尽量减少中断处理程序需要完成的工作量,因为他在运行过程中,当前中断线所在的处理器上都会被屏蔽。缩短中断屏蔽的时间对系统的响应能力和性能至关重要。此外必须尽力缩短中断处理程序的执行,解决办法就是把一些工作放到以后去做。
3.起源
最早linux 只提供 bottom half 这种机制实现下半部,简称 BH,后面由于性能不高废弃。
4. 任务队列 (task Queue)
任务队列是一种用于管理和执行任务的通用机制。它允许内核将任务排队并异步执行它们。任务队列通常用于执行不需要在特定上下文或时间限制内完成的任务。
在 Linux 内核中,任务队列由以下数据结构表示:
struct task_queue_struct {
spinlock_t lock;
struct list_head list;
const char *name;
struct wake_q_head wake_q;
struct hrtimer timer;
int (*func)(void *data);
void *data;
};
其中:
lock:用于保护任务队列的锁。
list:存储已排队的任务的链表。
name:任务队列的名称。
wake_q:用于唤醒等待任务队列中任务完成的进程的等待队列。
timer:用于定期检查任务队列的计时器。
func:要执行的任务的函数指针。
data:要传递给任务函数的数据。
5. 软中断 (SoftIRQ)
软中断(SoftIRQ)是一种中断处理机制,用于处理与硬件设备交互的任务。它允许内核在处理硬件中断后异步执行这些任务,从而提高系统的响应能力和并行性。
在 Linux 内核中,软中断由以下数据结构表示:
struct softirq_action {
const char *name;
void (*action)(struct softirq_action *);
};
struct softirq_list {
struct softirq_action *action;
unsigned long vec;
};
其中:
name:软中断的名称。
action:要执行的软中断处理程序函数。
vec:软中断的向量号。
6. 任务调度器 (Tasklet)
任务调度器(Tasklet)是一种用于执行与特定硬件设备或软件事件相关的短时间任务的机制。它允许内核在硬件中断处理程序或软中断处理程序上下文中快速且高效地执行这些任务。
在 Linux 内核中,任务调度器由以下数据结构表示:
struct tasklet_struct {
struct tasklet_head head;
void (*func)(unsigned long);
unsigned long data;
};
struct tasklet_head {
struct tasklet_struct *next;
};
其中:
head:任务调度器的头结构。
func:要执行的任务调度器函数。
data:要传递给任务调度器函数的数据。
next:指向下一个任务调度器的指针。
7.总结
linux 2.6后,内核提供了三种方式实现下半部:软中断,tasklets和工作队列。 以前曾经用过的
BH和任务队列接口已经废除