Chinaunix首页 | 论坛 | 博客
  • 博客访问: 233917
  • 博文数量: 82
  • 博客积分: 30
  • 博客等级: 民兵
  • 技术积分: 505
  • 用 户 组: 普通用户
  • 注册时间: 2011-02-23 14:59
文章分类

全部博文(82)

文章存档

2015年(81)

2011年(1)

我的朋友

分类: 嵌入式

2015-03-03 13:58:12

error: implicit declaration of  ‘class_device_create’

这个代码在Kernel 2.6.18下面编译的时候没有任何问题。为什么在2.6.34下面会出现这个错误呢?难道class_device_create这个kernel API已经从新版kernel里面移除了?

google了一下,发现确实是已经被移除了,在新版的kernel里面,可以使用device_create来代替,参数完全一致。

在LXR()网站上面查找了一番,发现class_device_create在2.6.25里面还有,从2.6.26起就被移除了。

Linux Kernel的Kernel API是经常会变化的。这给需要支持多个版本的Driver带来了不小的麻烦。有没有什么地方可以很方便的知道 Linux Kernel各个版本之间Kernel API的变化?暂时没有找到。一个可行的方法是,遇到问题之后,到LXR里面如搜索一下,LXR可以搜索特定的kernel版本。

 

之前写的字符类设备驱动,没有自动创建设备节点,因为只使用了register_chrdev()函数,只是注册了这个设备。然后在系统启动后,就要自己创建设备节点mknod,这样虽然是可行的,但是比较麻烦。于是想在__init函数里面,自动创建设备节点。

    经过查阅资料,发现创建设备节点使用了两个函数  class_create()和class_device_create(),当然在__exit()函数里,要使用class_destory()和class_device_desotry()注销创建的设备节点!

       问题来了,编译了之后,发现报错error: implicit declaration of  'class_device_create'等几个错误。经过分析,应该是Linux内核版本不同的原因!早期的版本,使用的是上面说的两个函数,但是在2.6.29以后(我用的是2.6.32的),使用的函数则变成了 class_create()和device_create(),并且要在声明中加入#i nclude  ,因为定义这些函数是在Linux2.6.32/include/linux/device.h里面!

      经过这些修改后,驱动编译成功,就能够自动创建设备节点了!

 

 

自学驱动以来,一直都是在加载模块后采用手动创建节点,虽然这个过程比较简单,毕竟还是有点麻烦,尤其是在调试模块的时候。
#insmod module_name.ko
#mknod /dev/module_name c  MAJOR  MINOR
#


在2.4里设备文件采用的是devfs,在2.6里已经用udev取代devfs,为解决上面那样手动创建节点的麻烦,我们可以在程序里加上创建节点这项,如下:
以字符设备char_dev为例,在驱动初始化的代码里调用class_create为该设备创建一个class,再为每个设备调用 class_device_create创建对应的设备,这样的module被加载时,undev daemon就会自动在/dev下创建char_dev设备文件。大概方法如下:

struct class *myclass = class_create(THIS_MODULE, “char_dev”);
class_device_create(myclass, NULL, MKDEV(major_num, 0), NULL, “char_dev”);

当然,在exit函数中要把创建的class移除:
class_destory(&xxx_dev->cdev);
class_device_desotry(my_class,MKDEV(major_num,0));

下面以一个简单字符设备驱动来展示如何使用这几个函数

  1. #include   
  2. #include   
  3. #include   
  4. #include   
  5. #include   
  6. #include   
  7.   
  8. MODULE_LICENSE ("GPL");  
  9.   
  10. int hello_major = 555;  
  11. int hello_minor = 0;  
  12. int number_of_devices = 1;  
  13.   
  14. struct cdev cdev;  
  15.     dev_t dev = 0;  
  16.   
  17. struct file_operations hello_fops = {  
  18.       .owner = THIS_MODULE  
  19.     };  
  20.   
  21. static void char_reg_setup_cdev (void)  
  22.     {  
  23.        int error, devno = MKDEV (hello_major, hello_minor);  
  24.        cdev_init (&cdev, &hello_fops);  
  25.        cdev.owner = THIS_MODULE;  
  26.        cdev.ops = &hello_fops;  
  27.        error = cdev_add (&cdev, devno , 1);  
  28.        if (error)  
  29.            printk (KERN_NOTICE "Error %d adding char_reg_setup_cdev", error);  
  30.   
  31. }  
  32.   
  33. struct class *my_class;  
  34.   
  35. static int __init hello_2_init (void)  
  36.     {  
  37.        int result;  
  38.        dev = MKDEV (hello_major, hello_minor);  
  39.        result = register_chrdev_region (dev, number_of_devices, "hello");  
  40.        if (result<0) {  
  41.            printk (KERN_WARNING "hello: can't get major number %d/n", hello_major);  
  42.            return result;  
  43.      }  
  44.   
  45.  char_reg_setup_cdev ();  
  46.   
  47.  /* create your own class under /sysfs */  
  48.      my_class = class_create(THIS_MODULE, "my_class");  
  49.      if(IS_ERR(my_class))  
  50.      {  
  51.           printk("Err: failed in creating class./n");  
  52.           return -1;  
  53.       }  
  54.   
  55.   /* register your own device in sysfs, and this will cause udev to create corresponding device node */  
  56.       device_create( my_class, NULL, MKDEV(hello_major, 0), "hello" "%d", 0 );  
  57.   
  58.   printk (KERN_INFO "Registered character driver/n");  
  59.       return 0;  
  60.     }  
  61.   
  62. static void __exit hello_2_exit (void)  
  63.     {  
  64.        dev_t devno = MKDEV (hello_major, hello_minor);  
  65.   
  66.        cdev_del (&cdev);  
  67.   
  68.    device_destroy(my_class, MKDEV(adc_major, 0));         //delete device node under /dev  
  69.        class_destroy(my_class);                               //delete class created by us  
  70.   
  71.    unregister_chrdev_region (devno, number_of_devices);  
  72.   
  73.    printk (KERN_INFO "char driver cleaned up/n");  
  74.     }  
  75.   
  76. module_init (hello_2_init);  
  77. module_exit (hello_2_exit);  

这样,模块加载后,就能在/dev目录下找到hello0这个设备节点了。
阅读(884) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~