1.06.2014

MOD_INC_USE_COUNT, MOD_DEC_USE_COUNT, try_module_get(), module_put()

好久好久都沒有來更新BLOG了,感覺這裡都快要荒廢了....

最近被公司交辦了一項任務,要開發一個新產品,這個新產品在技術上對我而言,比較困難的就是「要利用GPIO來模擬I2C」。

這是我之前沒有接觸過的,當然,被公司賦予這樣的工作,那表示我還有進步和成長的空間。

但是,我們軟體部偏偏沒有主管,由PM出身的技術長來代理;當時他是這麼交辦給我的「把linux-2.4x裡GPIO來模擬I2C的部份,把它Copy-Paste到linux-2.6.30就可以了!!」想當然爾,這種Driver Porting (驅動程式移植)的工作,不會像他講得這麼簡單。於是就有了這一篇文章的誕生。

當我在Study linux-2.4.x程式碼的時後,裡面有一段是這麼寫的:
int gpio_i2c_open(struct inode *indoe, struct file *file)
{
    MOD_INC_USE_COUNT;

    return 0;
}

int gpio_i2c_release(struct inode *indoe, struct file *file)
{
    MOD_DEC_USE_COUNT;
    kfree(indoe->i_private);
    kfree(file->private_data);

    return 0;
}
把這一段程式碼拷貝到linux-2.6.30的平台,當然是make不過。所以就上網Google一下,找找看這兩行程式碼在linux-2.4.x之中是幹嘛的。

講到這,就必須要瞭解到Linux Driver Programming中參考計數 (Reference Count)連結計數 (Link Count)之間的關係:

1. 刪除檔案會使得參考計數減一。
2. 打開檔案會使得參考計數加一。
3. 關閉檔案也會使得參考計數減一;當參考計數變成0的時後,如果連結計數也是0的話,才會真正地刪除檔案。

所以,簡言之,在linux-2.4.x中的MOD_INC_USE_COUNTMOD_DEC_USE_COUNT就是在做上述三件事。

假如,要移植到linux-2.6.30平台的話,該如何修改??
int gpio_i2c_open(struct inode *indoe, struct file *file)
{
    if (try_module_get(THIS_MODULE) == 0) // Failed!!
        printk(KERN_EMERG "%s: try_module_get() error!! \n", __func__);

    return 0;
}

int gpio_i2c_release(struct inode *indoe, struct file *file)
{
    module_put(THIS_MODULE);

    if ((file->private_data) != NULL)
        kfree((void *)(file->private_data));

    if ((indoe->i_private) != NULL)
        kfree((void *)(indoe->i_private));

    return 0;
}
來講解一下try_module_get()module_put()這兩個Linux Kernel API的用法。

定義:
1. static inline int try_module_get(struct module *module)
2. void module_put(struct module *module)

標頭檔:<linux/module.h>

功能描述:
1. try_module_get()該函數的功能是首先判斷模組module是否處於活動狀態,然後透過local_inc()巨集操作將模組module的參考計數加一。
2. module_put()的功能是將一個特定模組module的參考計數減一,這樣當一個模組的參考計數因為不為0而不能從核心中移除時,可以呼叫此函數一次或多次,實現對模組計數的歸零,從而實現模組移除。

輸入參數說明:module: 指向模組結構體的指標,結構體中包含模組的名稱、狀態、所屬的模組鏈結串列等等。

回傳值:
1. try_module_get()傳回值為一個整數值。如果模組module處於活動狀態且對其參考計數增加一的操作成功,則函數傳回1;否則傳回0。
2. module_put()該函數沒有傳回值。

沒有留言:

張貼留言