第一次读这本linux的圣经的时候,真是一头雾水,无从下手,参考知乎上知友推荐的阅读顺序,勉勉强强读完了第一遍,脑袋里有了印象,之后在工作中用到了一些东西,参考代码,然后才准备第二次阅读,结合陈老师的读书笔记,梳理框架,整理思路,做学习记录。
中断下半部的处理机制
1.软中断请求(softirq)机制
软中断的分配是静态的(即在编译时定义),同一种类型的软中断可并发的运行在多个cpu上,所以软中断是可重入函数且必须明确使用自旋锁保护其数据结构,软中断代码在:kernel/softirq.c,软中断流程如下
2.小任务(tasklet)机制
tasklet分配和初始化可在运行事进行(eg:安装一个内核模块时),相同类型的tasklet总是被串行的执行,即不能再两个cpu同事运行相同类型的tasklet,但类型不同的tasklet可在几个cpu上并发执行,tasklet也是利用软中断实现,但提供了比软中断更好的接口,一般建议使用tasklet实现自己的中断。
tasklet对应的结构体在 <linux/interrupt.h> 中
struct tasklet_struct
{
struct tasklet_struct *next; /* 链表中的下一个tasklet */
unsigned long state; /* tasklet状态 */
atomic_t count; /* 引用锁计数器 */
void (*func)(unsigned long); /* tasklet处理函数 */
unsigned long data; /* tasklet处理函数的参数 */
};
3.工作队列机制
以上的可延迟函数运行在中断上下文中,工作队列的函数运行在进程上下文中,执行可阻塞函数(eg:需访问磁盘数据块的函数)的唯一饭否是是在进程上下文运行,因为中断上下文不可能发生进程切换,可延迟函数(软中断)和工作队列函数君不能访问进程用户态地址空间,工作队列中的函数是由内核线程来执行的。
(1)工作队列用到的3个结构体如下:
/* 在 include/linux/workqueue.h 文件中定义 */
struct work_struct {
atomic_long_t data; /* 这个并不是处理函数的参数,而是表示此work是否pending等状态的flag */
#define WORK_STRUCT_PENDING 0 /* T if work item pending execution */
#define WORK_STRUCT_FLAG_MASK (3UL)
#define WORK_STRUCT_WQ_DATA_MASK (~WORK_STRUCT_FLAG_MASK)
struct list_head entry; /* 中断下半部处理函数的链表 */
work_func_t func; /* 处理中断下半部工作的函数 */
#ifdef CONFIG_LOCKDEP
struct lockdep_map lockdep_map;
#endif
};
/* 在 kernel/workqueue.c文件中定义
* 每个工作者线程对应一个 cpu_workqueue_struct ,其中包含要处理的工作的链表
* (即 work_struct 的链表,当此链表不空时,唤醒工作者线程来进行处理)
*/
/*
* The per-CPU workqueue (if single thread, we always use the first
* possible cpu).
*/
struct cpu_workqueue_struct {
spinlock_t lock; /* 保护该数据结构的自旋锁 */
struct list_head worklist; /* 工作队列头节点 */
wait_queue_head_t more_work; /*等待队列其中的工作者线程因等待更多的工作而处于睡眠状态*/
struct work_struct *current_work; /**/
struct workqueue_struct *wq; /* 关联工作队列结构 */
struct task_struct *thread; /* 关联线程 */
} ____cacheline_aligned;
/* 也是在 kernel/workqueue.c 文件中定义的
* 每个 workqueue_struct 表示一种工作者类型,系统默认的就是 events 工作者类型
* 每个工作者类型一般对应n个工作者线程,n就是处理器的个数
*/
/*
* The externally visible workqueue abstraction is an array of
* per-CPU workqueues:
*/
struct workqueue_struct {
struct cpu_workqueue_struct *cpu_wq; /* 工作者线程 */
struct list_head list;
const char *name;
int singlethread;
int freezeable; /* Freeze threads during suspend */
int rt;
#ifdef CONFIG_LOCKDEP
struct lockdep_map lockdep_map;
#endif
};
(2)工作队列的执行流程
在学习中进步,如有错误,请多多批评指正