在linux中,當你想延時幾秒或者幾毫秒再執行一個任務或者自定義的一個函數時,延時工作隊列是你最好的選擇。在你的任務或者函數中,加上queue_delayed_work,就可以每隔一段時間執行一次你的任務或者自定義的一個函數,具體實現如下:
按如下步驟:
首先還是要添加上工作隊列的相關頭文件,頭文件一般有這些函數的聲明和定義,include了相關的頭文件,我們才能隨心所欲的使用這些頭文件裏面的函數,達到我們的目的:
#include <linux/workqueue.h>
一.聲明一個工作隊列
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 <linux/workqueue.h>
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 <linux/workqueue.h>
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);