700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Linux驱动编程 step-by-step (四) 字符设备的注册与设备节点的自动创建

Linux驱动编程 step-by-step (四) 字符设备的注册与设备节点的自动创建

时间:2023-01-29 12:22:16

相关推荐

Linux驱动编程 step-by-step (四) 字符设备的注册与设备节点的自动创建

字符设备的注册与设备节点的自动创建

cdev 结构

内核内部使用struct cdev<linux/cdev.h>来表示一个字符设备

structcdev{

structkobjectkobj;//kobj设备模型以后介绍

structmodule*owner;

conststructfile_operations*ops;//文件操作

structlist_headlist;

dev_tdev;//设备号

unsignedintcount;//设备个数

};

注册字符设备

动态初始化:

structcdev*my_cdev=cdev_alloc();

my_cdev->ops=&my_ops;

静态初始化:

structcdevmy_cdev;

cdev_init(&my_dev,&my_ops);

向内核注册(添加设备):

intcdev_add(structcdev*dev,dev_tnum,unsignedcount); dev:指向以初始化的字符设备结构

num: 设备号

count: 所要添加的设备个数

返回值:

成功返回0 失败返回错误码,设备被注册时候可能立即会呗调用,所以在驱动程序还没有准备好处理设备操作时候不要先调用cdev_add

注销字符设备:

在不需要用西设备时候需要注销设备

voidcdev_del(structcdev*);

早期的方法

在2.6的内核之前注册字符设备有一个简单易用的方法,现在也可以使用但是不建议使用,因为到最后这个方法会从内核消失

注册字符设备:

staticinlineintregister_chrdev(unsignedintmajor,

constchar*name,conststructfile_operations*fops); major: 主设备号 (当major为0时表示有内核分配一个可用的主设备号并返回)

name: 驱动名

fops: 文件操作

缺点: 不能同时注册多个设备, 他是用一种默认的方式去建立一个cdev结构,而这样的话它不能使用大于255的主次设备号

注销设备:

staticinlinevoidunregister_chrdev(unsignedintmajor,constchar*name)

设备节点的自动创建

在上一个程序中,虽然能够争取的得到一个设备号,但是并不会在/dev/目录下生成一个设备节点。

使用手动创建

mknod/dev/device_namecmajorminor

device_name: 指设备名,

c: 表述创建字符设备节点(同理b 表示创建块设备文件节点)

major: 主设备号

minor: 次设备号

在做测试时候这样做事可以理解的,而在作为一个模块要发行时候,这样就太不方面了,①要先查看设备是否成功创建,②查看注册设备的主设备号,③输入命令创建文件节点

当然可以写一个shell脚本来完成这些事情。

自动创建设备节点

需要的纤体内核空间支持udev,在内核配置,及busybox配置时候需要指定

内核中定义了struct class 与 struct devic结构<linux/device.h>

创建一个class结构

#defineclass_create(owner,name)\

({\

staticstructlock_class_key__key;\

__class_create(owner,name,&__key);\

})

owner表示拥有这个模块的指针

name 表示设备名

调用此函数后 创建了一个struct class结构放在sysfs下边,而后调用

structdevice*device_create(structclass*cls,

structdevice*parent,

dev_tdevt,void*drvdata,

constchar*fmt,...) 在/dev目录下创建设备节点

cls : 是上边函数的创建的struct class结构指针

parent: 指向设备的父节点设备(如果没有填NULL

devt: 被添加设备的设备号

drvdata: 回调函数参数

fmt ,args:一个或者多个设备名

至此我们就自动创建了一个设备节点

删除设备节点

在设备不需要使用时候我们需要删除设备节点:

voiddevice_destroy(structclass*class,dev_tdevt);//删除设备节点

voidclass_destroy(structclass*cls);//删除sysfs下得structclass结构 至于深层的一些实现机制,没有细细研究,大家干兴趣可以参考相关资料

实例:

初始化 添加设备到内核

simple_cdev=cdev_alloc();//动态初始化字符设备 if(simple_cdev!=NULL) { simple_cdev->ops=&simple_fops;//文件操作 simple_cdev->owner=THIS_MODULE; } else { printk(KERN_ERR"alloccdeverrnomemory"); unregister_chrdev_region(dev,DEV_COUNT);//如果分配资源出错则释放设备号 return-ENOMEM; } err=cdev_add(simple_cdev,dev,DEV_COUNT);//向内核添加设备 if(err<0) { printk(KERN_ERR"addcdeverr\n"); gotoerror1; } else { #ifSIMPLE_DEBUG printk(KERN_INFO"addchardevOK!\n"); #endif }

自动创建设备节点

simple_class=class_create(THIS_MODULE,SIMPLE_NAME); if(simple_class==NULL) { printk(KERN_ERR"createsimpleclasserror\n"); gotoerror2; } else { #ifSIMPLE_DEBUG printk(KERN_INFO"createsimpleclassOK!\n"); #endif } simple_dev=device_create(simple_class,NULL,dev,NULL,SIMPLE_NAME); if(simple_dev==NULL) { printk(KERN_ERR"createdeviceerror"); gotoerror3; } else { #ifSIMPLE_DEBUG printk(KERN_INFO"createsimpledeviceOK!\n"); #endif }

删除设备节点,注销字符设备

dev=MKDEV(simple_major,simple_minor);//计算出设备号 device_destroy(simple_class,dev);//删除设备节点 class_destroy(simple_class);//删除并释放class结构 cdev_del(simple_cdev);//注销设备 cdev_put(simple_cdev);//对动态的设备需要使用cdev_put‘来释放资源

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。