linux 中断底半部的实现

一、描述

工作队列(work queue) 类似 tasklet,允许调用者请求在将来某个时间调用一个函数。

tasklet 在软件中断上下文中运行,所以tasklet执行很快,持续短,并且一般在原子态。
tasklet一般只能在最初被提交的处理器上运行。

工作队列在一个特殊内核进程上下文运行,有更多的灵活性,并且能够休眠。工作队列包括一系列将要执行的任务和执行这些任务的内核线程。每个工作队列有一个专门的线程,所有的任务必须在进程的上下文中运行,这样它们可以安全休眠。


二、代码数据结构

1. tasklet
struct tasklet_struct
{
	struct tasklet_struct *next;
	unsigned long state;
	atomic_t count;
	void (*func)(unsigned long);//tasklet的处理函数 ---- 底半部
	unsigned long data;//传递给tasklet处理函数的参数
};
2. 编程使用
1.分配初始化
    struct tasklet_struct mytasklet;
    tasklet_init(&mytasklet,处理函数,处理函数的参数);
或者
    DECLARE_TASKLET(tasklet名,处理函数,处理函数的参数);  
    
2.在顶半部中登记tasklet
    tasklet_schedule(&mytasklet);   

tasklet本身运行在中断上下文,处理函数不能 阻塞/睡眠。

3.工作队列

tasklet处理函数不允许睡眠,如果底半部需要睡眠可以选择工作队列,工作队列包括工作和延时工作。

//工作
typedef void (*work_func_t)(struct work_struct *work);//函数指针类型
struct work_struct {
	atomic_long_t data;
	struct list_head entry;
	work_func_t func;//工作的处理函数
#ifdef CONFIG_LOCKDEP
	struct lockdep_map lockdep_map;
#endif
};

//延时工作 -------- 指定延时多久后才处理
struct delayed_work {
	struct work_struct work;//工作
	struct timer_list timer;//内核定时器
};
4. 编程使用
1)分配初始化
    struct work_struct mywork;
    struct delayed_work mydwork;
    
    INIT_WORK(&mywork,工作处理函数);
    INIT_DELAYED_WORK(&mydwork,延时工作处理函数);
    
2)在顶半部中登记工作/延时工作
    schedule_work(&mywork);//空闲时调用
    schedule_delayed_work(&mydwork,延时时间);//延时指定时间调用 HZ <===> 1s3)注意事项
    工作/延时工作 工作于进程上下文,使用内核线程来执行,参与任务调度,可以睡眠

三、比较

比较点Tasklet工作队列
执行上下文延后的工作(中断底半部),运行于中断上下文延后的工作(中断底半部),运行于进程上下文
可重用不能在不同的CPU上同时运行,但是不同的CPU可以运行不同的 tasklet可以在不同的CPU上同时运行
睡眠不能睡眠可以睡眠
抢占不能抢占/调度可以抢占/调度
易用性容易使用容易使用
使用场合如果延后的工作不会睡眠如果延后的工作会睡眠

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值