建立字元裝置的三種方法

2021-06-05 16:54:58 字數 3000 閱讀 2022

****************************************===

****************************************===

《建立字元裝置的三種方法》這篇文章已經在網上廣為流傳,你可以在找到這篇文章的乙份拷貝,從瀏覽量上看定有許多人參考過這篇文章,但是很遺憾,它的第三種方法有乙個嚴重的問題,記憶體洩露!雖然大多數時候它跑的很好,而記憶體洩露導致系統崩潰也是幾無可能,但是這是乙個模板,如果大多數人在寫驅動時參考了這篇文章,並且不巧選擇了第三種,那麼潛在危險就有點大了,好了言歸正傳。

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....