新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > linux內核工作隊列講解和源碼詳細注釋

        linux內核工作隊列講解和源碼詳細注釋

        作者: 時間:2016-10-08 來源:網絡 收藏

        1. 前言

        本文引用地址:http://www.104case.com/article/201610/305909.htm

        工作隊列(workqueue)的Linux內核中的定義的用來處理不是很緊急事件的回調方式處理方法。

        以下代碼的linux內核版本為2.6.19.2, 源代碼文件主要為kernel/workqueue.c.

        2. 數據結構

        /* include/linux/workqueue.h */ // 工作節點結構struct work_struct { // 等待時間unsigned long pending;// 鏈表節點struct list_head entry;// workqueue回調函數void (*func)(void *);// 回調函數func的數據void *data;// 指向CPU相關數據, 一般指向struct cpu_workqueue_struct結構void *wq_data;// 定時器struct timer_list timer;};

        struct execute_work { struct work_struct work;};

        /* kernel/workqueue.c */ /* * The per-CPU workqueue (if single thread, we always use the first * possible cpu)。

        * * The sequence counters are for flush_scheduled_work()。 It wants to wait * until all currently-scheduled works are completed, but it doesn't * want to be livelocked by new, incoming ones. So it waits until * remove_sequence is >= the insert_sequence which pertained when * flush_scheduled_work() was called. */ // 這個結構是針對每個CPU的struct cpu_workqueue_struct { // 結構鎖spinlock_t lock;// 下一個要執行的節點序號long remove_sequence; /* Least-recently added (next to run) */ // 下一個要插入節點的序號long insert_sequence; /* Next to add */ // 工作機構鏈表節點struct list_head worklist;// 要進行處理的等待隊列wait_queue_head_t more_work;// 處理完的等待隊列wait_queue_head_t work_done;// 工作隊列節點struct workqueue_struct *wq;// 進程指針struct task_struct *thread;int run_depth; /* Detect run_workqueue() recursion depth */ } ____cacheline_aligned;/* * The externally visible workqueue abstraction is an array of * per-CPU workqueues:*/ // 工作隊列結構struct workqueue_struct { struct cpu_workqueue_struct *cpu_wq;const char *name;struct list_head list; /* Empty if single thread */ };

        kernel/workqueue.c中定義了一個工作隊列鏈表, 所有工作隊列可以掛接到這個鏈表中:static LIST_HEAD(workqueues);

        3. 一些宏定義

        /* include/linux/workqueue.h */ // 初始化工作隊列#define __WORK_INITIALIZER(n, f, d) { // 初始化list。entry = { (n)。entry, (n)。entry },// 回調函數。func = (f),// 回調函數參數。data = (d),// 初始化定時器。timer = TIMER_INITIALIZER(NULL, 0, 0),}

        // 聲明工作隊列并初始化#define DECLARE_WORK(n, f, d)

        struct work_struct n = __WORK_INITIALIZER(n, f, d)

        /* * initialize a work-struct's func and data pointers:*/ // 重新定義工作結構參數#define PREPARE_WORK(_work, _func, _data)

        do {(_work)->func = _func;(_work)->data = _data;} while (0)

        /* * initialize all of a work-struct:*/ // 初始化工作結構, 和__WORK_INITIALIZER功能相同,不過__WORK_INITIALIZER用在// 參數初始化定義, 而該宏用在程序之中對工作結構賦值#define INIT_WORK(_work, _func, _data)

        do { INIT_LIST_HEAD((_work)->entry);(_work)->pending = 0;PREPARE_WORK((_work), (_func), (_data));init_timer((_work)->timer);} while (0)

        4. 操作函數

        4.1 創建工作隊列

        一般的創建函數是create_workqueue, 但這其實只是一個宏:/* include/linux/workqueue.h */ #define create_workqueue(name) __create_workqueue((name), 0)

        在workqueue的初始化函數中, 定義了一個針對內核中所有線程可用的事件工作隊列, 其他內核線程建立的事件工作結構就都掛接到該隊列:void init_workqueues(void)

        {……

        keventd_wq = create_workqueue(events);……

        }

        核心創建函數是__create_workqueue:

        struct workqueue_struct *__create_workqueue(const char *name,int singlethread)

        { int cpu, destroy = 0;struct workqueue_struct *wq;struct task_struct *p;// 分配工作隊列結構空間wq = kzalloc(sizeof(*wq), GFP_KERNEL);if (!wq)

        return NULL;// 為每個CPU分配單獨的工作隊列空間wq->cpu_wq = alloc_percpu(struct cpu_workqueue_struct);if (!wq->cpu_wq) { kfree(wq);return NULL;} wq->name = name;mutex_lock(workqueue_mutex);if (singlethread) { // 使用create_workqueue宏時該參數始終為0 // 如果是單一線程模式, 在單線程中調用各個工作隊列// 建立一個的工作隊列內核線程INIT_LIST_HEAD(wq->list);// 建立工作隊列的線程p = create_workqueue_thread(wq, singlethread_cpu);if (!p)

        destroy = 1;else // 喚醒該線程wake_up_process(p);} else { // 鏈表模式, 將工作隊列添加到工作隊列鏈表list_add(wq->list, workqueues);// 為每個CPU建立一個工作隊列線程for_each_online_cpu(cpu) { p = create_workqueue_thread(wq, cpu);if (p) { // 綁定CPU kthread_bind(p, cpu);// 喚醒線程wake_up_process(p);} else destroy = 1;} mutex_unlock(workqueue_mutex);/* * Was there any error during startup? If yes then clean up:*/ if (destroy) { // 建立線程失敗, 釋放工作隊列destroy_workqueue(wq);wq = NULL;} return wq;} EXPORT_SYMBOL_GPL(__create_workqueue);

        // 創建工作隊列線程static struct task_struct *create_workqueue_thread(struct workqueue_struct *wq,int cpu)

        { // 每個CPU的工作隊列struct cpu_workqueue_struct *cwq = per_cpu_ptr(wq->cpu_wq, cpu);struct task_struct *p;spin_lock_init(cwq->lock);// 初始化cwq->wq = wq;cwq->thread = NULL;cwq->insert_sequence = 0;cwq->remove_sequence = 0;INIT_LIST_HEAD(cwq->worklist);// 初始化等待隊列more_work, 該隊列處理要執行的工作結構init_waitqueue_head(cwq->more_work);// 初始化等待隊列work_done, 該隊列處理執行完的工作結構init_waitqueue_head(cwq->work_done);// 建立內核線程work_thread if (is_single_threaded(wq))


        上一頁 1 2 3 4 下一頁

        關鍵詞:

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 金塔县| 琼结县| 安康市| 咸宁市| 海伦市| 平邑县| 客服| 安泽县| 兴化市| 绍兴县| 江陵县| 合川市| 日喀则市| 沙雅县| 平塘县| 筠连县| 横山县| 邵阳县| 凤城市| 大同市| 志丹县| 湘潭市| 东辽县| 台湾省| 合山市| 家居| 苍梧县| 深泽县| 县级市| 巧家县| 阿坝县| 疏附县| 土默特右旗| 广宗县| 铁岭县| 吉安县| 兴安县| 武胜县| 洛南县| 丽江市| 南木林县|