您好,欢迎访问三七文档
当前位置:首页 > 临时分类 > Linux字符驱动中动态分配设备号与动态生成设备节点
Linux字符驱动中动态分配设备号与动态生成设备节点在编写Linux内核驱动程序的时候,如果不动态生成设备号的话,需要自己手动分配设备号,有可能你分配的设备号会与已有设备号相同而产生冲突。因此推荐自动分配设备号。使用下面的函数:intalloc_chrdev_region(dev_t*dev,unsignedbaseminor,unsignedcount,constchar*name)该函数需要传递给它指定的第一个次设备号baseminor(一般为0)和要分配的设备数count,以及设备名,调用该函数后自动分配得到的设备号保存在dev中。当使用了alloc_chrdev_region()动态分配设备号之后,需要依次使用:cdev_init(structcdev*cdev,conststructfile_operations*fops)和cdev_add(structcdev*p,dev_tdev,unsignedcount)将字符设备注册到内核中。通过上面三个函数就可以动态生成设备号了。在卸载的时候需要使用:unregister_chrdev_region(dev_tfrom,unsignedcount)来释放设备编号动态创建设备号之后,将驱动加载到内核,通过:cat/proc/devices命令可以查看设备号如果上层应用程序需要访问驱动程序,则需要为该驱动创建设备节点。如果手动创建设备结点需要这样做:(这里假设通过cat/proc/devices发现字符设备CDEV_ZHU的设备号为254)$mknod/dev/CDEV_ZHUc2540如果我们在驱动里面动态创建的话需要这样做:cdev_class=class_create(owner,name)//cdev_class为structclass类型然后使用:device_create(_cls,_parent,_devt,_device,_fmt)当动态创建了设备节点之后,在卸载的时候需要使用:device_destroy(_cls,_device)和class_destroy(structclass*cls)来销毁设备和类。下面给出一组测试代码:(该组代码实现了应用程序通过打开驱动访问和修改驱动的一个全局变量“global_var”)/*驱动部分:globalvar.c*/#includelinux/module.h#includelinux/init.h#includelinux/fs.h#includeasm/uaccess.h#includeasm/device.h//下面这三个头文件是由于动态创建需要加的#includelinux/device.h#includelinux/cdev.hMODULE_LICENSE(GPL);#defineDEVICE_NAMECDEV_ZHUstaticstructclass*cdev_class;staticssize_tglobalvar_read(structfile*,char*,size_t,loff_t*);staticssize_tglobalvar_write(structfile*,constchar*,size_t,loff_t*);//初始化字符设备驱动的file_operations结构体structfile_operationsglobalvar_fops={read:globalvar_read,write:globalvar_write,};staticintglobal_var=0;//CDEV_ZHU设备的全局变量dev_tdev=0;//这里是动态分配设备号和动态创建设备结点需要用到的structcdevdev_c;staticint__initglobalvar_init(void){intret,err;//注册设备驱动ret=alloc_chrdev_region(&dev,0,1,DEVICE_NAME);//动态分配设备号if(ret){printk(globalvarregisterfailure\n);unregister_chrdev_region(dev,1);returnret;}else{printk(globalvarregistersuccess\n);}cdev_init(&dev_c,&globalvar_fops);err=cdev_add(&dev_c,dev,1);if(err){printk(KERN_NOTICEerror%daddingFC_dev\n,err);unregister_chrdev_region(dev,1);returnerr;}cdev_class=class_create(THIS_MODULE,DEVICE_NAME);//动态创建设备结点if(IS_ERR(cdev_class)){printk(ERR:cannotcreateacdev_class\n);unregister_chrdev_region(dev,1);return-1;}device_create(cdev_class,NULL,dev,0,DEVICE_NAME);returnret;}staticvoid__exitglobalvar_exit(void){//注销设备驱动device_destroy(cdev_class,dev);class_destroy(cdev_class);unregister_chrdev_region(dev,1);printk(globalvar_exit\n);}staticssize_tglobalvar_read(structfile*filp,char*buf,size_tlen,loff_t*off){//将global_var从内核空间复制到用户空间if(copy_to_user(buf,&global_var,sizeof(int))){return-EFAULT;}returnsizeof(int);}staticssize_tglobalvar_write(structfile*filp,constchar*buf,size_tlen,loff_t*off){//将用户空间的数据复制到内核空间的global_varif(copy_from_user(&global_var,buf,sizeof(int))){return-EFAULT;}returnsizeof(int);}module_init(globalvar_init);module_exit(globalvar_exit);/*应用程序:globalvartest.c*/#includesys/types.h#includesys/stat.h#includestdio.h#includefcntl.hintmain(){intfd,num;//打开/dev/CDEV_ZHUfd=open(/dev/CDEV_ZHU,O_RDWR,S_IRUSR|S_IWUSR);if(fd!=-1){//初次读global_varread(fd,&num,sizeof(int));printf(Theglobalvaris%d\n,num);//写global_varprintf(Pleaseinputthenumwrittentoglobalvar\n);scanf(%d,&num);write(fd,&num,sizeof(int));//再次读global_varread(fd,&num,sizeof(int));printf(Theglobalvaris%d\n,num);//关闭“/dev/CDEV_ZHU”close(fd);}else{printf(Deviceopenfailure\n);}return0;}说明:这个程序是我修改了“深入浅出Linux设备编程”这本书的代码的来的,在项目中使用动态创建设备节点和动态生成设备号比较方便,于是就在这里分享了。使用一个简单的makefile将(驱动)globalvar.c编译过后使用insmodglobalvar.ko将驱动加载到内核,然后就将globalvartest.c生成的可执行文件运行起来就可以操作驱动中的全局变量了。不用像书上一样还要在命令行去创建设备节点。我使用的内核版本是2.6.33.4。makeitsimple,makeithappen
本文标题:Linux字符驱动中动态分配设备号与动态生成设备节点
链接地址:https://www.777doc.com/doc-2884806 .html