今天在编译一个Linux kernel module 的时候,遇到下面的错误:
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(),并且要在声明中加入#include <linux/device.h> ,因为定义这些函数是在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));
下面介绍下函数class_creat和class_device_creat的原型:
class_create()
-------------------------------------------------
linux-2.6.22/include/linux/device.h
struct class *class_create(struct module *owner, const char *name)
class_create - create a struct class structure
@owner: pointer to the module that is to "own" this struct class
@name: pointer to a string for the name of this class.
在/sys/class/下创建类目录
class_device_create()
-------------------------------------------------
linux-2.6.22/include/linux/device.h
struct class_device *class_device_creat(struct class *cls,
struct class_device *parent,
dev_t devt,
struct device *device,
const char *fmt, ...)
class_device_create - creates a class device and registers it with sysfs
@cls: pointer to the struct class that this device should be registered to.
@parent: pointer to the parent struct class_device of this new device, if any.
@devt: the dev_t for the char device to be added.
@device: a pointer to a struct device that is assiociated with this class device.
@fmt: string for the class device's name
void class_destroy(struct class *cls);/*销毁/sys/class下的类 */
void class_device_destroy(struct class *cls, dev_t devt); /*销毁一个类设备*/
参数含义同上
补充:
在Linux2.6中,针对上面的这个问题不同的版本有些修改,使用前要先查看下/.../include/linux/device.h里的函数声明,如我用的是Linux2.6.29,里面就没有class_device_create函数,而直接使用device_create就可以了,而在之前的版本如Linux2.6.15,里面就要用class_device_create函数 。