资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,实验三,增加新的设备驱动程序,实验三 增加新的设备驱动程序,预备知识,Linux,设备分类,Linux,设备文件,Linux,设备驱动,实验指导,设备驱动函数,模块方式动态加载,编译时静态加载,实验目的、内容,1.1 Linux,设备分类,字符设备,通过位于,/dev,目录的文件系统结点来存取,映射为,chrdevs,向量表中的,device_struct,条目,大部分字符设备是数据通道,只能顺序存取,直接对设备进行读写操作,块设备,通过,/dev,目录的文件系统结点存取,分为,SCSI,类和,IDE,类,填充,blk_dev,向量表中的,blk_dev_struct,数据结构,利用系统内存作为缓冲区在设备与内存间传送数据,网络设备,类似于一个已挂载的块设备,基于,BSD Unix,的,Socket,机制,1.2 Linux,设备文件,把物理设备看成文件,将各种设备硬件的物理特性的细节屏蔽起来,实现用户程序与设备的无关性,三类设备文件:字符设备文件,(c),、块设备文件,(b),、网络设备文件,(s),设备文件命名规则,第一部分:主设备号,,2-3,个字符,表示设备的种类,(,驱动,),第二部分:次设备号,字母或数字,用于区分同种设备中的单个设备,通过,proc,文件系统访问相应的驱动程序,1.3 Linux,驱动程序,驱动程序加载方式,常见的驱动程序作为内核模块动态加载(如声卡、网卡等),最基础的驱动程序编译在内核文件中(如,CPU,、,PCI,总线、,VFS,等),驱动加载时的模块命令,模块加入:,insmod,modulename.ko,查看模块:,lsmod,删除模块:,rmmod,modulename,实验三 增加新的设备驱动程序,预备知识,Linux,设备分类,Linux,设备文件,Linux,设备驱动,实验指导,设备驱动函数,模块方式动态加载,编译时静态加载,实验目的、内容,2.1,添加设备驱动程序,注册设备:向系统登记设备及驱动程序的入口点,int,register_chrdev,(unsigned,int,major,const char*name,struct,file_operations*fops);,/,向系统的字符设备表登记一个字符设备,/,major,:,希望获得的设备号,为,0,时系统选择一个没有被占用的设备号返回。,/,name,:,设备名,/,fops,:,登记驱动程序实际执行操作的函数的指针,/,登记成功,返回设备的主设备号,否则,返回一个负值,int,register_blkdev,(unsigned,int,major,const char*name,struct,file_operations*fops);,/,向系统的块设备表登记一个块设备,添加设备驱动程序(续),设备卸载,int,unregister_chrdev,(unsigned,int,major,const char*name);,/,卸载字符设备,/,major,:,要卸载设备的主设备号,/,name,:,设备名,int,unregister_blkdev,(unsigned,int,major,const char*name);,/,卸载块设备,添加设备驱动程序(续),Linux,系统采用一组固定的入口点来实现驱动设备的功能。,open,入口点,:,打开设备。对将要进行的,I/O,操作做好必要的准备工作,如清除缓冲区等,close,入口点,:,关闭一个设备,read,入口点,:,从设备上读数据,write,入口点,:,往设备上写数据,ioctl,入口点,:,执行读、写之外的操作,select,入口点,:,检查设备,看数据是否可读或设备是否可用于写数据,添加设备驱动程序,内核模块,(LKM,Loadable Kernel Modules),Linux,核心是一种,monolithic,类型的内核,即单一的大核心,linux,内核是一个整体结构,因此向内核添加或者删除某些功能,都十分困难。为了解决这个问题,引入了模块机制,从而可以动态的在内核中添加或删除模块,添加设备驱动程序,(,续),模块的实现机制,模块初始化,(,注册,),int,init_module(),;,模块卸载,(,注销,),int,cleanup_module(),;,操作,unsigned long sys_create_module(char*name,unsigned long size);/,重新分配内存,int,sys_delete_module(char*name);/,卸载,int,sys_query_module(const char*name,int,which,void*,buf,size_t,bufsize,size_t*ret);/,查询,2.2,模块方式动态加载,内核模块,(LKM,Loadable Kernel Modules),linux,内核是整体结构,向内核添加或删除某些功能十分困难,引入模块机制,在内核中动态添加或删除模块,将模块从内核中独立出来,根据需要随时装入和卸载,使内核大小和通信量达到最小,内核模块动态加载,用,insmod,命令将模块手工插入到内核,通过,kerneld,内核守护进程自动装入所需模块,2.2,动态加载,操作命令,lsmod,:列出已经被内核调入的模块,insmod,:将某个,module,插入到内核中,(,加载指定的库,),modprob,:将某个,module,加载到内核中,(,加载之前分析库之间的依赖关系,),rmmod,:将某个,module,从内核中卸载,depmod,:生成依赖文件,告诉将来的,insmod,从哪儿调入模块,kerneld,:自动将模块调入内核和把模块从内核中卸载,2.2,动态加载,实现机制,init_modules,(),:启动时内核模块的初始化,求出内核符号表中符号的个数,sys_create_module,(),:创建一个新模块,即为新模块分配空间,也是系统调用,create_module,(),在内核的实现函数,sys_init_module,(),:系统调用,init_module,(),在内核的实现函数,sys_delete_module,(),:系统调用,delete_module,(),在内核的实现函数,query_module,(),:查询模块名,request_module,(),:主动装入内核模块,实验三 增加新的设备驱动程序,预备知识,Linux,设备分类,Linux,设备文件,Linux,设备驱动,实验指导,设备驱动函数,模块方式动态加载,实验目的、内容,3.1,实验目的,了解,Linux,下设备驱动程序的原理,学习,Linux 2.6,内核下设备驱动程序编写方法,掌握用模块方式设计和加载驱动程序的方法,3.2,实验内容,增加设备驱动程序,增加一个新的字符设备驱动程序,以动态方式加载设备驱动程序,采用动态模块加载方式加载已完成的字符设备驱动程序,并编写应用程序进行测试,添加设备驱动程序(续),添加设备驱动程序的方法,编写设备驱动程序,mydev.c,设备驱动模块的编译,加载设备驱动模块,:,insmod,mydev.ko,若加载成功,在文件,/proc/devices,中能看到新增加的设备,包括设备名,mydev,和主设备号。,生成设备文件:,mknod,/dev/test c 254 0,其中,,test,为设备文件名,,254,为主设备号,,0,为从设备号,,c,表示字符设备,添加设备驱动程序(续),Linux,系统采用一组固定的入口点来实现驱动设备的功能。,open,入口点,:,打开设备准备,I/O,操作。,open,子程序必须对将要进行的,I/O,操作做好必要的准备工作,如清除缓冲区等。,close,入口点,:,关闭一个设备。当最后一次使用设备终结后,调用,close,子程序。,read,入口点,:,从设备上读数据。,write,入口点,:,往设备上写数据。,ioctl,入口点,:,执行读、写之外的操作。,select,入口点,:,检查设备,看数据是否可读或设备是否可用于写数据。,如果设备驱动程序没有提供上述入口点中的某一个,系统会用缺省的子程序来代替。对于不同的系统,也还有一些其它的入口点。,添加设备驱动程序(续),入口点采用如下数据结构实现:,int,(*flush)(,struct,file*);,int,(*release)(,struct,inode,*,struct,file*);,int,(*,fsync,)(,struct,file*,struct,dentry,*,int,datasync,);,int,(*,fasync,)(,int,struct,file*,int,);,int,(*lock)(,struct,file*,int,struct,file_lock*);,ssize_t,(*,readv,)(,struct,file*,const,struct,iovec,*,unsigned long,loff_t,*);,ssize_t,(*,writev,)(,struct,file*,const,struct,iovec,*,unsigned long,loff_t,*);,ssize_t,(*,sendpage,)(,struct,file*,struct,page*,int,size_t,loff_t,*,int,);,unsigned long(*,get_unmapped_area)(struct,file*,unsigned long,unsigned long,unsigned long,unsigned long);,include,struct,file_operations,struct,module*owner;,loff_t,(*,llseek,)(,struct,file*,loff_t,int,);,ssize_t,(*read)(,struct,file*,char*,size_t,loff_t,*);,ssize_t,(*write)(,struct,file*,const char*,size_t,loff_t,*);,int,(*,readdir,)(,struct,file*,void*,filldir_t,);,unsigned,int,(*poll)(,struct,file*,struct,poll_table_struct,*);,int,(*,ioctl,)(,struct,inode,*,struct,file*,unsigned,int,unsigned long);,int,(*,mmap,)(,struct,file*,struct,vm_area_struct,*);,int,(*open)(,struct,inode,*,struct,file*);,编写应用程序,测试驱动程序,添加设备驱动程序(续),if(,testdev,=-1),printf(Cannt,open file n);,exit(0);,read(testdev,buf,10);,for(i=0;i 10;i+),printf(%dn,bufi,);,close(testdev,);,#include,#include,#include,#include,int,main(),int,testdev,;,int,i;,char buf10;,testdev,=open(/dev/test,O_RDWR);,补充说明,printk,();,unsigned long,copy_to_user(void,_user*to,const void*from,unsigned long n),unsigned long,copy_from_user(void,*to,const voi
展开阅读全文