转载请注明出处: http://blog.csdn.net/drivelinux/article/details/8656280
字符设备相关函数
1.alloc_chrdev_region()
功能: 自动分配一个主设备号及基于此主设备号的若干个连续的指定数量的次设备号。
函数原型如下:
-
-
-
-
-
-
-
-
-
-
-
- int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,const char *name)
2.register_chrdev_region()
功能:注册连续的若干个设备号,用这个函数要自己指定主设备号。
函数原型:
-
-
-
-
-
-
-
-
-
- int register_chrdev_region(dev_t from, unsigned count, const char *name)
注: register_chrdev() 函数也用于分配设备号,但是用于2.6版本之前的内核中,在之后的版本中不再使用。
3.unregister_chrdev_region()
功能:注销由alloc_chrdev_region()或者register_chrdev_region()注册的设备号,一般在驱动模块的退出函数中要执行此操作,将注册的设备号还给系统。
函数原型:
-
-
-
-
-
-
-
-
-
- void unregister_chrdev_region(dev_t from, unsigned count)
4.cdev_alloc()
功能:分配一个表示字符设备的cdev结构体。
函数原型:
-
-
-
-
-
- struct cdev *cdev_alloc(void)
5.cdev_init()
功能:初始化由cdev_alloc()分配的表示字符设备的cdev结构体,并通过向该函数传入的struct file_operations *fops参数来指定该字符设备的文件操作函数。
函数原型:
-
-
-
-
-
-
-
-
- void cdev_init(struct cdev *cdev, const struct file_operations *fops)
6.cdev_add()
功能:添加一个(由cdev_alloc()分配并通过cdev_init()初始化的)字符设备到系统中。
函数原型:
-
-
-
-
-
-
-
-
-
-
- int cdev_add(struct cdev *p, dev_t dev, unsigned count)
7.cdev_del()
功能:执行和cdev_add()相反的操作,将一个指定的字符设备从系统中删除。
函数原型:
-
-
-
-
-
-
-
- void cdev_del(struct cdev *p)
以下为一个简单的字符设备初始化函数,函数中列出了向系统中添加一个字符设备的简单步骤:
- struct cdev *myDev_dev;
-
- static int myDev_major = 0;
- static int myDev_minor = 0;
-
- static int __init myDev_init(void)
- {
- int err = -1;
- dev_t dev = 0;
-
-
- err = alloc_chrdev_region(&dev, 0, TOTAL_DEVICE_COUNT, "myDev");
- if(err < 0) {
- printk(KERN_ALERT"Failed to alloc char dev region.\n");
- return err;
- }
-
- myDev_major = MAJOR(dev);
- myDev_minor = MINOR(dev);
-
-
- myDev_dev = cdev_alloc();
- if(!myDev_dev) {
- err = -ENOMEM;
- printk(KERN_ALERT"Failed to alloc myDev_dev.\n");
- return err;
- }
-
- cdev_init(myDev_dev, &myDev_fops);
-
-
- err = cdev_add(myDev_dev,dev, TOTAL_DEVICE_COUNT);
- if(err) {
- return err;
- }
- return err;
- }
自动创建设备节点相关函数
1.class_create()
功能:创建一个struct class结构体,作为device_create()函数的参数。
函数原型:
- #define class_create(owner, name) \
- ({ \
- static struct lock_class_key __key; \
- __class_create(owner, name, &__key); \
- })
2.device_create()
功能:该函数创建一个设备并将其注册到sysfs中,同时在系统的sys/class和sys/device目录下会生成相应的类和设备入口。并且,该函数还会出发用户空间udev的动作,udev会根据sysfs下的class在/dev目录下创建设备节点,这也为自动创建设备节点提供了一种途径。通过device_create()函数,我们就可以不用通过mknod命令手动的创建设备节点了。
函数原型:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- struct device *device_create(struct class *class, struct device *parent,
- dev_t devt, void *drvdata, const char *fmt, ...)
3.device_create_file()
功能:该函数用于为指定设备在sysfs下建立属性文件,如:
device_create_file(dev, &dev_attr_val);
其中的dev_attr_val可以通过DEVICE_ATTR宏进行定义,也可以直接通过struct device_attribute xxx=__ATTR(_name,_mode,_show,_store)进行定义,区别就是用DEVICE_ATTR宏进行定义时得到的变量名都是以dev_attr_为前缀的,而通过struct device_attribute xxx=__ATTR(_name,_mode,_show,_store)进行定义时,变量名可以任意指定。
函数原型:
-
-
-
-
-
-
- int device_create_file(struct device *dev,const struct device_attribute *attr)
-
-
- #define DEVICE_ATTR(_name, _mode, _show, _store) \
- struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
如下代码可以实现自动创建设备节点:
- static struct class* myDev_class = NULL;
- struct device* devc= NULL;
-
-
- myDev_class = class_create(THIS_MODULE,"myDevClass");
- if(IS_ERR(myDev_class)) {
- err = PTR_ERR(myDev_class);
- printk(KERN_ALERT"Failed to create class.\n");
- return err;
- }
-
- devc = device_create(myDev_class,NULL,dev,NULL,"myDev");
- if(IS_ERR(devc)) {
- err = PTR_ERR(devc);
- printk(KERN_ALERT"Failed to create device.");
- return err;
- }
以下贴出以上分两部分介绍的字符设备的初始化代码:
- struct cdev *myDev_dev;
-
- static int myDev_major = 0;
- static int myDev_minor = 0;
-
-
- static int __init myDev_init(void)
- {
- int err = -1;
- dev_t dev = 0;
- struct device *devc = NULL;
-
-
- err = alloc_chrdev_region(&dev, 0, TOTAL_DEVICE_COUNT, "myDev");
- if(err < 0) {
- printk(KERN_ALERT"Failed to alloc char dev region.\n");
- return err;
- }
-
- myDev_major = MAJOR(dev);
- myDev_minor = MINOR(dev);
-
-
- myDev_dev = cdev_alloc();
- if(!myDev_dev) {
- err = -ENOMEM;
- printk(KERN_ALERT"Failed to alloc myDev_dev.\n");
- return err;
- }
-
- cdev_init(myDev_dev, &myDev_fops);
-
-
- err = cdev_add(myDev_dev,dev, TOTAL_DEVICE_COUNT);
- if(err) {
- return err;
- }
-
-
- myDev_class = class_create(THIS_MODULE,"myDevClass");
- if(IS_ERR(myDev_class)) {
- err = PTR_ERR(myDev_class);
- printk(KERN_ALERT"Failed to create class.\n");
- return err;
- }
-
- devc = device_create(myDev_class,NULL,dev,NULL,"myDev");
- if(IS_ERR(devc)) {
- err = PTR_ERR(devc);
- printk(KERN_ALERT"Failed to create device.");
- return err;
- }
- return err;
- }
通用函数
1.kmalloc()和kzalloc()的异同
在内核include/linux/slab.h文件中有如下定义:
-
-
-
-
-
- static inline void *kzalloc(size_t size, gfp_t flags)
- {
- return kmalloc(size, flags | __GFP_ZERO);
- }
从注释以及函数原型均能看出kzalloc()函数的作用,即申请一块内存并且该内存会在函数调用过程中被清零。
2.module_platform_driver()
该函数实际是一个宏,它在include/linux/platform_device.h中定义如下:
-
-
-
-
-
- #define module_platform_driver(__platform_driver) \
- module_driver(__platform_driver, platform_driver_register, \
- platform_driver_unregister)
其中的module_driver在/include/linux/device.h中定义,如下:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- #define module_driver(__driver, __register, __unregister, ...) \
- static int __init __driver##_init(void) \
- { \
- return __register(&(__driver) , ##__VA_ARGS__); \
- } \
- module_init(__driver##_init); \
- static void __exit __driver##_exit(void) \
- { \
- __unregister(&(__driver) , ##__VA_ARGS__); \
- } \
- module_exit(__driver##_exit);
由上述定义可知,module_platform_driver()宏的作用就是定义指定名称的平台设备驱动注册函数和平台设备驱动注销函数,并且在函数体内分别通过platform_driver_register()函数和platform_driver_unregister()函数注册和注销该平台设备驱动。
3.read_cpuid_id()
读取CPU ID,定义于arch/arm/include/asm/cputype.h文件中
。