延时操作

 

tasklet例程

简单实现步骤1.DECLARE_TASKLET()  2. tasklet_schedule(&demo_tasklet);
//设备相关的指针
static struct demo_dev *p = ....;

//延迟操作函数
void demo_delay_action(unsigned long data)
{
   // 通过data获得设备相关指针
   static struct demo_dev * pdev = (static struct demo_dev *)data;
  // 延迟操作
  .....
}

//用DECLARE_TASKLET(name, func, data)定义一个tasklet对象demo_tasklet
DECLARE_TASKLET(demo_tasklet, demo_delay_action, (unsigned log)p );

//中断处理例程
irqreturn_t demo_isr(int irq, void * dev_id)
{
   .................
   通过tasklet_schedule实现延迟操作
    tasklet_schedule(&demo_tasklet);  //此处提交tasklet对象和SOFTIRQ部分调用处理
}

在任意时刻,同一tasklet只能有一个实例在运行,即使是多处理器系统也如此。tasklet另一个特性是:
那个处理器调用tasklet_schedule提交的tasklet,只能在该处理器上运行。


 

工作队列work queue

简单实现步骤:1. INIT_WORK(_work, _func);    2. schedule_work();

struct work_struct    //工作节点

struct cpu_workqueue_struct   //cpu工作队列管理结构

struct workqueue_struct  //工作队列管理管理结构

 

驱动程序可以调用create_singlethread_workaueue和creat_workqueue函数来让内核生成属于自己的工作队列,两者区别

前者只在系统中第一个CPU上创建工作队列和工人线程,后者函数会在系统中每个CPU上创建工作队列和工人线程。在用

queue_work提交工作节点时,如果是singlethread类型,只能提交到这唯一的一个worklist。反之,如果不是singlethread

类型,那么工作节点将会提交到当前运行queue_work的CPU所在的worklist中。

 

动态初始化:INIT_WORK(_work, _func)

静态初始化:DECLARE_WORK(n,f)

提交工作节点时只需调用schedule_work()函数就可以,对于queue_delayed_work,对于内核创建的工作队列而言,

延迟提交函数变成schedule_delayed_work().

 

使用内核工作队列好处是驱动无须创建自己的工作队列就可以提交节点来实现延迟操作,坏处是正在与系统

中其它模块共享一个工作队列以及该队列上的work_thread,所以无法预期提交一个节点需多久才调度执行。

 

内核提供了另一个提交节点的函数queue_delayed_work

int queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *dwork, unsigned long delay);

 

自己创建工作队列例程:


//定义全局性的struct workqueue_struct指针demo_dev_wq
static struct workqueue_struct * demo_dev_wq;

//设备特定的数据结构,实际使用中大部分struct work_struct结构都内嵌在这个数据结构中
struct demo_device{
....................
struct work_struct work;
...............
}

static struct demo_device * demo_dev;

//定义延迟操作函数
void demo_work_func(ftruct work_struct *work)
{.................}

// 驱动程序模块初始化代码调用create_singlethread_workqueue创建工作队列
static int_init demo_dev_init(void)
{ ..................
  demo_dev = kzalloc(sizeof *demo_dev,GFP_KERNEL);

demo_dev_wq = create_singlethread_workqueue("demo_dev_workqueue");
INIT_WORK(&demo_dev->work,demo_work_func);
...................
}

//模块退出函数
static void demo_dev _exit(void)
{.................
   flush_wokqueue(demo_dev_wq);
  destroy_workqueue(demo_dev_wq);
.........................
}

//中断处理函数
irqreturn_t demo_isr(int irq, void * dev_id)
{...........................
   queue_work(demo_dev_wq, &demo_dev->work);
   ..........................
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值