Linux字符设备驱动基础(三)

- 日理万妓 2022-01-22 10:13 351阅读 0赞

Linux字符设备驱动基础(三)

6 创建设备节点

6.1 手动创建设备节点

查看申请的设备名及主设备号:

  1. cat /proc/devices
  2. # cat /proc/devices
  3. Character devices:
  4. 1 mem
  5. 2 pty
  6. 3 ttyp
  7. 4 /dev/vc/0
  8. 4 tty
  9. 5 /dev/tty
  10. 5 /dev/console
  11. 5 /dev/ptmx
  12. 7 vcs
  13. 10 misc
  14. 11 module_test
  15. Block devices:
  16. 8 sd
  17. 93 spinor
  18. 259 blkext

Mknod用法:

  1. # mknod
  2. BusyBox v1.27.1 (2018-10-22 13:38:05 CST) multi-call binary.
  3. Usage: mknod [-m MODE] NAME TYPE MAJOR MINOR
  4. Create a special file (block, character, or pipe)
  5. -m MODE Creation mode (default a=rw)
  6. TYPE:
  7. b Block device
  8. c or u Character device
  9. p Named pipe (MAJOR and MINOR are ignored)
  10. 如:mknod module_test b 11 0

6.2 自动创建设备节点

利用udev(mdev)来实现设备文件的自动创建,首先应保证支持udev(mdev),由busybox配置。

在驱动用加入对udev 的支持主要做的就是:在驱动初始化的代码里调用class_create(…)为该设备创建一个class,再为每个设备调用device_create(…)创建对应的设备。

内核中定义的struct class结构体,顾名思义,一个struct class结构体类型变量对应一个类,内核同时提供了class_create(…)函数,可以用它来创建一个类,这个类存放于sysfs下面,一旦创建好了这个类,再调用 device_create(…)函数来在/dev目录下创建相应的设备节点。

这样,加载模块的时候,用户空间中的udev会自动响应 device_create()函数,去/sysfs下寻找对应的类从而创建设备节点。
第一步:创建class类

  1. Struct class chardev_test_class = class_create(THIS_MODULE, CHARDEV_DRV_NAME);

源码如下:

  1. /* This is a #define to keep the compiler from merging different
  2. * instances of the __key variable */
  3. #define class_create(owner, name) \
  4. ({ \
  5. static struct lock_class_key __key; \
  6. __class_create(owner, name, &__key); \
  7. })
  8. 参数:
  9. -OwnerTHIS_MODULE
  10. -Nameclass name
  11. /**
  12. * class_create - create a struct class structure
  13. * @owner: pointer to the module that is to "own" this struct class
  14. * @name: pointer to a string for the name of this class.
  15. * @key: the lock_class_key for this class; used by mutex lock debugging
  16. *
  17. * This is used to create a struct class pointer that can then be used
  18. * in calls to device_create().
  19. *
  20. * Returns &struct class pointer on success, or ERR_PTR() on error.
  21. *
  22. * Note, the pointer created here is to be destroyed when finished by
  23. * making a call to class_destroy().
  24. */
  25. struct class *__class_create(struct module *owner, const char *name,
  26. struct lock_class_key *key)
  27. {
  28. struct class *cls;
  29. int retval;
  30. cls = kzalloc(sizeof(*cls), GFP_KERNEL);
  31. if (!cls) {
  32. retval = -ENOMEM;
  33. goto error;
  34. }
  35. cls->name = name;
  36. cls->owner = owner;
  37. cls->class_release = class_create_release;
  38. retval = __class_register(cls, key);
  39. if (retval)
  40. goto error;
  41. return cls;
  42. error:
  43. kfree(cls);
  44. return ERR_PTR(retval);
  45. }

class销毁函数:

  1. /**
  2. * class_destroy - destroys a struct class structure
  3. * @cls: pointer to the struct class that is to be destroyed
  4. *
  5. * Note, the pointer to be destroyed must have been created with a call
  6. * to class_create().
  7. */
  8. void class_destroy(struct class *cls)
  9. {
  10. if ((cls == NULL) || (IS_ERR(cls)))
  11. return;
  12. class_unregister(cls);
  13. }

第二步:创建device

  1. Struct device *dev = device_create(chardev_test_class, &pdev->dev,
  2. MKDEV(major, minor), NULL,
  3. CHARDEV_DRV_NAME);
  4. 参数:
  5. -class:该设备需绑定的class类;
  6. -parent:该设备的父设备;
  7. -devt:该设备的设备号;
  8. -drvdata:设备私有参数;
  9. -fmt 设备名
  10. /**
  11. * device_create - creates a device and registers it with sysfs
  12. * @class: pointer to the struct class that this device should be registered to
  13. * @parent: pointer to the parent struct device of this new device, if any
  14. * @devt: the dev_t for the char device to be added
  15. * @drvdata: the data to be added to the device for callbacks
  16. * @fmt: string for the device's name
  17. *
  18. * This function can be used by char device classes. A struct device
  19. * will be created in sysfs, registered to the specified class.
  20. *
  21. * A "dev" file will be created, showing the dev_t for the device, if
  22. * the dev_t is not 0,0.
  23. * If a pointer to a parent struct device is passed in, the newly created
  24. * struct device will be a child of that device in sysfs.
  25. * The pointer to the struct device will be returned from the call.
  26. * Any further sysfs files that might be required can be created using this
  27. * pointer.
  28. *
  29. * Returns &struct device pointer on success, or ERR_PTR() on error.
  30. *
  31. * Note: the struct class passed to this function must have previously
  32. * been created with a call to class_create().
  33. */
  34. struct device *device_create(struct class *class, struct device *parent,
  35. dev_t devt, void *drvdata, const char *fmt, ...)
  36. {
  37. va_list vargs;
  38. struct device *dev;
  39. va_start(vargs, fmt);
  40. dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs);
  41. va_end(vargs);
  42. return dev;
  43. }

设备销毁函数:

  1. /**
  2. * device_destroy - removes a device that was created with device_create()
  3. * @class: pointer to the struct class that this device was registered with
  4. * @devt: the dev_t of the device that was previously registered
  5. *
  6. * This call unregisters and cleans up a device that was created with a
  7. * call to device_create().
  8. */
  9. void device_destroy(struct class *class, dev_t devt)
  10. {
  11. struct device *dev;
  12. dev = class_find_device(class, NULL, &devt, __match_devt);
  13. if (dev) {
  14. put_device(dev);
  15. device_unregister(dev);
  16. }
  17. }

发表评论

表情:
评论列表 (有 0 条评论,351人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Linux字符设备驱动基础(二)

    Linux字符设备驱动基础(二) 5 设备号相关操作 设备号由主设备号和次设备号组成。主设备号用来标识与设备文件相连的驱动程序,用以反映设备类型;次设备号是用于驱动