休息了整整一个星期,(*^__^*) 嘻嘻……,一个字,爽!!!
一个星期没有学习了,也就没有贴这些东西喽。不过今天是新的开始,所以就打算贴点东西上来,还是按键中断,不过是通过工作队列来实现的!
我买的视频没有这些东西,所以只能自己看喽,我个人感觉使用工作队列来处理按键中断,很大的好处是可以消抖!别的还真没有看出什么东西来,呵呵。
还有就是工作队列和等待队列是啥子关系呢<~>暂时还真的不清楚。
1、内核工作队列
工作队列(workqueue)是 Linux 内核中定义的用来处理不是很紧急事件的回调方式处理方法,常用来处理中断下半部的工作。内核对工作队列的处理是通过工作者线程完成的。工作者线程在一般情况下处于睡眠状态,当我们通过调度把需要推迟执行的工作挂到工作队列之后,就会唤醒工作者线程,遍历工作队列中的每个待处理的工作,并执行工作结构 work_struct 中 func 成员表示的回调函数。工作队列通常不需要自己创建,因为内核维护了一些全局的工作队列(定义在 kernel/workqueue.c 中),并提供了对应的操作接口,我们需要做的就是定义工作结构并使用相应的接口进行调度。
2、相关结构与操作
在内核头文件 include/linux/workqueue.h 中,声明和定义了工作队列的相关结构和操作接口,下面将列举一些常用的结构和方法:
1)定义和初始化
工作结构是利用工作队列进行调度工作的主要成员,在 workqueue.h 中,它定义如下:
struct work_struct { atomic_long_t data; struct list_head entry; work_func_t func;}
其中 func 成员是一个函数指针,指向工作回调函数,work_func_t 是类型重定义:
typedef void(*work_func_t)(struct work_struct *work);
初始化一个工作结构使用如下宏函数:
INIT_WORK(_work,_func)▲:_work:表示工作结构,实际上要求填写该结构的地址或执行该结构的指针。▲:_func:回调函数。
定义并初始化一个工作结构使用如下宏函数:
DECLARE_WORK(n,f)▲:n:工作结构名。▲:f:回调函数。
2)调度工作
调度工作使用如下接口函数,该函数实际上完成将指定工作添加到内核维护的全局工作队列 system_wq 中去的工作。
int shcedule_work(struct work_struct *work);▲:work:被添加的工作。
返回值:成功返回 0,失败返回非 0。
3)延迟调度工作
如果推后执行的任务需要延时指定的时间再触发,那么应该采用延迟调度工作。延迟调度工作,通常利用内核定时器实现,方法是在定时器的回调函数中执行 schedule_work() 进行调度工作。另外,内核还定义了一个专门的结构及其相关操作接口,用来处理需要延迟调度的工作,这个结构在 include/linux/kqueue.h 中:
struct delay_work{ struct work_struct work; struct timer_list timer;};
可见,delay_work 结构仅仅是在工作结构的基础上,添加了用于延迟调度的定时器,初始化一个 delay_work 结构使用如下宏函数:
INIT_DELAY_WORK(_work,_func)▲:_work:表示工作结构。▲:_func:回调函数。
定义并初始化一个工作结构使用如下宏函数:
DECLARE_DELAYD_WORK(n,f);▲:n:工作结构名。▲:f:回调函数。
延迟调度工作使用如下接口函数,该函数将在 delay 个 jiffies 后,在 dwork->timer 指定的定时器中执行对 dwork->work 的工作调度,将该工作添加到内核维护的全局工作队列 system_wq 中去:
函数原型int schedule_delayed_work(struct delay_struct *dwork,
unsigned long delay)
函数参数
▲:dwork:被添加的延时工作。
▲:delay:延迟时间,单位 jiffies,为 0 时,将会立即执行。
返回值成功返回 0,失败返回非零。
画龙画虎难画骨,知人知面不知心。