在linux中,当你想延时几秒或者几毫秒再执行一个任务或者自定义的一个函数时,延时工作队列是你最好的选择。在你的任务或者函数中,加上queue_delayed_work,就可以每隔一段时间执行一次你的任务或者自定义的一个函数,具体实现如下:
按如下步骤:
首先还是要添加上工作队列的相关头文件,头文件一般有这些函数的声明和定义,include了相关的头文件,我们才能随心所欲的使用这些头文件里面的函数,达到我们的目的:
#include
一.声明一个工作队列
static struct workqueue_struct *test_wq;
二.声明一个延期工作描述实例
static struct delayed_work test_delay_wq;
三.声明并实现一个工作队列延迟处理函数
void test_power_delay_work_func(struct work_struct *work)
{
int value;
value = get_adc_sample(0, CHAN_1); //这里调用adc接口去读取数据
pr_err("-czd-: current power adc value is %d\n", value);
queue_delayed_work(test_wq, &test_delay_wq, msecs_to_jiffies(5000)); //加上这句就可以每隔5秒钟执行一次这个函数test_power_delay_work_func,不加就只执行一次,时间msecs_to_jiffies(5000)可以设置别的时间,这里是5秒,相关部分想了解更多可以百度
}
四.初始化一个工作队列(在init模块加载函数添加或者在probe函数添加)
test_wq = create_workqueue("test_wq");
if (!test_wq) {
printk(“-czd-: No memory for workqueue\n");
return 1;
}
五. 任务初始化(在init模块加载函数添加或者在probe函数添加)
INIT_DELAYED_WORK(&test_delay_wq, test_power_delay_work_func);
六.向工作队列提交工作项(在init模块加载函数添加或者在probe函数添加)
ret = queue_delayed_work(test_wq, &test_delay_wq, msecs_to_jiffies(5000));
pr_err("-czd-: ret=%d\n", ret);
七.取消工作队列中的工作项
int cancel_delayed_work(test_wq);
如果这个工作项在它开始执行前被取消,返回值是非零。内核保证给定工作项的执行不会在调用 cancel_delay_work 成功后被执行。 如果 cancel_delay_work 返回 0,则这个工作项可能已经运行在一个不同的处理器,并且仍然可能在调用 cancel_delayed_work 之后被执行。要绝对确保工作函数没有在 cancel_delayed_work 返回 0 后在任何地方运行,你必须跟随这个调用之后接着调用 flush_workqueue。在 flush_workqueue 返回后。任何在改调用之前提交的工作函数都不会在系统任何地方运行。
八.刷新工作队列
flush_workqueue(test_wq);
九.工作队列销毁
destroy_workqueue(test_wq);
七八九可以同时添加到exit函数中,例如以下:
static void __exit module_exit(void)
{
int ret;
ret = cancel_delayed_work(&test_dwq);
flush_workqueue(test_wq);
destroy_workqueue(test_wq);
printk("-czd-: enter %s, ret=%d\n", __func__, ret);
}
除了上面调用的queue_delayed_work之外,使用schedule_delayed_work也是可以的。其实schedule_delayed_work最终返回调用的还是queue_delayed_work。函数声明在include/linux/workqueue.h中。
static inline bool schedule_delayed_work(struct delayed_work *dwork,
unsigned long delay)
{
return queue_delayed_work(system_wq, dwork, delay);
}
下面的demo是实现3秒之后再执行work_queue:
#include
static struct delayed_work send_event; //定义一个delay_work
static void send_event_workq(struct work_struct *work) //定义你要延时执行的函数
{
rk_send_wakeup_key();
printk("***************charger mode send wakeup key\n\n");
schedule_delayed_work(&send_event, msecs_to_jiffies(3000)); //添加之后每隔3秒执行一次
}
static int __init module_init(void)
{
INIT_DELAYED_WORK(&send_event, send_event_workq); //初始化工作队列
schedule_delayed_work(&send_event, msecs_to_jiffies(3000)); //添加到延时工作队列,这里延时3秒
}
static void __exit module_exit(void)
{
cancel_delayed_work_sync(&send_event); //取消延时工作队列
}
下面是创建一个工作队列的demo 代码:
#include
void my_func(void *data)
{
char *name = (char *)data;
printk(KERN_INFO “Hello world, my name is %s!\n”, name);
}
struct workqueue_struct *my_wq = create_workqueue(“my wq”);
struct work_struct my_work;
INIT_WORK(&my_work, my_func);
queue_work(my_wq, &my_work);
destroy_workqueue(my_wq);