代码

  1. #include <linux/module.h>
  2. #include <linux/fs.h>
  3. #include <linux/uaccess.h>
  4. #include <linux/init.h>
  5. #include <linux/cdev.h>
  6. #define DEMO_NAME "my_demo_dev"
  7. static dev_t dev;
  8. static struct cdev *demo_cdev;
  9. static signed count = 1;
  10. static int demodrv_open(struct inode *inode, struct file *file)
  11. {
  12. int major = MAJOR(inode->i_rdev);
  13. int minor = MINOR(inode->i_rdev);
  14. printk("%s: major=%d, minor=%d\n", __func__, major, minor);
  15. return 0;
  16. }
  17. static int demodrv_release(struct inode *inode, struct file *file)
  18. {
  19. return 0;
  20. }
  21. static ssize_t
  22. demodrv_read(struct file *file, char __user *buf, size_t lbuf, loff_t *ppos)
  23. {
  24. printk("%s enter\n", __func__);
  25. return 0;
  26. }
  27. static ssize_t
  28. demodrv_write(struct file *file, const char __user *buf, size_t count, loff_t *f_pos)
  29. {
  30. printk("%s enter\n", __func__);
  31. return 0;
  32. }
  33. static const struct file_operations demodrv_fops = {
  34. .owner = THIS_MODULE,
  35. .open = demodrv_open,
  36. .release = demodrv_release,
  37. .read = demodrv_read,
  38. .write = demodrv_write
  39. };
  40. static int __init simple_char_init(void)
  41. {
  42. int ret;
  43. ret = alloc_chrdev_region(&dev, 0, count, DEMO_NAME);
  44. if (ret) {
  45. printk("failed to allocate char device region");
  46. return ret;
  47. }
  48. demo_cdev = cdev_alloc();
  49. if (!demo_cdev) {
  50. printk("cdev_alloc failed\n");
  51. goto unregister_chrdev;
  52. }
  53. cdev_init(demo_cdev, &demodrv_fops);
  54. ret = cdev_add(demo_cdev, dev, count);
  55. if (ret) {
  56. printk("cdev_add failed\n");
  57. goto cdev_fail;
  58. }
  59. printk("succeeded register char device: %s\n", DEMO_NAME);
  60. printk("Major number = %d, minor number = %d\n",
  61. MAJOR(dev), MINOR(dev));
  62. return 0;
  63. cdev_fail:
  64. cdev_del(demo_cdev);
  65. unregister_chrdev:
  66. unregister_chrdev_region(dev, count);
  67. return ret;
  68. }
  69. static void __exit simple_char_exit(void)
  70. {
  71. printk("removing device\n");
  72. if (demo_cdev)
  73. cdev_del(demo_cdev);
  74. unregister_chrdev_region(dev, count);
  75. }
  76. module_init(simple_char_init);
  77. module_exit(simple_char_exit);
  78. MODULE_LICENSE("GPL");
  79. MODULE_AUTHOR("zhouchengzhu <1073355312@qq.com>");
  80. MODULE_DESCRIPTION("A simple hello world driver");
  81. MODULE_VERSION("2:1.0");

使用

  1. [root@imx6ull:~/NFS]# insmod simple_char.ko
  2. Major number = 245, minor number = 0
  3. [root@imx6ull:~/NFS]# cat /proc/devices | grep my_demo_dev
  4. 245 my_demo_dev
  5. # 然后我们查看/dev/下是否存在 主设备号 245 的设备
  6. [root@imx6ull:~/NFS]# ls -al /dev | grep 245
  7. # 发现并没对应主设备号的设备
  8. # 那么我们自动手动创建两个
  9. # 设备名称为 demo_drv 字符设备 主设备号 245 次设备号 0
  10. [root@imx6ull:~/NFS]# mknod /dev/demo_drv c 245 0
  11. [root@imx6ull:~/NFS]# mknod /dev/demo_drv1 c 245 1

上面我们创建了设备,现在可以使用设备了。使用下面的测试用例测试

  1. # 输出了主次设备号
  2. [root@imx6ull:~/NFS]# ./test
  3. demodrv_open: major=245, minor=0

测试用例

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

使用函数简介

  1. fs/char_dev.c:214
  2. int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
  3. const char *name)
  4. void unregister_chrdev_region(dev_t from, unsigned count)
  5. struct cdev *cdev_alloc(void)
  6. void cdev_init(struct cdev *cdev, const struct file_operations *fops)
  7. int cdev_add(struct cdev *p, dev_t dev, unsigned count)
  8. void cdev_del(struct cdev *p)

下一篇文章我们将会来分析一下使用到的这些函数。