實驗名稱:
Linux 驅動程式開發 work queue
實驗目的:
介紹 work queue 在 Linux Kernel 裡面的作用與使用方式。
使用材料及設備:
硬體: Raspberry Pi B+
軟體: 可編譯 Linux Module 的 Raspbian 系統。
work queue 和 tasklet 的主要功用是類似的,就是向系統核心註冊一個工作,系統核心會把該工作排進去它的行程表之中,並等到適當的時機去處理這個被註冊的工作。但 tasklet 通常是和中斷服務程式配合使用,而 work queue 則是設計給一般的工作排程所使用。
程式碼說明
程式碼內容
------------------CODE---------------------
------------------CODE---------------------
程式碼架構
此模組的架構包含了模組的進入點函式和離開點函式。進入點函式為my_init() 由系統模組工具函式 module_init() 註冊進去系統核心之中。離開點函式則由系統模組工具函式module_exit() 註冊進去系統核心之中。
使用到 work queue 時必須宣告資料型態為 struct work_struct 的全域變數,這邊我們使用的變數名稱為 workq 。
而此 workq 在宣告之後使用之前必須先變過初始化動作,此初始化的動作我們在函式 my_init() 之中進行,初始化可利用系統核心工具巨集 INIT_WORK() 所完成。
在 workq 用 INIT_WORK() 初始化之時,須指定一個函式指標 ( 當系統排程至 workq 執行時會去呼叫該函式),此範例將函式 my_workqueue_handler() 指定給 workq。
程式碼說明
此範例示範了 Linux 核心中 work queue 的簡易使用。一開始載入模組之後,直接就初始化 workq ,並指定自定函式 my_workqueue_handler() 。而初始化完之後,就註冊進去系統核心之中。註冊完之後,核心會在眾多工作排程之中輪到執行 workq 之時去呼叫 my_workqueue_handler() ,所以觀察下面的執行結果可以看到,my_workqueue_handler() 是在模組完成函式 my_init() 的執行之後才去執行的。
INIT_WORK( &workq , my_workqueue_handler ) ,此行程式碼為系統工具巨集,第一個參數必須傳入一個資料型態為 struct work_queue 的變數的指標。此變數代表一個工作排程。而第二個參數 my_workqueue_handler 則為一個函式指標。其資料型態必須為:
void (*)(struct work_queue *)
在這行程式碼中,會被指定給 workq 。如果系統核心會透過 workq 來呼叫該函式指標。將 workq 排進核心的工作排程是由系統核心工具函式 schedule_work(&workq) 來完成,其傳入的資料必須為 struct work_queue * 。
為了幫助理解,可以想像一種情境: 假設有一個工程師放假想要整天在家看電影,該位工程師準備了一張張的標籤,每張標籤上面都寫了一部電影名字。然後對這些標籤進行排列組合成一張清單,來安排電影播放順序。此時,宣告為 struct work_queue 的 workq 就是一張標籤,而 my_workqueue_handler 就是這張標籤上的電影名稱。在播放任何時候,都可以插入該張標籤進去播放清單之中的任何地方,並依序一部部電影播放下去,總會有輪到該張標籤然後去播放其指定的電影。
執行結果:
實驗名稱:
實驗目的:
使用材料及設備:
work queue 和 tasklet 的主要功用是類似的,就是向系統核心註冊一個工作,系統核心會把該工作排進去它的行程表之中,並等到適當的時機去處理這個被註冊的工作。但 tasklet 通常是和中斷服務程式配合使用,而 work queue 則是設計給一般的工作排程所使用。
程式碼說明
程式碼內容
------------------CODE---------------------
程式碼架構
此模組的架構包含了模組的進入點函式和離開點函式。進入點函式為my_init() 由系統模組工具函式 module_init() 註冊進去系統核心之中。離開點函式則由系統模組工具函式module_exit() 註冊進去系統核心之中。
使用到 work queue 時必須宣告資料型態為 struct work_struct 的全域變數,這邊我們使用的變數名稱為 workq 。
而此 workq 在宣告之後使用之前必須先變過初始化動作,此初始化的動作我們在函式 my_init() 之中進行,初始化可利用系統核心工具巨集 INIT_WORK() 所完成。
在 workq 用 INIT_WORK() 初始化之時,須指定一個函式指標 ( 當系統排程至 workq 執行時會去呼叫該函式),此範例將函式 my_workqueue_handler() 指定給 workq。
程式碼說明
此範例示範了 Linux 核心中 work queue 的簡易使用。一開始載入模組之後,直接就初始化 workq ,並指定自定函式 my_workqueue_handler() 。而初始化完之後,就註冊進去系統核心之中。註冊完之後,核心會在眾多工作排程之中輪到執行 workq 之時去呼叫 my_workqueue_handler() ,所以觀察下面的執行結果可以看到,my_workqueue_handler() 是在模組完成函式 my_init() 的執行之後才去執行的。
INIT_WORK( &workq , my_workqueue_handler ) ,此行程式碼為系統工具巨集,第一個參數必須傳入一個資料型態為 struct work_queue 的變數的指標。此變數代表一個工作排程。而第二個參數 my_workqueue_handler 則為一個函式指標。其資料型態必須為:
void (*)(struct work_queue *)
在這行程式碼中,會被指定給 workq 。如果系統核心會透過 workq 來呼叫該函式指標。將 workq 排進核心的工作排程是由系統核心工具函式 schedule_work(&workq) 來完成,其傳入的資料必須為 struct work_queue * 。
為了幫助理解,可以想像一種情境: 假設有一個工程師放假想要整天在家看電影,該位工程師準備了一張張的標籤,每張標籤上面都寫了一部電影名字。然後對這些標籤進行排列組合成一張清單,來安排電影播放順序。此時,宣告為 struct work_queue 的 workq 就是一張標籤,而 my_workqueue_handler 就是這張標籤上的電影名稱。在播放任何時候,都可以插入該張標籤進去播放清單之中的任何地方,並依序一部部電影播放下去,總會有輪到該張標籤然後去播放其指定的電影。
沒有留言 :
張貼留言