您好,欢迎访问三七文档
1LinuxDevice&Module设备管理与模块机制基本概念传统方式的设备注册与管理devfs注册与管理块设备的请求队列网络设备模块机制2LinuxDevice&Module基本概念字符设备、块设备、网络设备字符设备以字节为单位进行数据处理,通常只允许按顺序访问块设备将数据按可寻址的块为单位进行处理,可以随机访问,利用缓冲技术网络设备是一类特殊的设备,每块网卡有名字但没有设备文件与之对应查看系统中的设备:/proc/devices主设备号和次设备号majornumber:相同的设备使用相同的驱动程序minornumber:用来区分具体设备的实例查看设备及其类型“ls-l/dev”设备文件系统devfs/dev目录过于庞大,很多设备文件没有对应系统中的设备devfs根据系统中的实际设备构建设备文件,并按目录存放,如/dev/disk,/dev/pts3LinuxDevice&Module基本概念用户空间内核空间I/O请求设备驱动程序设备ISR系统调用ret_from_sys_call返回,进程继续4LinuxDevice&Module基本概念用户程序调用Fd=fopen(“/dev/hda”,O_RDWR,0);read(buff,fd,size)write(fd,buff,size)close(fd)VirtualfilesystemGeneric_file_read()Generic_file_write()块设备文件建立设备:#mknod/dev/dev_nametypemajor_numberminor_number5LinuxDevice&ModuleVFS中的文件include/linux/fs.hstructfile{……structfile_operations*f_op;};structfile_operations{loff_t(*llseek)(structfile*,loff_t,int);ssize_t(*read)(structfile*,char*,size_t,loff_t*);ssize_t(*write)(structfile*,constchar*,size_t,loff_t*);int(*ioctl)(structinode*,structfile*,unsignedint,unsignedlong);int(*mmap)(structfile*,structvm_area_struct*);int(*open)(structinode*,structfile*);int(*release)(structinode*,structfile*);int(*fsync)(structfile*,structdentry*,intdatasync);int(*fasync)(int,structfile*,int);……};6LinuxDevice&Module(1)llseek(file,offset,whence):修改文件的读写指针。(2)read(file,buf,count,offset):从设备文件的offset处开始读出count个字节,然后增加*offset的值。(3)write(file,buf,count,offset):从设备文件的offset处写入count个字节,然后增加*offset的值。(4)ioctl(inode,file,cmd,arg):向一个硬件设备发命令,对设备进行控制。(5)mmap(file,vma):将设备空间映射到进程地址空间。(6)open(inode,file):打开并初始化设备。(7)release(inode,file):关闭设备并释放资源。(8)fsync(file,dentry):实现内存与设备之间的同步通信。(9)fasync(file,on):实现内存与设备之间的异步通信。7LinuxDevice&Modulefs/devices.cstructdevice_struct{constchar*name;structfile_operations*fops;};staticstructdevice_structchrdevs[MAX_CHRDEV];注册与注销函数:intregister_chrdev(unsignedintmajor,constchar*name,structfile_operations*fops)intunregister_chrdev(unsignedintmajor,constchar*name);注:major即设备的主设备号,注册后就是访问数组chrdevs的索引(下标)。字符设备的注册与管理8LinuxDevice&ModulePCI设备(驱动实现见word文档)Linux内核启动时会对所有PCI设备进行扫描、登录和分配资源等初始化操作,建立起系统中所有PCI设备的拓扑结构此后当内核欲初始化某设备时,调用module_init加载该设备的驱动程序9LinuxDevice&Module块设备fs/block_dev.cstaticstruct{constchar*name;structblock_device_operations*bdops;}blkdevs[MAX_BLKDEV];10LinuxDevice&Module块设备注册fs/block_dev.cregister_blkdev(unsignedintmajor,constchar*name,structblock_device_operations*bdops)intunregister_blkdev(unsignedintmajor,constchar*name)11LinuxDevice&Module块设备的操作block_device_operationsstructblock_device_operations{int(*open)(structinode*,structfile*);int(*release)(structinode*,structfile*);int(*ioctl)(structinode*,structfile*,unsigned,unsignedlong);int(*check_media_change)(kdev_t);int(*revalidate)(kdev_t);structmodule*owner;};12LinuxDevice&Moduleblock_device_operations{}并不能完全提供file_operations结构中的所必需的主要函数(例如read、write),所以内核实际上是采用def_blk_fops变量对相关的file_operations{}变量进行了赋值:structfile_operationsdef_blk_fops;除了open、release等函数利用了设备注册时提供的block_device_operations{}结构中的成员变量之外,其他函数都是采用所有块设备通用的操作函数(def_blk_fops{})块设备的缺省操作def_blk_fops13LinuxDevice&Modulefs/block_dev.cstructfile_operationsdef_blk_fops={open:blkdev_open,release:blkdev_close,llseek:block_llseek,read:generic_file_read,write:generic_file_write,mmap:generic_file_mmap,fsync:block_fsync,ioctl:blkdev_ioctl,};块设备的缺省操作def_blk_fops14LinuxDevice&Moduleblock_read与block_write等函数是设备相关的块设备注册时一个重要的任务就是提供这个设备相关的操作函数给内核15LinuxDevice&Moduledevfs注册与管理fs/devfs/base.cregister_chrdev()停止使用,改为devfs_register_chrdev()register_blkdev()停止使用,改为devfs_register_blkdev()intdevfs_register_chrdev(unsignedintmajor,constchar*name,structfile_operations*fops)intdevfs_register_blkdev(unsignedintmajor,constchar*name,structblock_device_operations*bdops)intdevfs_unregister_chrdev(unsignedintmajor,constchar*name)intdevfs_unregister_blkdev(unsignedintmajor,constchar*name)16LinuxDevice&Module块设备的请求队列当系统对块设备进行读操作时,仅仅是通过块设备通用的读操作函数block_read(),将这一个请求发送给对应的设备,并保存在该设备的操作请求队列(requestqueue)中。然后调用这个块设备的底层处理函数,对请求队列中的操作请求进行逐一的执行structblk_dev_struct{/*include/linux/blkdev.h*/request_queue_trequest_queue;queue_proc*queue;void*data;};structblk_dev_structblk_dev[MAX_BLKDEV];17LinuxDevice&Moduleblock_read()流程block_read()ll_rw_block()submit_bh()generic_make_request()__make_request()add_request(),给请求队列添加新的请求18LinuxDevice&ModuleLinux网络协议栈应用系统内核硬件设备应用层BSDSocket层INETSocket层IP层硬件层TCPUDP网络设备接口19LinuxDevice&Module重要的数据结构以socket文件描述符作为参数,系统调用从用户空间切换到内核空间,从而进入到BSDSocket层的操作。操作的对象是socket{}结构,每一个这样的结构对应的是一个网络连接通过网络地址族的不同来判断是否应该进入到INETSocket层;这一层的数据存放在msghdr{}结构的变量中在INETSocket层中,分成面向连接和面向无连接两种类型,区分TCP和UDP协议。在这一层中的操作对象是sock{}类型的数据,而数据存放在sk_buff{}结构中20LinuxDevice&Module模块机制(Module)Linux的单块结构(monolithic)使得其可扩展性较差模块机制(LinuxKernelModule,LKM)提高了linux内核的可扩展性利用linux源码编译生成内核时,如某功能允许“m”选项(其他为“y”,“n”),说明可以以模块形式存在多数设备驱动程序以模块的方式挂接到内核系统启动时已将若干模块挂入了内核用户只要有权限,就可以编写模块挂入内核模块的缺点:增加了内核管理代价21LinuxDevice&Module模块的设计EveryLKMconsistsoftwobasicfunctions(minimum):intinit_module(void)/*usedforallinitializationstuff*/{...}voidcleanup_module(void)/*usedforacleanshutdown*/{...}安装模块命令#insmodmodule.o#modprobemodule.o卸载模块命
本文标题:设备管理与模块机制
链接地址:https://www.777doc.com/doc-1316312 .html