工作队列 order linux,linux 工作队列(workqueue)
在處理內核相關工作中, 我們經常看到工作隊列(workqueue)的身影. 本文描述何為 linux workqueue.
本文基于 2.6.32 的內核, 此時的工作隊列還不是 cmwq.
為什么使用 workqueue
在內核代碼中, 經常希望延緩部分工作到將來某個時間執行, 這樣做的原因很多, 比如
在持有鎖時做大量(或者說費時的)工作不合適.
希望將工作聚集以獲取批處理的性能.
調用了一個可能導致睡眠的函數使得在此時執行新調度非常不合適.
...
內核中提供了許多機制來提供延遲執行, 使用最多則是 workqueue.
如中斷的下半部處理可延遲中斷上下文中的部分工作;
定時器可指定延遲一定時間后執行某工作;
workqueue 則允許在進程上下文環境下延遲執行;
內核中曾短暫出現過的慢工作機制 (slow work mechanism);
異步函數調用(asynchronous function calls);
各種私有實現的線程池;
...
術語
workqueue: 所有工作項(需要被執行的工作)被排列于該隊列.
worker thread: 是一個用于執行 workqueue 中各個工作項的內核線程, 當 workqueue 中沒有工作項時, 該線程將變為 idle 狀態.
single threaded(ST): worker thread 的表現形式之一, 在系統范圍內, 只有一個 worker thread 為 workqueue 服務.
multi threaded(MT): worker thread 的表現形式之一, 在多 CPU 系統上每個 CPU 上都有一個 worker thread 為 workqueue 服務.
使用步驟
創建 workqueue(如果使用內核默認的 workqueue, 此步驟略過).
創建工作項 work_struct.
向 workqueue 提交工作項.
工作項
數據結構(略有調整):
struct work_struct {
atomic_long_t data;
struct list_head entry;
work_func_t func;
struct lockdep_map lockdep_map;
};
struct delayed_work {
struct work_struct work;
struct timer_list timer;
};
靜態地創建工作項:
DECLARE_WORK(n, f)
DECLARE_DELAYED_WORK(n, f)
動態地創建工作項:
INIT_WORK(struct work_struct work, work_func_t func);
PREPARE_WORK(struct work_struct work, work_func_t func);
INIT_DELAYED_WORK(struct delayed_work work, work_func_t func);
PREPARE_DELAYED_WORK(struct delayed_work work, work_func_t func);
內核默認的 workqueue
查閱源碼可知, 內核默認的全局 workqueue 應為:
// 定義
static struct workqueue_struct *keventd_wq __read_mostly;
// 初始化
...
keventd_wq = create_workqueue("events"); // MT worker thread 模式.
...
// 確認對應的內核線程數目, 應等于 CPU 核數
$ lscpu
Architecture: x86_64
CPU(s): 3
Thread(s) per core: 1
$ ps aux | grep "events"
root 9 0.0 0.0 0 0 ? S Feb09 1:15 [events/0]
root 10 0.0 0.0 0 0 ? S Feb09 0:59 [events/1]
root 11 0.0 0.0 0 0 ? S Feb09 0:59 [events/2]
工作項加入 keventd_wq 由下面兩個函數之一完成:
int schedule_work(struct work_struct *work)
{
return queue_work(keventd_wq, work);
}
int schedule_delayed_work(struct delayed_work *dwork, unsigned long delay)
{
return queue_delayed_work(keventd_wq, dwork, delay);
}
用戶自定義的 workqueue
創建 workqueue:
create_singlethread_workqueue(name) // 僅對應一個內核線程
create_workqueue(name) // 對應多個內核線程, 同上文.
向 workqueue 中提交工作項:
int queue_work(workqueue_t *queue, work_t *work);
int queue_delayed_work(workqueue_t *queue, work_t *work, unsigned long delay);
取消 workqueue 中掛起的工作項以及釋放 workqueue 此處略過.
工作隊列的優點
使用簡單.
執行在進程上下文, 從而可以睡眠, 被調度和搶占.
在多核環境下使用也非常友好.
example
#include
#include
#include
static struct workqueue_struct *queue = NULL;
static struct work_struct work;
static void work_handler(struct work_struct *data)
{
printk(KERN_ALERT "work handler for work_item in queue helloworkqueue\n");
// workqueue 中的每個工作完成之后就被移除 workqueue.
// 下面的語句會造成"死機", 原因可能是該 workqueue 占據了所有的 CPU 時間.
// queue_work(queue, &work);
}
static int __init test_init(void)
{
queue = create_singlethread_workqueue("helloworkqueue");
if (!queue)
{
goto err;
}
INIT_WORK(&work, work_handler);
queue_work(queue, &work);
return 0;
err:
return -1;
}
static void __exit test_exit(void)
{
destroy_workqueue(queue);
}
MODULE_LICENSE("GPL");
module_init(test_init);
module_exit(test_exit);
brought to you by .
總結
以上是生活随笔為你收集整理的工作队列 order linux,linux 工作队列(workqueue)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 高中生入门计算机编程,高中生必看:入门学
- 下一篇: vim中如何设置多行注释和删除注释