Linux 驱动中工作队列的使用
2017-05-18 17:10
531 查看
工作队列
struct work_struct my_wq;//定义一个处理函数
void my_wq_func(unsigned long);//定义一个处理函数
通过INIT_WORK()可以初始化这个工作队列并将工作队列与处理函数绑定,
INIT_WORK(&my_wq,(void(*)(void*)) my_wq_func, NULL);
shedule_work(&my_wq);//调度工作队列执行。
10.3 工作队列使用模板
//定义工作队列和关联函数
struct work_struct xxx_wq;
void xxx_do_work(unsigned long);
//中断处理底半部
void xxx_do_work(unsigned long)
{
....
}
//中断顶半部
irqreturn_t xxx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
...
schedule_work(&xxx_wq);
...
}
//设备驱动模块加载函数
int xxx_init(void)
{
....
//申请中断
result = request_irq(xxx_irq, xxx_interrupt, SA_INTERRUPT, "XXX", NULL);
//初始化工作队列
INIT_WORK(&xxx_wq, (void(*)(void *)) xxx_do_work,NULL);
...
}
void xxx_exit(void)
{
free_irq(xxx_irq, xxx_interrupt);
}
工作队列相关:
struct work_struct pen_event_work;
struct workqueue_struct *ts_workqueue;
flush_workqueue
cancel_work_sync(&pen_event_work);
destroy_workqueue(ts_workqueue);
work_pending(work_struct)//找出work_struct是否在pending状态
如:在中断处理上下文里的用法
static irqreturn_t gsl_ts_irq(int irq, void *dev_id)
{
struct gsl_ts *ts = dev_id;
if (ts->is_suspended == true)
return IRQ_HANDLED;
print_info("==========GSLX680 Interrupt============\n");
disable_irq_nosync(ts->irq); //关中断
if (!work_pending(&ts->work)) //判断中断下文处理函数是否在pending
{
queue_work(ts->wq, &ts->work);
}
return IRQ_HANDLED;
}
==============================================================
struct work_struct stk_acc_work;
struct workqueue_struct *stk_acc_wq; //
static void stk_acc_poll_work_func(struct work_struct *work)
{
struct stk831x_data *stk = container_of(work, struct stk831x_data, stk_acc_work);
STK831x_ReadSensorData(stk);
STK831x_ReportValue(stk);
return;
}
stk_acc_wq = create_singlethread_workqueue("stk_acc_wq");//创建单线程。create_workqueue:为每一个CPU都创建一个内核线程。
INIT_WORK(&stk->stk_acc_work, stk_acc_poll_work_func);
queue_work(stk->stk_acc_wq, &stk->stk_acc_work);
destroy_workqueue(stk->stk_acc_wq);//销毁工作队列。
================================================================================
================================================================================
#include <linux/workqueue.h>
struct workqueue_struct;
struct work_struct;
struct delayed_work
struct workqueue_struct *create_workqueue(const char *name);
void destroy_workqueue(struct workqueue_struct *queue);
INIT_WORK(_work, _func);
INIT_DELAYED_WORK(_work, _func);
int queue_work(struct workqueue_struct *wq, struct work_struct *work);
int queue_delayed_work(struct workqueue_struct *wq,struct delayed_work *dwork, unsigned long delay);
int queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
struct delayed_work *dwork, unsigned long delay);
int cancel_work_sync(struct work_struct *work);
int cancel_delayed_work_sync(struct delayed_work *dwork);
void flush_workqueue(struct workqueue_struct *wq);
struct work_struct ps_work; //work 工作
struct workqueue_struct *ps_wq; //queue 队列
INIT_WORK(work_struct, do_func);
序号 接口函数 说明
1 create_workqueue 用于创建一个workqueue队列,为系统中的每个CPU都创建一个内核线程。输入参数:
@name:workqueue的名称
2 create_singlethread_workqueue 用于创建workqueue,只创建一个内核线程。输入参数:@name:workqueue名称
3 destroy_workqueue 释放workqueue队列。输入参数:@ workqueue_struct:需要释放的workqueue队列指针
4 schedule_work 调度执行一个具体的任务,执行的任务将会被挂入Linux系统提供的workqueue——keventd_wq输入参数:
@ work_struct:具体任务对象指针
5 schedule_delayed_work 延迟一定时间去执行一个具体的任务,功能与schedule_work类似,多了一个延迟时间,输入参数:
@delayed_work:具体任务对象指针
@delay:延迟时间
queue_work(struct workqueue_struct *wq,struct work_struct *work)
:调度执行一个指定中的wq任务。输入参数:@ workqueue_struct:指定的wq指针
@work_struct:具体任务对象指针
7 queue_delayed_work 延迟调度执行一个指定workqueue中的任务,功能与queue_work类似,输入参数多了一个delay。
//delay work的用法
定义全局变量:
#ifdef TPD_ESD_PROTECT
#define TPD_ESD_CHECK_CIRCLE 2000
static struct delayed_work gsl_esd_check_work;
static struct workqueue_struct *gsl_esd_check_workqueue = NULL;
#endif
初始化:
#ifdef TPD_ESD_PROTECT
INIT_DELAYED_WORK(&gsl_esd_check_work, gsl_esd_check_func);
gsl_esd_check_workqueue = create_workqueue("gsl_esd_check");
#endif
开启定时:
queue_delayed_work(gsl_esd_check_workqueue, &gsl_esd_check_work, TPD_ESD_CHECK_CIRCLE);
关闭定时:
cancel_delayed_work_sync(&gsl_esd_check_work);
中断函数:
static void gsl_esd_check_func(struct work_struct *work) //函数的参数一定要为(struct work_struct *)结构指针类型。
{
**************************
}
================================================================================
//android early_suspend
===================
4000
=============================================================
#if defined(CONFIG_HAS_EARLYSUSPEND)
struct early_suspend early_suspend;
#endif
#ifdef CONFIG_HAS_EARLYSUSPEND
static void gsl_ts_early_suspend(struct early_suspend *h)
{
struct gsl_ts *ts = container_of(h, struct gsl_ts, early_suspend);
print_info("gsl1680 call func start%s\n", __func__);
}
static void gsl_ts_late_resume(struct early_suspend *h)
{
struct gsl_ts *ts = container_of(h, struct gsl_ts, early_suspend);
print_info("gsl1680 call func end %s\n", __func__);
}
#endif
int xxx_init(void)
{
#ifdef CONFIG_HAS_EARLYSUSPEND
early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN; //级别 也就是先后顺序
early_suspend.suspend = gsl_ts_early_suspend;
early_suspend.resume = gsl_ts_late_resume;
register_early_suspend(&early_suspend);
#endif
}
void xxx_exit(void)
{
#ifdef CONFIG_HAS_EARLYSUSPEND
unregister_early_suspend(&early_suspend);
#endif
}
======================================================================================
struct work_struct my_wq;//定义一个处理函数
void my_wq_func(unsigned long);//定义一个处理函数
通过INIT_WORK()可以初始化这个工作队列并将工作队列与处理函数绑定,
INIT_WORK(&my_wq,(void(*)(void*)) my_wq_func, NULL);
shedule_work(&my_wq);//调度工作队列执行。
10.3 工作队列使用模板
//定义工作队列和关联函数
struct work_struct xxx_wq;
void xxx_do_work(unsigned long);
//中断处理底半部
void xxx_do_work(unsigned long)
{
....
}
//中断顶半部
irqreturn_t xxx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
...
schedule_work(&xxx_wq);
...
}
//设备驱动模块加载函数
int xxx_init(void)
{
....
//申请中断
result = request_irq(xxx_irq, xxx_interrupt, SA_INTERRUPT, "XXX", NULL);
//初始化工作队列
INIT_WORK(&xxx_wq, (void(*)(void *)) xxx_do_work,NULL);
...
}
void xxx_exit(void)
{
free_irq(xxx_irq, xxx_interrupt);
}
工作队列相关:
struct work_struct pen_event_work;
struct workqueue_struct *ts_workqueue;
flush_workqueue
cancel_work_sync(&pen_event_work);
destroy_workqueue(ts_workqueue);
work_pending(work_struct)//找出work_struct是否在pending状态
如:在中断处理上下文里的用法
static irqreturn_t gsl_ts_irq(int irq, void *dev_id)
{
struct gsl_ts *ts = dev_id;
if (ts->is_suspended == true)
return IRQ_HANDLED;
print_info("==========GSLX680 Interrupt============\n");
disable_irq_nosync(ts->irq); //关中断
if (!work_pending(&ts->work)) //判断中断下文处理函数是否在pending
{
queue_work(ts->wq, &ts->work);
}
return IRQ_HANDLED;
}
==============================================================
struct work_struct stk_acc_work;
struct workqueue_struct *stk_acc_wq; //
static void stk_acc_poll_work_func(struct work_struct *work)
{
struct stk831x_data *stk = container_of(work, struct stk831x_data, stk_acc_work);
STK831x_ReadSensorData(stk);
STK831x_ReportValue(stk);
return;
}
stk_acc_wq = create_singlethread_workqueue("stk_acc_wq");//创建单线程。create_workqueue:为每一个CPU都创建一个内核线程。
INIT_WORK(&stk->stk_acc_work, stk_acc_poll_work_func);
queue_work(stk->stk_acc_wq, &stk->stk_acc_work);
destroy_workqueue(stk->stk_acc_wq);//销毁工作队列。
================================================================================
================================================================================
#include <linux/workqueue.h>
struct workqueue_struct;
struct work_struct;
struct delayed_work
struct workqueue_struct *create_workqueue(const char *name);
void destroy_workqueue(struct workqueue_struct *queue);
INIT_WORK(_work, _func);
INIT_DELAYED_WORK(_work, _func);
int queue_work(struct workqueue_struct *wq, struct work_struct *work);
int queue_delayed_work(struct workqueue_struct *wq,struct delayed_work *dwork, unsigned long delay);
int queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
struct delayed_work *dwork, unsigned long delay);
int cancel_work_sync(struct work_struct *work);
int cancel_delayed_work_sync(struct delayed_work *dwork);
void flush_workqueue(struct workqueue_struct *wq);
struct work_struct ps_work; //work 工作
struct workqueue_struct *ps_wq; //queue 队列
INIT_WORK(work_struct, do_func);
序号 接口函数 说明
1 create_workqueue 用于创建一个workqueue队列,为系统中的每个CPU都创建一个内核线程。输入参数:
@name:workqueue的名称
2 create_singlethread_workqueue 用于创建workqueue,只创建一个内核线程。输入参数:@name:workqueue名称
3 destroy_workqueue 释放workqueue队列。输入参数:@ workqueue_struct:需要释放的workqueue队列指针
4 schedule_work 调度执行一个具体的任务,执行的任务将会被挂入Linux系统提供的workqueue——keventd_wq输入参数:
@ work_struct:具体任务对象指针
5 schedule_delayed_work 延迟一定时间去执行一个具体的任务,功能与schedule_work类似,多了一个延迟时间,输入参数:
@delayed_work:具体任务对象指针
@delay:延迟时间
queue_work(struct workqueue_struct *wq,struct work_struct *work)
:调度执行一个指定中的wq任务。输入参数:@ workqueue_struct:指定的wq指针
@work_struct:具体任务对象指针
7 queue_delayed_work 延迟调度执行一个指定workqueue中的任务,功能与queue_work类似,输入参数多了一个delay。
//delay work的用法
定义全局变量:
#ifdef TPD_ESD_PROTECT
#define TPD_ESD_CHECK_CIRCLE 2000
static struct delayed_work gsl_esd_check_work;
static struct workqueue_struct *gsl_esd_check_workqueue = NULL;
#endif
初始化:
#ifdef TPD_ESD_PROTECT
INIT_DELAYED_WORK(&gsl_esd_check_work, gsl_esd_check_func);
gsl_esd_check_workqueue = create_workqueue("gsl_esd_check");
#endif
开启定时:
queue_delayed_work(gsl_esd_check_workqueue, &gsl_esd_check_work, TPD_ESD_CHECK_CIRCLE);
关闭定时:
cancel_delayed_work_sync(&gsl_esd_check_work);
中断函数:
static void gsl_esd_check_func(struct work_struct *work) //函数的参数一定要为(struct work_struct *)结构指针类型。
{
**************************
}
================================================================================
//android early_suspend
===================
4000
=============================================================
#if defined(CONFIG_HAS_EARLYSUSPEND)
struct early_suspend early_suspend;
#endif
#ifdef CONFIG_HAS_EARLYSUSPEND
static void gsl_ts_early_suspend(struct early_suspend *h)
{
struct gsl_ts *ts = container_of(h, struct gsl_ts, early_suspend);
print_info("gsl1680 call func start%s\n", __func__);
}
static void gsl_ts_late_resume(struct early_suspend *h)
{
struct gsl_ts *ts = container_of(h, struct gsl_ts, early_suspend);
print_info("gsl1680 call func end %s\n", __func__);
}
#endif
int xxx_init(void)
{
#ifdef CONFIG_HAS_EARLYSUSPEND
early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN; //级别 也就是先后顺序
early_suspend.suspend = gsl_ts_early_suspend;
early_suspend.resume = gsl_ts_late_resume;
register_early_suspend(&early_suspend);
#endif
}
void xxx_exit(void)
{
#ifdef CONFIG_HAS_EARLYSUSPEND
unregister_early_suspend(&early_suspend);
#endif
}
======================================================================================
相关文章推荐
- linux驱动学习之工作队列使用
- linux驱动开发之输入子系统编程(一)使用工作队列实现中断下半部
- linux work queue工作队列小结与使用
- linux 触摸屏驱动中断下半部实现-工作队列
- linux驱动---等待队列、工作队列、Tasklets
- linux驱动中的工作队列
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】中断服务下半部之工作队列详解
- Linux驱动开发-中断分层机制_工作队列 笔记 7
- Linux驱动之等待队列和poll使用
- linux 工作队列的使用
- linux驱动编程--工作队列浅析
- Linux 驱动之中断下半部之工作队列
- linux设备驱动--内核等待队列知识点---结合中断使用
- linux驱动增加work工作队列和获取唤醒锁操作
- rookit for linux 9.发送skb---使用工作队列
- Linux工作队列的使用
- linux 工作队列的使用
- 如何使用Linux工作队列workqueue
- linux驱动学习之工作队列机制
- Linux工作队列的使用