​本文的copyright归yuweixian4230@163.com 所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。
作者:yuweixian


博客:
​yuweixian4230.blog.chinaunix.net ​ 

1. device_create()文件包含: #include 函数定义:     函数位置: src/drivers/base/core.c     函数格式:

  1. extern struct device *device_create(struct class​ ​*cls, struct device *parent,dev_t devt, void *drvdataconst char *fmt, ...)

函数功能:    函数device_create()用于动态的建立逻辑设备,并对新的逻辑设备类进行相应初始化,将其与函数的第一个参数所代表的逻辑类关联起来,然后将此逻辑设备加到linux内核系统的设备驱动程序模型中。函数能够自动在/sys/devices/virtual目录下创建新的逻辑设备目录,在/dev目录下创建于逻辑类对应的设备文件 参数说明:   struct class cls:与即将创建额逻辑设备相关的逻辑类,在“​​class类 class_create使用”​​说明了。   dev_t dev:设备号   void *drvdata: void类型的指针,代表回调函数的输入参数   const char *fmt: 逻辑设备的设备名,即在目录 /sys/devices/virtual创建的逻辑设备目录的目录名。 2.函数device_destroy()文件包含:#include 函数定义: src/drivers/base/core.c           void device_destroy(struct class *dev, dev_t devt); 函数功能:     函数device_destroy()用于从linux内核系统设备驱动程序模型中移除一个设备,并删除/sys/devices/virtual目录下对应的设备目录及/dev/目录下对应的设备文件 ====================================================================== class_create() 和 device_create()有什么关系呢?? 

在刚开始写Linux设备驱动程序的时候,很多时候都是利用mknod命令手动创建设备节点,实际上Linux内核为我们提供了一组函数,可以用来在模块加载的时候自动在/dev目录下创建相应设备节点,并在卸载模块时删除该节点,当然前提条件是用户空间移植了udev。什么事udev??请查看“  ​收集 3个介绍uedv 网址资料​  ”

内核中定义了struct class结构体,顾名思义,一个struct class结构体类型变量对应一个类,内核同时提供了class_create(…)函数,可以用它来创建一个类,这个类存放于sysfs下面,一旦创建好了这个类,再调用device_create(…)函数来在/dev目录下创建相应的设备节点。这样,加载模块的时候,用户空间中的udev会自动响应device_create(…)函数,去/sysfs下寻找对应的类从而创建设备节点。

在下面的例子中具体说明关系!!!!!!!!

1. 首先通过 ​  ​mem_class = class_create(THIS_MODULE,"ywx_class_char");​ ​语句建立了逻辑设备类,在​ ​ /sys/class/ ​ ​下新建了 ywx_class_char目录 查看:

  1. ywx@ywx​:/​sys​/class$​ls ywx_class_char
  2. ywx_device_char

2. 通过语句 ​ ​device_create(mem_class,NULL,MKDEV(MEM_MAJOR,MEM_MINOR),NULL,"ywx_device_char");​ ​阿在 ​ ​/dev/ ​ ​下自动建立了 ywx_device_char 设备节点 ,具体查看:

  1. ywx@ywx​:/​dev$ ls​-​l ywx_device_char
  2. crw​-------​1 root root​240, 0​2012​-​01​-​03 15​:​40​ywx_device_char

3.那么 class_create 和 device_create还有什么关系呢?? 在/sys/devices/virtual/建立了 “ywx_class_char”在/sys/devices/virtual/ywx/class/char/下建立了 ywx_device_char 目录

  1. ywx@ywx​:/​sys​/​devices​/​virtual​/​ywx_class_char​/​ywx_device_char$ ls​-​la
  2. total 0
  3. drwxr​-​xr​-​x 3 root root 0 2012​-​01​-​03 15​:​40​.
  4. drwxr​-​xr​-​x 3 root root 0 2012​-​01​-​03 15​:​40​..
  5. -​r​--​r​--​r​--​1 root root​4096​2012​-​01​-​03 16​:​10​dev 这个就是我们在驱动中分配的大小4KB
  6. drwxr​-​xr​-​x 2 root root 0 2012​-​01​-​03 16​:​10 power
  7. lrwxrwxrwx​1 root root 0 2012​-​01​-​03 15​:​40 subsystem​->../../../../class/ywx_class_char符号链接设备
  8. -​rw​-​r​--​r​--​1 root root 4096 2012​-​01​-​03 15​:​40 uevent

====================================================================== drivers/i2c/i2c-dev.c 也有关于 class_create的例子

​i2c_dev_class​​​ =  ​​class_create​​​( ​​THIS_MODULE​​,  ​"i2c-dev"​);

====================================================================自己的字符设备驱动程序​ ​序代码附加:​ ​ cdev_init_add_del.rar ​​   ​将rar修改为tar.bz2

  1. #include​<​linux​/​kernel​.​h​>
  2. #include​<​linux​/​module​.​h​>
  3. #include​<​linux​/​init​.​h​>
  4. #include​<​linux​/​cdev​.​h​>
  5. #include​<​linux​/​device​.​h​>
  6. #include​<​linux​/​slab​.​h​>//​kmalloc
  7. #include​<​linux​/​vmalloc​.​h​>//​vmalloc​()
  8. #include​<​linux​/​types​.​h​>//​ssize_t
  9. #include​<​linux​/​fs​.​h​>//​file_operaiotns
  10. #include​<​linux​/​uaccess​.​h​>//​copy_from_user
  11. #define MEM_MALLOC_SIZE 4096​////​缓冲区大小
  12. #define MEM_MAJOR    240​////​主设备号
  13. #define MEM_MINOR    0
  14. char​*​mem_spvm​=NULL;////​缓冲区指针,指向内存区
  15. struct cdev​*​mem_cdev​=NULL;//​字符设备对象指针
  16. struct​class*​mem_class​=NULL;//​设备类指针
  17. static​int​__init mem_init​(​void​);
  18. static void __exit mem_exit​(​void​);
  19. static​int​mem_open​(​struct inode​*​inode​,​struct file​*​filp​);
  20. static​int​mem_release​(​struct inode​*​inode​,​struct file​*​filp​);
  21. static ssize_t mem_read​(​struct file​*​filp​,​char __user​*​buf​,​size_t count​,​loff_t​*​fpos​);
  22. static ssize_t mem_write​(​struct file​*​filp​,​char __user​*​buf​,​size_t count​,​loff_t​*​fops​);
  23. static​const​struct file_operations mem_fops​={
  24. .​owner​=​THIS_MODULE​,
  25. .​open​=​mem_open​,
  26. .​release​=​mem_release​,
  27. .​read​=​mem_read​,
  28. .​write​=​mem_write​,
  29. };
  30. static​int​__init mem_init​(​void​)
  31. {
  32. int​ret​;
  33. //​创建设备号 主次设备号
  34. int​devno​=​MKDEV​(​MEM_MAJOR​,​MEM_MINOR​);
  35. printk​("mem_init initial...\n");
  36. //​开辟内核内存缓冲区
  37. mem_spvm​=(​char​*)​vmalloc​(​MEM_MALLOC_SIZE​);
  38. if(​mem_spvm​==NULL)
  39. {
  40. printk​("vmalloc mem_spvm error\n");
  41. return​-​ENOMEM​;//
  42. }
  43. //
  44. mem_cdev​=​cdev_alloc​();
  45. if(​mem_cdev​==NULL)
  46. {
  47. printk​("cdev_alloc error\n");
  48. return​-​ENOMEM​;
  49. }
  50. cdev_init​(​mem_cdev​,&​mem_fops​);
  51. mem_cdev​->​owner​=​THIS_MODULE​;
  52. ret​=​cdev_add​(​mem_cdev​,​devno​,​1​);//​将字符设备键入内核系统
  53. if(​ret​)
  54. {
  55. cdev_del​(​mem_cdev​);
  56. mem_cdev​=NULL;
  57. printk​("cdev_add error\n");
  58. return​-​1​;
  59. }
  60. //
  61. mem_class​=​class_create​(​THIS_MODULE​,"ywx_class_char");
  62. if(​IS_ERR​(​mem_class​))
  63. {
  64. printk​("class_create error..\n");
  65. return​-​1​;
  66. }
  67. device_create​(​mem_class​,NULL,​MKDEV​(​MEM_MAJOR​,​MEM_MINOR​),NULL,"ywx_device_char");
  68. printk​("init finished..\n");
  69. return 0​;
  70. }
  71. static void __exit mem_exit​(​void​)
  72. {
  73. printk​("mem_exit starting..\n");
  74. if(​mem_cdev​!=NULL)
  75. cdev_del​(​mem_cdev​);
  76. printk​("cdev_del ok\n");
  77. device_destroy​(​mem_class​,​MKDEV​(​MEM_MAJOR​,​MEM_MINOR​));
  78. class_destroy​(​mem_class​);
  79. if(​mem_spvm​!=NULL)
  80. vfree​(​mem_spvm​);
  81. printk​("vfree ok\n");
  82. printk​("mem_exit finished..\n");
  83. }
  84. static​int​mem_open​(​struct inode​*​inode​,​struct file​*​filp​)
  85. {
  86. printk​("open vmalloc space..\n");
  87. try_module_get​(​THIS_MODULE​);//​模块引用计数器自加
  88. printk​("open vamlloc space ok..\n");
  89. return 0​;
  90. }
  91. static​int​mem_release​(​struct inode​*​inode​,​struct file​*​filp​)
  92. {
  93. printk​("close vmalloc space..\n");
  94. module_put​(​THIS_MODULE​);//​模块引用计数器自减
  95. return 0​;
  96. }
  97. static ssize_t mem_read​(​struct file​*​filp​,​char __user​*​buf​,​size_t count​,​loff_t​*​fpos​)
  98. {
  99. int​ret​=-​1​;
  100. char​*​tmp​;
  101. printk​("copy data to the user space\n");
  102. tmp​=​mem_spvm​;
  103. if(​count​>​MEM_MALLOC_SIZE​)
  104. count​=​MEM_MALLOC_SIZE​;
  105. if(​tmp​!=NULL)//​将内核数据写入到用户空间
  106. ret​=​copy_to_user​(​buf​,​tmp​,​count​);
  107. if(​ret​==​0​)
  108. {
  109. printk​("read copy data success\n");
  110. return count​;
  111. }
  112. else
  113. {
  114. printk​("read copy data error\n");
  115. return 0​;
  116. }
  117. }
  118. static ssize_t mem_write​(​struct file​*​filp​,​char __user​*​buf​,​size_t count​,​loff_t​*​fops​)
  119. {
  120. int​ret​=-​1​;
  121. char​*​tmp​;
  122. printk​("read data from the user space.\n");
  123. tmp​=​mem_spvm​;
  124. if(​count​>​MEM_MALLOC_SIZE​)
  125. count​=​MEM_MALLOC_SIZE​;
  126. if(​tmp​!=NULL)
  127. ret​=​copy_from_user​(​tmp​,​buf​,​count​);
  128. if(​ret​==​0​)
  129. {
  130. printk​("write copy data success.\n");
  131. return count​;
  132. }
  133. else
  134. {
  135. printk​("write copy data error.\n");
  136. return 0​;
  137. }
  138. }
  139. MODULE_LICENSE​("GPL");
  140. module_init​(​mem_init​);
  141. module_exit​(​mem_exit​);

应用程序:

  1. #include​<​stdio​.​h​>
  2. #include​<​stdlib​.​h​>
  3. #include​<​unistd​.​h​>
  4. #include​<​fcntl​.​h​>
  5. #include​<string.​h​>//​memset​()
  6. int​main​(int​argc​,​char​*​argv​[])
  7. {
  8. int​fd​,​cnt​;
  9. char buf​[​256​];
  10. int​i​;
  11. printf​("char device testing..\n");
  12. fd​=​open​("/dev/ywx_device_char",​O_RDWR​);
  13. if(​fd​==​0​)
  14. {
  15. printf​("open failed.\n");
  16. return 1​;
  17. }
  18. printf​("input the data for kernel:");
  19. scanf​("%s",​buf​);
  20. cnt​=​write​(​fd​,​buf​,​256​);
  21. if(​cnt​==​0​)
  22. printf​("write error\n");
  23. printf​("clear buf,and will read from kernel...\n");
  24. for(​i​=​0​;​i​<​256​;​i​++)
  25. buf​[​i​]=​32​;//​32​=" "
  26. cnt​=​read​(​fd​,​buf​,​256​);
  27. if(​cnt​>​0​)
  28. printf​("read data from kernel is:%s\n",​buf​);
  29. else
  30. printf​("read data error\n");
  31. close​(​fd​);
  32. printf​("close app..\n");
  33. return 0​;
  34. }

应用程序测试:

  1. root@ywx​:/​home​/​ywx​/​desktop​/​module​/​api_​/​cdev_init_add_del​/​app#​./​app
  2. char device testing​..
  3. input the data​for​kernel​:yuweixian4230.blog.chinaunix.net
  4. clear buf​,and​will read from kernel​...
  5. read data from kernel​is:yuweixian4230.blog.chinaunix.net
  6. close app​..