最近被公司交辦了一項任務,要開發一個新產品,這個新產品在技術上對我而言,比較困難的就是「要利用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_COUNT和MOD_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()該函數沒有傳回值。
沒有留言:
張貼留言