第七讲字符设备驱动

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

数字集成电路设计与系统应用专业1字符设备驱动(1)数字集成电路设计与系统应用专业Linux驱动程序基础知识Linux字符设备驱动基础file_opration结构分析用户空间与内核空间数据传输基本字符设备驱动函数模板2数字集成电路设计与系统应用专业3设备驱动程序基础Linux设备驱动概念驱动程序为操作硬件提供良好内部接口驱动程序为应用程序提供了访问设备的机制Linux设备驱动分类字符设备:键盘、鼠标、串口块设备:硬盘、Flash网络接口:以太网特定类型设备:audio设备数字集成电路设计与系统应用专业4系统调用和设备I/O数字集成电路设计与系统应用专业设备驱动健壮性和安全性驱动程序是内核的一部分驱动程序的漏洞和缺陷直接危及内核留心未初始化的指针,恶意用户程序,缓冲区溢出5数字集成电路设计与系统应用专业驱动程序与内核版本号Linux内核版本号简述2.0.x2.2.x2.4.x2.6.x版本号在内核编译过程中的影响模块加载时的版本号检查6数字集成电路设计与系统应用专业Linux下构建和运行模块为什么用模块?模块和应用程序有什么不同#ifdef__KERNEL__#ifdefMODULE7数字集成电路设计与系统应用专业Linux内核与模块中的并发可重入简介共享资源带来的问题并发与同步问题抢占式内核对并发的影响8数字集成电路设计与系统应用专业模块的编译和装载编译模块都需要什么编译模块相关的宏模块工具insmod,rmmod,lsmod,modprobe,modinfo9数字集成电路设计与系统应用专业Linux驱动程序模块加载10数字集成电路设计与系统应用专业模块的版本依赖版本号定义可以区分不同版本内核的接口函数可以在linux/version.h找到版本定义KERNEL_VERSION11数字集成电路设计与系统应用专业模块初始化和关闭模块加载调用的第一个函数init_module模块所使用资源的分配与释放使用计数模块卸载和cleanup_module显式指定初始化和清除函数12数字集成电路设计与系统应用专业一个简单的Linux内核模块1#includelinux/init.h2#includelinux/module.h3MODULE_LICENSE(DualBSD/GPL);4staticinthello_init(void)5{6printk(KERN_ALERTHelloWorldenter\n);7return0;8}9staticvoidhello_exit(void)10{11printk(KERN_ALERTHelloWorldexit\n);12}13module_init(hello_init);14module_exit(hello_exit);1516MODULE_AUTHOR(SongBaohua);17MODULE_DESCRIPTION(AsimpleHelloWorldModule);18MODULE_ALIAS(asimplestmodule);13数字集成电路设计与系统应用专业Linux内核模块的程序结构模块加载函数(必须)模块卸载函数(必须)模块许可证声明(必须)大多数情况下,内核模块应遵循GPL兼容许可权。Linux2.6内核模块最常见的是以MODULE_LICENSE(DualBSD/GPL)语句声明模块采用BSD/GPL双LICENSE。模块参数(可选)。模块导出符号(可选)模块作者等信息声明(可选)14数字集成电路设计与系统应用专业模块参数module_param(参数名,参数类型,参数读/写权限)module_param(myshort,short,0000);MODULE_PARM_DESC(myshort,Ashortinteger);module_param(myint,int,0000);MODULE_PARM_DESC(myint,Aninteger);#insmodhello.komyshort=55myint=45615数字集成电路设计与系统应用专业导出符号Linux2.6的“/proc/kallsyms”文件对应着内核符号表,它记录了符号以及符号所在的内存地址。模块可以使用如下宏导出符号到内核符号表:EXPORT_SYMBOL(符号名);EXPORT_SYMBOL_GPL(符号名);16数字集成电路设计与系统应用专业模块的使用计数Linux2.4内核:MOD_INC_USE_COUNT、MOD_DEC_USE_COUNTLinux2.6内核:try_module_get(&module)该函数用于增加模块使用计数module_put(&module)该函数用于减少模块使用计数17数字集成电路设计与系统应用专业Linux驱动程序基础知识Linux字符设备驱动基础file_opration结构分析用户空间与内核空间数据传输基本字符设备驱动函数模板18数字集成电路设计与系统应用专业19Linux字符设备驱动基础驱动注册与初始化主设备号和次设备号设备名设备文件节点操作与fileoperation结构用户系统调用与驱动函数集合数字集成电路设计与系统应用专业20设备名与主次设备号字符设备文件例子crw-rw----1rootuucp4,642005-03-2003:36/dev/ttyS0主设备号区分设备驱动程序次设备号区分同一个驱动程序创建的多个设备常见于多个串口,硬盘分区等mknod创建设备文件:mknod/dev/mydevicec2540open、close等操作/dev/下设备文件,内核根据文件的主设备号找到对应驱动程序主设备号可以分为动态、静态申请数字集成电路设计与系统应用专业动态分配主设备号alloc_chrdev_region注册动态主设备号(2.6)动态分配主设备号的优缺点/proc/devices和lsmod动态生成设备文件系统节点dev_t和kdev_t21数字集成电路设计与系统应用专业22file_opration结构分析file在内核中定义linux/fs.hfilestruct{Mode_tf_modeLoff_tf_posUnsignedintf_flagsStructfile_operations*f_opvoid*private_dataStructdentry*f_dentry}数字集成电路设计与系统应用专业Linux驱动程序基础知识Linux字符设备驱动基础file_opration结构分析用户空间与内核空间数据传输基本字符设备驱动函数模板23数字集成电路设计与系统应用专业24file_opration结构分析file_operations在内核中定义linux/fs.hstructfile_operations{structmodule*owner;loff_t(*llseek)(structfile*,loff_t,int);ssize_t(*read)(structfile*,char__user*,size_t,loff_t*);ssize_t(*write)(structfile*,constchar__user*,size_t,loff_t*);unsignedint(*poll)(structfile*,structpoll_table_struct*);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);……};数字集成电路设计与系统应用专业25file_operationsint(*open)(structinode*,structfile*)增加使用计数,检查错误如果未初始化,则调用初始化识别次设备号,如果必要,更新f_op指针分配并填写被置于filp-private_data的数据结构int(*realse)(structinode*,structfile*)open逆操作数字集成电路设计与系统应用专业26file_operationsssize_t(*read)(structfile*,char*,size_t,loff_t*)用户空间和内核空间数据交互用户空间指针和内核指针驱动调用copy_to_user()将数据返回给用户ssize_t(*write)(structfile*,constchar*,size_t,loff_t*)驱动调用copy_from_user()将用户数据读到本地buffer数字集成电路设计与系统应用专业27file_operationsint(*mmap)(structfile*,structvm_area_struct*)驱动中提供该方法用于支持用户mmap操作用户将设备内存区映射到进程的地址空间,直接操作该物理内存提高效率典型例子:framebuffer,sound,capture等驱动数字集成电路设计与系统应用专业28file_operationsint(*ioctl)(structinode*,structfile*,unsignedintcmd,unsignedlongarg)驱动程序一般需支持通过Ioctl实现各种控制与参数设置,如串口可设置波特率等多参数cmd变量存放命令,驱动代码根据cmd里面的值进行switch-cas处理分支arg存放参数,如为整数,可直接使用。如为指针,驱动程序首先要检查指针的合法性intaccess_ok(inttype,constvoid*addr,unsignedlongsize);检查通过后可以使用驱动程序还可通过intcapable(intcapability)函数来确定调用进程是否有权执行操作数字集成电路设计与系统应用专业29怎样使用ioctl用户系统调用:intioctl(intfd,intcmd,...);cmd命令码格式用户空间与Linux内核中定义需一致:___________________________________|设备类型|序列号|方向|数据尺寸||----------|--------|------|--------||8bit|8bit|2bit|8~14bit|数字集成电路设计与系统应用专业Ioctl权能和受限操作驱动程序的访问控制采用linux文件系统的权限机制驱动程序采用权能机制来控制特殊的操作权限驱动程序通过intcapable(intcapability);函数来确定调用进程是否有权执行操作30数字集成电路设计与系统应用专业用ioctl控制驱动程序实例分析intscull_ioctl(structinode*inode,structfile*filp,unsignedintcmd,unsignedlongarg){interr=0,tmp;intretval=0;if(_IOC_TYPE(cmd)!=SCULL_IOC_MAGIC)return-ENOTTY;if(_IOC_NR(cmd)SCULL_IOC_MAXNR)return-ENOTTY;if(_IOC_DIR(cmd)&_IOC_READ)err=!access_ok(VERIFY_WRITE,(void__user*)arg,_IOC_SIZE(cmd));elseif(_IOC_DIR(cmd)&_IOC_WRITE)err=!ac

1 / 39
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功