天天看點

linux 同步機制之complete【轉】

要使用completion,必須在檔案中包含<linux/completion.h>,同時建立一個類型為struct completion的變量。

這個變量可以靜态地聲明和初始化:  

DECLARE_COMPLETION(my_comp);  

或者動态初始化:  

struct completion my_comp;  

init_completion(&my_comp);  

如果驅動程式要在執行後面操作之前等待某個過程的完成,它可以調用wait_for_completion ,以要完成的事件為參數:

void wait_for_completion(struct completion *comp);  

wait_for_completion等待在completion上。如果加了interruptible,就表示線程等待可被外部發來的信号打斷;如果加了killable,就表示線程隻可被kill信号打斷;如果加了timeout,表示等待超出一定時間會自動結束等待,timeout的機關是系統所用的時間片jiffies(多為1ms)。

如果其它部分代碼可以确定事件已經完成,可以調用下面兩個函數之一來喚醒等待該事件的程序:

void complete(struct completion *comp);  

void complete_all(struct completion *comp); /* Linux 2.5.x以上版本 */  

前一個函數将隻喚醒一個等待程序,而後一個函數喚醒等待該事件的是以程序。由于completion的實作方式,即使complete在wait_for_competion之前調用,也可以正常工作。

例如,在MD裝置驅動程式實作中,有一個恢複線程md_recovery_thread。驅動程式通過md_register_thread和md_unregister_thread來注冊和登出恢複線程。恢複線程的執行邏輯在md_thread函數中,大緻如下:

int md_thread(void * arg)  

{  

    線程初始化;  

    while (運作) {  

        處理邏輯;  

        接收信号;  

    }  

    return 0;  

}  

md_register_thread将建立一個恢複線程,它必須線上程真正初始化結束之後才能傳回該線程的指針。是以,其邏輯是:

mdk_thread_t *md_register_thread(void (*run) (void *), void *data, const char *name)  

    mdk_thread_t *thread;  

    ……  

    struct completion event;  

    /* 為線程配置設定空間 */  

    thread = (mdk_thread_t *) kmalloc (sizeof(mdk_thread_t), GFP_KERNEL);  

    init_completion(&event);  

    thread->event = &event;  

    /* 建立核心線程 */  

    ret = kernel_thread(md_thread, thread, 0);  

    /* 等待線程初始化結束 */  

    wait_for_completion(&event);  

    /* 傳回線程指針 */  

    return thread;  

而md_unregister_thread通過向線程發送SIGKILL信号登出恢複線程,它也需要線上程真正退出後才能釋放線程所占用的記憶體。是以,其邏輯是:

void md_unregister_thread(mdk_thread_t *thread)  

    /* 向線程發送SIGKILL信号終止其運作 */  

    md_interrupt_thread(thread);  

    /* 等待線程退出 */  

    /* 釋放線程所占用的記憶體 */  

    kfree(thread);  

如果考慮completion,md_thread的邏輯是:

    complete(thread->event);   

需要說明的是,由于等待事件是在驅動程式和恢複線程中的一個共享資源,它必須是一個全局變量,或者如實作代碼中,定義為一個局部變量,而将其指針放在恢複線程結構中。

typedef struct mdk_thread_s {

    ……

    struct completion *event;

} mdk_thread_t;

【新浪微網誌】 張昺華--sky

【twitter】 @sky2030_

【facebook】 張昺華 zhangbinghua

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利.

繼續閱讀