源码

  1. /*mydemodrv_misc.c*/
  2. #include <linux/module.h>
  3. #include <linux/fs.h>
  4. #include <linux/uaccess.h>
  5. #include <linux/init.h>
  6. #include <linux/miscdevice.h>
  7. #define DEMO_NAME "my_demo_dev"
  8. static struct device *mydemodrv_device;
  9. static int demodrv_open(struct inode *inode, struct file *file)
  10. {
  11. int major = MAJOR(inode->i_rdev);
  12. int minor = MINOR(inode->i_rdev);
  13. printk("%s: major=%d, minor=%d\n", __func__, major, minor);
  14. return 0;
  15. }
  16. static int demodrv_release(struct inode *inode, struct file *file)
  17. {
  18. return 0;
  19. }
  20. static ssize_t
  21. demodrv_read(struct file *file, char __user *buf, size_t lbuf, loff_t *ppos)
  22. {
  23. printk("%s enter\n", __func__);
  24. return 0;
  25. }
  26. static ssize_t
  27. demodrv_write(struct file *file, const char __user *buf, size_t count, loff_t *f_pos)
  28. {
  29. printk("%s enter\n", __func__);
  30. return 0;
  31. }
  32. static const struct file_operations demodrv_fops = {
  33. .owner = THIS_MODULE,
  34. .open = demodrv_open,
  35. .release = demodrv_release,
  36. .read = demodrv_read,
  37. .write = demodrv_write
  38. };
  39. static struct miscdevice mydemodrv_misc_device = {
  40. .minor = MISC_DYNAMIC_MINOR,
  41. .name = DEMO_NAME,
  42. .fops = &demodrv_fops,
  43. };
  44. static int __init simple_char_init(void)
  45. {
  46. int ret;
  47. ret = misc_register(&mydemodrv_misc_device);
  48. if (ret) {
  49. printk("failed register misc device\n");
  50. return ret;
  51. }
  52. mydemodrv_device = mydemodrv_misc_device.this_device;
  53. printk("succeeded register char device: %s\n", DEMO_NAME);
  54. return 0;
  55. }
  56. static void __exit simple_char_exit(void)
  57. {
  58. printk("removing device\n");
  59. misc_deregister(&mydemodrv_misc_device);
  60. }
  61. module_init(simple_char_init);
  62. module_exit(simple_char_exit);
  63. MODULE_LICENSE("GPL");
  64. MODULE_AUTHOR("zhouchengzhu <1073355312@qq.com>");
  65. MODULE_DESCRIPTION("A simple hello world driver");
  66. MODULE_VERSION("2:1.0");

测试用例

  1. #include <stdio.h>
  2. #include <fcntl.h>
  3. #include <unistd.h>
  4. #define DEMO_DEV_NAME "/dev/my_demo_dev"
  5. int main()
  6. {
  7. char buffer[64];
  8. int fd;
  9. fd = open(DEMO_DEV_NAME, O_RDONLY);
  10. if (fd < 0) {
  11. printf("open device %s failded\n", DEMO_DEV_NAME);
  12. return -1;
  13. }
  14. read(fd, buffer, 64);
  15. close(fd);
  16. return 0;
  17. }

使用

  1. [root@imx6ull:~/NFS]# insmod mydemodrv_misc.ko
  2. succeeded register char device: my_demo_dev
  3. [root@imx6ull:~/NFS]# ./test.run
  4. demodrv_open: major=10, minor=56
  5. demodrv_read enter

设备分析

misc字符设备,又称为杂项设备,内核首先把不符合预先确定得字符设备划分为杂项设备。这一类设备得主设备号就是 10。使用得结构体

misc设备

  1. struct miscdevice {
  2. int minor;
  3. const char *name;
  4. const struct file_operations *fops;
  5. struct list_head list;
  6. struct device *parent;
  7. struct device *this_device;
  8. const struct attribute_group **groups;
  9. const char *nodename;
  10. umode_t mode;
  11. };

对应得API

这两个函数用作创建misc字符设备。

  1. extern int misc_register(struct miscdevice *misc);
  2. extern void misc_deregister(struct miscdevice *misc);

参考资料

各种杂项设备文档
linux MISC 驱动模型分析