Chinaunix首页 | 论坛 | 博客
  • 博客访问: 170881
  • 博文数量: 78
  • 博客积分: 30
  • 博客等级: 民兵
  • 技术积分: 287
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-24 02:49
文章分类
文章存档

2013年(23)

2012年(55)

分类:

2012-08-26 21:49:25

内核在内部使用类型 struct cdev 的结构来代表字符设备. 在内核调用你的设备操作前, 你编写分配并注册一个或几个这些结构.

2 种方法来分配和初始化一个这些结构. 如果你想在运行时获得一个独立的 cdev 结构, 你可以为此使用这样的代码:

struct cdev *my_cdev = cdev_alloc();my_cdev->ops = &my_fops;

但是, 偶尔你会想将 cdev 结构嵌入一个你自己的设备特定的结构; scull 这样做了. 在这种情况下, 你应当初始化你已经分配的结构, 使用:

void cdev_init(struct cdev *cdev, struct file_operations *fops);

任一方法, 有一个其他的 struct cdev 成员你需要初始化. file_operations 结构, struct cdev 有一个拥有者成员, 应当设置为 THIS_MODULE. 一旦 cdev 结构建立, 最后的步骤是把它告诉内核, 调用:

int cdev_add(struct cdev *dev, dev_t num, unsigned int count);

dev cdev 结构, num 是这个设备响应的第一个设备号, count 是应当关联到设备的设备号的数目. 常常 count 1, 但是有多个设备号对应于一个特定的设备的情形. 例如, 设想 SCSI 磁带驱动, 它允许用户空间来选择操作模式(例如密度), 通过安排多个次编号给每一个物理设备.

在使用 cdev_add 是有几个重要事情要记住. 第一个是这个调用可能失败. 如果它返回一个负的错误码, 你的设备没有增加到系统中. 它几乎会一直成功, 但是, 并且带起了其他的点: cdev_add 一返回, 你的设备就是"活的"并且内核可以调用它的操作. 除非你的驱动完全准备好处理设备上的操作, 你不应当调用 cdev_add.

为从系统去除一个字符设备, 调用:

void cdev_del(struct cdev *dev);

点击(此处)折叠或打开

  1. /**
  2.  * 注册设备
  3.  * Lzy     2012\7\24
  4.  */

  5. #include <linux/init.h>
  6. #include <linux/module.h>
  7. #include <linux/kernel.h>
  8. #include <linux/fs.h>
  9. #include <linux/cdev.h>
  10. #include <linux/slab.h>    

  11. #include "hello.h"

  12. /************************* 设备号 ******************************/
  13. int mem_major = MEMDEV_MAJOR;    /* 定义主设备号 */
  14. module_param(mem_major, int, S_IRUGO); /* 主设备号设置为模块参数 */
  15. int mem_minor = MEMDEV_MINOR;    /* 定义次设备号 */
  16. module_param(mem_minor, int, S_IRUGO); /* 次设备号设置为模块参数 */


  17. struct mem_dev *my_devices;



  18. struct file_operations my_fops =
  19. {
  20.     .owner = THIS_MODULE,
  21. };


  22. /**
  23.  * 注册字符设备
  24.  */
  25. static void mem_init_cdev(struct mem_dev *dev, int index)
  26. {
  27.     int err, devno = MKDEV(mem_major, mem_minor index);

  28.     cdev_init(&dev->cdev, &my_fops);    
  29.     dev->cdev.owner = THIS_MODULE;    
  30.     dev->cdev.ops = &my_fops;

  31.     err = cdev_add (&dev->cdev, devno, 1);    /* */
  32.     if (err)        
  33.         printk(KERN_NOTICE "Error %d adding scull%d", err, index);
  34. }

  35. static int mem_module_init(void)
  36. {
  37.     int ret,i;
  38.     dev_t mem_dev;    /* 声明设备号 */

  39.     /************ 注册设备号 ****************/
  40.     if(mem_major)
  41.     {
  42.         mem_dev = MKDEV(mem_major,mem_minor); /* 获得设备号 */
  43.         ret = register_chrdev_region(mem_dev, MEMDEV_NR_DEVS, MEMDEV_NAME);    /* 静态注册设备号 */
  44.     }
  45.     else
  46.     {
  47.         ret = alloc_chrdev_region(&mem_dev, mem_minor, MEMDEV_NR_DEVS, MEMDEV_NAME); /* 动态注册设备号 */
  48.         mem_major = MAJOR(mem_dev); /* 获得主设备号 */
  49.     }    

  50.     if(ret < 0)    /* 判断设备号注册是否成功 */
  51.     {
  52.         printk(KERN_WARNING "scull: can't get major %d\n", mem_major);
  53.         return ret;
  54.     }

  55.     /****************** 为设备分配空间 *****************************/
  56.     my_devices = kmalloc((MEMDEV_NR_DEVS * sizeof(struct mem_dev)), GFP_KERNEL);
  57.     if (!my_devices)
  58.     {        
  59.         ret = -ENOMEM;        
  60.         goto fail;
  61.     }
  62.     memset(my_devices, 0, MEMDEV_NR_DEVS * sizeof(struct mem_dev));

  63.     /************************ 设备初始化 **************************************/
  64.     for(i=0; i<MEMDEV_NR_DEVS;i )
  65.     {
  66.         my_devices[i].data = kmalloc(MEMDEV_SIZE, GFP_KERNEL);
  67.         memset(my_devices[i].data, 0, MEMDEV_SIZE);
  68.         
  69.         mem_init_cdev(&my_devices[i], i); /* 设备增加至系统 */
  70.     }
  71.     
  72.     return ret;
  73.     
  74. fail:    
  75.     unregister_chrdev_region(MKDEV(mem_major,mem_minor), MEMDEV_NR_DEVS);    /* 注销设备号 */

  76.     return ret;
  77. }

  78. static void mem_module_exit(void)
  79. {
  80.     int i;
  81.     
  82.     for(i=0; i<MEMDEV_NR_DEVS;i )    
  83.         cdev_del(&(my_devices[i].cdev));    /* 从系统去除字符设备 */
  84.     
  85.     unregister_chrdev_region(MKDEV(mem_major,mem_minor), MEMDEV_NR_DEVS);    /* 注销设备号 */
  86. }


  87. module_init(mem_module_init);
  88. module_exit(mem_module_exit);

  89. MODULE_LICENSE("GPL"); /* 模块许可证 */
  90. MODULE_AUTHOR("Lzy");    /* 作者声明 */
  91. MODULE_DESCRIPTION("memdev module"); /* 模块描述 */
  92. MODULE_VERSION("V1.0"); /* 模块版本声明 */

源码: test.rar   
阅读(848) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~