class_create() & device_create

本章節將介紹 class_create class_destroy 使用
========================================================================
struct class 定義在#include <linux/device.h>

1.宏class_create()
文件包含:#include<linux/device.h>

宏定義: 
   在內核源碼中位置:2.6.35-src/include/linux/device.h
  1. 310    #define class_create(owner, name) \
  2.  311   ({ \
  3.  312          static struct lock_class_key __key; \
  4.  313          __class_create(owner, name, &__key); \
  5.  314   })
功能描述:
    宏class_create()用於動態創建設備的邏輯類,並完成部分字段的初始化,然後將其添加進linux內核系統中。此函數的執行效果就是在目錄/sys/class/下創建一個新的文件夾,此文件夾的名字爲此函數的第二個輸入參數,單詞文件夾是空的。宏class_create()在實現時,調用了函數__class_create(),作用和函數__class_create()基本相同。

輸入參數說明:
    宏class_create()有兩個輸入參數
    宏owner是一個struct module結構體類型的指針,指向函數__class_create()即將創建的struct class類型對象的擁有者,一般賦值爲THIS_MODULE,詳細查看:src/include/linux/module.h
    參數name是char類型的指針,代表即將創建的struct class變量的名字

返回參數
    宏class_create()函數返回 struct class的邏輯類

2.函數class_destroy()
文件包含:#include <linux/device.h>

函數定義:
    函數實現: src/drivers/base/class.c
    函數定義格式: void class_destroy(struct class *cls);

==================================================================    
程序:簡單在內核中建立自己的動態設備邏輯類

附件代碼: class_create_destroy.rar   將rar修改爲tar.bz2
  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/kernel.h>

  4. #include <linux/device.h>//class_create

  5. struct class *mem_class;

  6. static int __init class_create_destroy_init(void)
  7. {
  8.     printk("class_create_destroy_init init..\n");
  9.     mem_class = class_create(THIS_MODULE,"ywx_dev");
  10.     if(IS_ERR(mem_class))
  11.     {
  12.         printk("err:failed create class\n");
  13.         return -1;
  14.     }
  15.     printk("class create suceess\n");
  16.     return 0;
  17. }

  18. static void __exit class_create_destroy_exit(void)
  19. {
  20.     printk("leaving class...\n");
  21.     class_destroy(mem_class);
  22.     printk("leaving finished.\n");
  23. }

  24. MODULE_LICENSE("GPL");
  25. module_init(class_create_destroy_init);
  26. module_exit(class_create_destroy_exit);
使用方法:
  1. root@ywx:/home/ywx/desktop/module/api_/class_create_destroy# insmod ./class_create_destroy.ko 
  2. root@ywx:/home/ywx/desktop/module/api_/class_create_destroy# dmesg | tail -8
  3. [ 2360.949466] class_create_destroy_init init..
  4. [ 2360.949956] class create suceess
  5. //在/sys/class/下生成我們自己建立的設備的邏輯類
  6. root@ywx:/home/ywx/desktop/module/api_/class_create_destroy# ls /sys/class | grep ywx
  7. ywx_dev
  8. root@ywx:/home/ywx/desktop/module/api_/class_create_destroy# rmmod class_create_destroy 
  9. root@ywx:/home/ywx/desktop/module/api_/class_create_destroy# dmesg | tail -8
  10. [ 2360.949466] class_create_destroy_init init..
  11. [ 2360.949956] class create suceess
  12. [ 2431.145922] leaving class...
  13. [ 2431.149030] leaving finished.
  14. root@ywx:/home/ywx/desktop/module/api_/class_create_destroy# ls /sys/class | grep ywx
  15. root@ywx:/home/ywx/desktop/module/api_/class_create_destroy#


前面章節“class 類 class_create class_destroy”瞭解了 class_create使用,這章節中介紹
device_create device_destroy使用,並通過這兩章節內容 自動建立備文件節點
========================================================================

1. device_create()
文件包含: #include <linux/device.h>

函數定義:
     函數位置: 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 <linux/device.h>

函數定義: 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的例子
====================================================================
自己的字符設備驅動程序
序代碼附加: 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.     //
  45.     mem_cdev = cdev_alloc();
  46.     if(mem_cdev == NULL)
  47.     {
  48.         printk("cdev_alloc error\n");
  49.         return -ENOMEM;
  50.     }
  51.     cdev_init(mem_cdev,&mem_fops);
  52.     mem_cdev->owner = THIS_MODULE;
  53.     ret = cdev_add(mem_cdev,devno,1);//將字符設備鍵入內核系統
  54.     if(ret)
  55.     {
  56.         cdev_del(mem_cdev);
  57.         mem_cdev = NULL;
  58.         printk("cdev_add error\n");
  59.         return -1;
  60.     }

  61.     //
  62.     mem_class = class_create(THIS_MODULE,"ywx_class_char");
  63.     if(IS_ERR(mem_class))
  64.     {
  65.         printk("class_create error..\n");
  66.         return -1;
  67.     }
  68.     device_create(mem_class,NULL,MKDEV(MEM_MAJOR,MEM_MINOR),NULL,"ywx_device_char");
  69.     
  70.     printk("init finished..\n");
  71.     return 0;
  72. }

  73. static void __exit mem_exit(void)
  74. {
  75.     printk("mem_exit starting..\n");
  76.     if(mem_cdev != NULL)
  77.         cdev_del(mem_cdev);
  78.     printk("cdev_del ok\n");

  79.     device_destroy(mem_class,MKDEV(MEM_MAJOR,MEM_MINOR));
  80.     class_destroy(mem_class);

  81.     if(mem_spvm != NULL)
  82.         vfree(mem_spvm);

  83.     printk("vfree ok\n");
  84.     printk("mem_exit finished..\n");
  85. }

  86. static int mem_open(struct inode *inode,struct file *filp)
  87. {
  88.     printk("open vmalloc space..\n");
  89.     try_module_get(THIS_MODULE);//模塊引用計數器自加
  90.     printk("open vamlloc space ok..\n");
  91.     return 0;
  92. }
  93. static int mem_release(struct inode *inode, struct file *filp)
  94. {
  95.     printk("close vmalloc space..\n");
  96.     module_put(THIS_MODULE);//模塊引用計數器自減
  97.     return 0;
  98. }
  99. static ssize_t mem_read(struct file *filp,char __user *buf,size_t count,loff_t *fpos)
  100. {
  101.     int ret = -1;
  102.     char *tmp;
  103.     printk("copy data to the user space\n");
  104.     tmp = mem_spvm;
  105.     if(count > MEM_MALLOC_SIZE)
  106.         count = MEM_MALLOC_SIZE;
  107.     if(tmp != NULL)//將內核數據寫入到用戶空間
  108.         ret = copy_to_user(buf,tmp,count);
  109.     if(ret == 0)
  110.     {
  111.         printk("read copy data success\n");
  112.         return count;
  113.     }
  114.     else
  115.     {
  116.         printk("read copy data error\n");
  117.         return 0;
  118.     }
  119. }
  120. static ssize_t mem_write(struct file *filp, char __user *buf,size_t count ,loff_t *fops)
  121. {
  122.     int ret = -1;
  123.     char *tmp;
  124.     printk("read data from the user space.\n");
  125.     tmp = mem_spvm;
  126.     if(count > MEM_MALLOC_SIZE)
  127.         count = MEM_MALLOC_SIZE;
  128.     if(tmp != NULL)
  129.         ret = copy_from_user(tmp,buf,count);
  130.     if(ret == 0)
  131.     {
  132.         printk("write copy data success.\n");
  133.         return count;
  134.     }
  135.     else
  136.     {
  137.         printk("write copy data error.\n");
  138.         return 0;    
  139.     }
  140. }

  141. MODULE_LICENSE("GPL");
  142. module_init(mem_init);
  143. 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.     
  19.     printf("input the data for kernel:");
  20.     scanf("%s",buf);
  21.     cnt = write(fd,buf,256);
  22.     if(cnt == 0)
  23.         printf("write error\n");
  24.     
  25.     printf("clear buf,and will read from kernel...\n");
  26.     for(i=0;i<256;i++)
  27.         buf[i] = 32;//32 =" "

  28.     cnt = read(fd,buf,256);
  29.     if(cnt > 0)
  30.         printf("read data from kernel is:%s\n",buf);
  31.     else
  32.         printf("read data error\n");
  33.     close(fd);
  34.     printf("close app..\n");
  35.     return 0;
  36. }
應用程序測試:
  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..

一些資料:







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章