****************************************===
****************************************===
《建立字元裝置的三種方法》這篇文章已經在網上廣為流傳,你可以在找到這篇文章的乙份拷貝,從瀏覽量上看定有許多人參考過這篇文章,但是很遺憾,它的第三種方法有乙個嚴重的問題,記憶體洩露!雖然大多數時候它跑的很好,而記憶體洩露導致系統崩潰也是幾無可能,但是這是乙個模板,如果大多數人在寫驅動時參考了這篇文章,並且不巧選擇了第三種,那麼潛在危險就有點大了,好了言歸正傳。
3.使用udev在/dev/下動態生成裝置檔案的方式
1. #include
2. #include
3. #include
4. #include
5. #include
6. #include
7. #include
8. #include
9. #include
10. #include
11. #include
12. #include
13. module_license("gpl"); /*此處如果不加的話載入的時候會出錯*/
14. int init_module(void);
15. void cleanup_module(void);
16. static int device_open(struct inode*, struct file*);
17. static int device_release(struct inode*, struct file*);
18. static ssize_t device_read(struct file*, char *, size_t, loff_t*);
19. static ssize_t device_write(struct file*, const char*, size_t, loff_t*);
20. #define success 0
21. #define device_name "chardev"
22. #define buf_len 80
23.24. static int major;
25. static int device_open = 0;
26. static char msg[buf_len];
27. static char *msg_ptr;
28. static struct cdev *my_cdev;
29. static struct class *my_class;
30. dev_t devid ;
31. static struct file_operations fops =
32. ;
38. int init_module(void)
39.
52. my_class = class_create(this_module, "chardev_class1");
53. if (is_err(my_class))
54.
58. class_device_create(my_class, null, devid, null, "chardev" "%d", minor(devid));
59. printk("major number is %d\n", major(devid));
60. return success;
61. }
62. void cleanup_module(void)
63.
69. ......
my_cdev = cdev_alloc();cdev_init(my_cdev, &fops);
注意到上面兩句話,申請cdev裝置,然後呼叫cdev_init,然後通過cdev_add新增到核心鍊錶中,沒錯啊,順理成章,但是如果你仔細看過ldd3,那麼你一定沒有見過書上這樣用,它的用法是:
1. cdev = cdev_alloc();
2. cdev->owner = this_module;
3. cdev->ops = fops;
問題的根本就是,乙個用了cdev_init,乙個沒有。比較一下和cdev_alloc和cdev_init的**:
1. struct cdev *cdev_alloc(void)
2. 8. return p;
9. }
1. void cdev_init(struct cdev *cdev, const struct file_operations *fops)
2. 注意到kobject_init的第二個引數struct kobj_type *ktype,其中的release函式會在cdev_del時被呼叫:
1. static struct kobj_type ktype_cdev_default = ;
4.5. static struct kobj_type ktype_cdev_dynamic = ;
繼續追蹤這兩個函式的實現:
1. static void cdev_default_release(struct kobject *kobj)
2. 6.
7. static void cdev_dynamic_release(struct kobject *kobj)
8. 注意到紅色部分的kfree。回顧前文,如果使用cdev_alloc動態申請裝置空間,此時釋放函式被安裝為 cdev_dynamic_release,到這裡還都沒錯,然後呼叫cdev_init,此時釋放函式被替換為了 cdev_default_release,最終模組解除安裝的時候,一段記憶體就這樣偷偷溜走了!
你可以嘗試在核心中搜尋cdev_alloc,然後看看使用它們的地方有沒有接著使用cdev_init,很遺憾,沒有,如果有,那麼快點報告該驅動的維護者吧,他應該看看ldd3了! ^^
世界又安靜了!
附乙個字元裝置驅動例項:
建立物件的三種方法
三種方式 利用字面量建立物件 物件字面量 就是花括號 裡面包含了表達這個具體事物 物件 的屬性和方法。var a 1.裡面的屬性或者方法我們採取鍵值對的形式鍵屬性名 值屬性值 2.多個屬性或者方法中間用逗號隔開的 3.方法冒號後面跟的是乙個匿名函式 使用物件 1.呼叫物件的屬性我們採取物件名.屬性名...
字元轉換的三種方法
遇到乙個問題 修改 js 中 parseint 的呼叫方式,使之實現 輸入 0x12 輸出 0 源 如下,原 能實現,輸入 12 輸出12,輸入 12px 輸出 12 但是對上面的要求不符合。function parse2int num 修改如下 function parse2int num js中...
pandas建立series三種方法
print 建立series方法一 dic s pd.series dic print s 建立方法一 由字典建立,字典的key就是index,values就是valuse key肯定是字串,假如values型別不止乙個會怎麼樣?dic series 建立方法二 由陣列建立 一維陣列 arr np....