再读《深入理解Linux内核》-----中断下半部的处理机制

第一次读这本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)工作队列的执行流程
在这里插入图片描述
在学习中进步,如有错误,请多多批评指正

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeAmmon

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值