自动创建设备节点 ,手动创建…

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(http://lxr.linux.no)网站上面查找了一番,发现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  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.    
  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.     
  56.       device_create( my_class, NULL, MKDEV(hello_major, 0), "hello" "%d", );  
  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这个设备节点了。

mdev是busybox自带的一个简化版的udev,适合于嵌入式的应用埸合。其具有使用简单的特点。它的作用,就是在系统启动和热插拔 或动态加载驱动程序时,自动产生驱动程序所需的节点文件。在以busybox为基础构建嵌入式linux的根文件系统时,使用它是最优

的选择。

mdev使用

mdev的使用在busybox中的mdev.txt文档已经将得很详细了。但作为例子,我简单讲讲我的使用过程:

(1)在编译时加上对mdev的支持(我是使用的是busybox1.10.1):

Linux System Utilities --->



mdev



Support /etc/mdev.conf



Support command execution at device addition/removal

(2)在启动时加上使用mdev的命令:

我在自己创建的根文件系统(nfs)中的/linuxrc文件中添加了如下指令:

#挂载/sys为sysfs文件系统

echo "----------mount /sys as sysfs"

/bin/mount -t tmpfs mdev /dev

/bin/mount -t sysfs sysfs /sys

echo "----------Starting mdev......"

/bin/echo /sbin/mdev > /proc/sys/kernel/hotplug

mdev -s

注意:是/bin/echo /sbin/mdev > /proc/sys/kernel/hotplug,并非/bin/echo /bin/mdev > /proc/sys/kernel/hotplug。

busybox的文档有错!!



(3)在你的驱动中加上对类设备接口的支持。

在驱动程序的初始化函数中,使用下述的类似语句,就能在类设备目录下添加包含设备号的名为“dev”的属性文件。并通过mdev

在/dev目录下产生gpio_dev0的设备节点文件。

my_class = class_create(THIS_MODULE, "gpio_class");

if(IS_ERR(my_class)) {

printk("Err: failed in creating class.\n");

return -1;

}



class_device_create(my_class, NULL, MKDEV(gpio_major_number, 0), NULL, "gpio_dev%d" ,0);

在驱动程序的清除程序段,加入以下语句,以完成清除工作。

class_device_destroy(my_class, MKDEV(gpio_major_number, 0));

class_destroy(my_class);

需要的头文件是linux/device.h,因此程序的开始应加入下句

#include

另外,my_class是class类型的结构体指针,要在程序开始时声明成全局变量。

struct class *my_class;

上述程序中的gpio_major_number是设备的主节点号。可以换成需要的节点号。gpio_dev是最终生成的设备节点文件的名子。%d是

用于以相同设备自动编号的。gpio_class是建立的class的名称,当驱动程序加载后,可以在/sys/class的目录下看到它。

上述语句也不一定要在初始化和清除阶段使用,可以根据需要在其它地方使用。

(4)至于/etc/mdev.conf文件,可有可无,不影响使用,只是添加了些功能。

关于mdev的使用方法,我在网上找到一篇中文版的。大家可以到我上传的资源中下载。

要想真正用好mdev,适当知道一下原理是必不可少的。现在简单介绍一下mdev的原理:

执行mdev -s

:以‘-s’为参数调用位于

/sbin目录写的mdev(其实是个链接,作用是传递参数给/bin目录下的busybox程序并调用它),mdev扫描 /sys/class 和

/sys/block

中所有的类设备目录,如果在目录中含有名为“dev”的文件,且文件中包含的是设备号,则mdev就利用这些信息为这个设备在/dev

下创建设备节点文件。一般只在启动时才执行一次 “mdev -s”。

热插拔事件:由于启动时运行了命

令:echo /sbin/mdev > /proc/sys/kernel/hotplug ,那么当有热插拔事件产生时,内核就会调用位于

/sbin目录的mdev。这时mdev通过环境变量中的 ACTION 和

DEVPATH,(这两个变量是系统自带的)来确定此次热插拔事件的动作以及影响了/sys中的那个目录。接着会看看这个目录中是否有

“dev”的属性文件,如果有就利用这些信息为

这个设备在/dev 下创建设备节点文件。

最后,附上我在工作中编写的一段简单的gpio控制驱动程序。此程序没有什么功能,主要是做一些测试用的。有兴趣的朋友可以用

它测试一下上述的mdev的使用方法。我用的是友善公司的mini2440开发板。



补充:1

[b]为mdev的运行准备环境

mdev需要改写/dev和/sys两个目录。所以必须保证这两个目录是可写的(一般会用到sysfs,tmpfs。所以要重新编译内核)。

然后在你的启动脚本文件中加入

/bin/mdev -s[/b]

[b]补充2:[/b]

[b] ·/etc/fstab[/b]

[b]这是mount -a要读取的文本。根据需要编写。[/b]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值