歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Linux驅動修煉之道-混雜設備

Linux驅動修煉之道-混雜設備

日期:2017/3/1 10:22:31   编辑:Linux編程

在Linux驅動中把無法歸類的五花八門的設備定義為混雜設備(用miscdevice結構體表述)。miscdevice共享一個主設備號MISC_MAJOR(即10),但次設備號不同。 所有的miscdevice設備形成了一個鏈表,對設備訪問時內核根據次設備號查找對應的miscdevice設備,然後調用其file_operations結構中注冊的文件操作接口進行操作。 在內核中用struct miscdevice表示miscdevice設備,然後調用其file_operations結構中注冊的文件操作接口進行操作。miscdevice的API實現在drivers/char/misc.c中。

下邊是描述這個設備的結構體:

  1. struct miscdevice {
  2. int minor; //次設備號
  3. const char *name; //設備的名稱
  4. const struct file_operations *fops; //文件操作
  5. struct list_head list; //misc_list的鏈表頭
  6. struct device *parent; //父設備(Linux設備模型中的東東了,哈哈)
  7. struct device *this_device; //當前設備,是device_create的返回值,下邊會看到
  8. };

然後來看看misc子系統的初始化函數:

  1. static int __init misc_init(void)
  2. {
  3. int err;
  4. #ifdef CONFIG_PROC_FS
  5. /*創建一個proc入口項*/
  6. proc_create("misc", 0, NULL, &misc_proc_fops);
  7. #endif
  8. /*在/sys/class/目錄下創建一個名為misc的類*/
  9. misc_class = class_create(THIS_MODULE, "misc");
  10. err = PTR_ERR(misc_class);
  11. if (IS_ERR(misc_class))
  12. goto fail_remove;
  13. err = -EIO;
  14. /*注冊設備,其中設備的主設備號為MISC_MAJOR,為10。設備名為misc,misc_fops是操作函數的集合*/
  15. if (register_chrdev(MISC_MAJOR,"misc",&misc_fops))
  16. goto fail_printk;
  17. return 0;
  18. fail_printk:
  19. printk("unable to get major %d for misc devices/n", MISC_MAJOR);
  20. class_destroy(misc_class);
  21. fail_remove:
  22. remove_proc_entry("misc", NULL);
  23. return err;
  24. }
  25. /*misc作為一個子系統被注冊到linux內核中*/
  26. subsys_initcall(misc_init);

下邊是register_chrdev函數的實現:

  1. int register_chrdev(unsigned int major, const char *name,
  2. const struct file_operations *fops)
  3. {
  4. struct char_device_struct *cd;
  5. struct cdev *cdev;
  6. char *s;
  7. int err = -ENOMEM;
  8. /*主設備號是10,次設備號為從0開始,分配256個設備*/
  9. cd = __register_chrdev_region(major, 0, 256, name);
  10. if (IS_ERR(cd))
  11. return PTR_ERR(cd);
  12. /*分配字符設備*/
  13. cdev = cdev_alloc();
  14. if (!cdev)
  15. goto out2;
  16. cdev->owner = fops->owner;
  17. cdev->ops = fops;
  18. /*Linux設備模型中的,設置kobject的名字*/
  19. kobject_set_name(&cdev->kobj, "%s", name);
  20. for (s = strchr(kobject_name(&cdev->kobj),'/'); s; s = strchr(s, '/'))
  21. *s = '!';
  22. /*把這個字符設備注冊到系統中*/
  23. err = cdev_add(cdev, MKDEV(cd->major, 0), 256);
  24. if (err)
  25. goto out;
  26. cd->cdev = cdev;
  27. return major ? 0 : cd->major;
  28. out:
  29. kobject_put(&cdev->kobj);
  30. out2:
  31. kfree(__unregister_chrdev_region(cd->major, 0, 256));
  32. return err;
  33. }
Copyright © Linux教程網 All Rights Reserved