字符设备驱动程序_第1页
字符设备驱动程序_第2页
字符设备驱动程序_第3页
字符设备驱动程序_第4页
字符设备驱动程序_第5页
已阅读5页,还剩38页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Linux字符设备驱动程序Linux驱动程序的分类字符设备驱动:用于驱动能够像字节流(文件)一样被访问的设备。应用程序通常可以利用open、close、read、write等系统调用访问字符设备驱动。块设备驱动:块设备和字符设备只在系统内核内部的管理上有所区别。应用程序对于字符设备的每一个I/O操作都会被内核直接传递给对应的驱动程序;而应用程序对于块设备的操作要经过虚拟文件系统(VFS)和缓冲区管理系统间接地传递给驱动程序处理。网络设备驱动:应用程序必须利用套接字(socket)接口访问网络设备。网络设备驱动程序字符设备驱动程序基本结构字符设备开发的基本步骤确定主设备号和次设备号实现字符驱动程序实现file_operations结构体构造字符设备结构体cdev在模块加载函数中注册字符设备在模块卸载函数中注销字符设备创建设备文件节点设备文件与设备号为了体现“一切都是文件”的设计思想,linux将每个已安装的设备都表示为一个设备文件。设备文件通常位于/dev子目录。对于字符设备,应用程序可以利用open、close、read、write等系统调用访问其设备文件,这些I/O操作都被直接传递给该设备文件所对应的设备。每个设备文件中都存储了该设备的“主设备号”和“次设备号”。一般由同一个内核模块管理的多个设备占用同一个主设备号,具体设备用次设备号标识。用mknodfilenamecmajorminor命令创建设备文件用rmfilename命令删除设备文件。注意删除设备文件并不会影响驱动模块。应用程序如何访问设备fd1=open(“/dev/ttyS1”,O_RDWR);//阻塞fd2=open(“/dev/ttyS1”,O_RDWR|O_NONBLOCK);//非阻塞intread(intfd,constvoid*buf,size_tlength);intwrite(intfd,constvoid*buf,size_tlength);intlseek(intfd,offset_toffset,intwhence);intioctl(intfd,intcmd,void*arg);intclose(intfd);设备号的内部表达设备编号的内部表达dev_t类型(32位):用来保存设备编号(包括主设备号(12位)和次设备号(20位))从dev_t获得主设备号和次设备号:MAJOR(dev_t);MINOR(dev_t);将主设备号和次设备号转换成dev_t类型:MKDEV(intmajor,intminor);

主设备号与次设备号分配主设备号手工分配主设备号:找一个内核没有使用的主设备号来使用。#include<linux/fs.h>intregister_chrdev_region(dev_tfirst,unsignedintcount,char*name);要分配的设备编号范围的起始值,次设备号经常为0所请求的连续设备编号的个数和该编号范围关联的设备名称主设设备备号号与与次次设设备备号号动态态分分配配主主设设备备号号::#include<linux/fs.h>intalloc_chrdev_resion(dev_t*dev,unsignedintfirstminor,unsignedintcount,char*name);输出出的的设设备备号号要使使用用的的被被请请求求的的第第一一个个次次设设备备号号主设设备备号号与与次次设设备备号号释放放设设备备号号voidunregister_chrdev_region(dev_tfirst,unsignedintcount);通常常在在模模块块的的清清除除函函数数中中调调用用。。记录录字字符符设设备备的的结结构构体体cdev实现现字字符符驱驱动动程程序序cdev结构构体体structcdev{structkobjectkobj;/*内嵌的kobject对象*/structmodule*owner;/*所属模块块*/structfile_operations*ops;/*文件操作作结构体体*/structlist_headlist;dev_tdev;/*设备号*/unsignedintcount;};cdev的kobj、list、count字段不用用我们关关系和维维护(内内核代劳劳),我我们只需需将其ops字段指向向为我们们自己的的fileoperations结构。对cdev结构体的的操作操作cdev的函数voidcdev_init(structcdev*,structfile_operations*);structcdev*cdev_alloc(void);intcdev_add(structcdev*,dev_t,unsigned);voidcdev_del(structcdev*);用于初始始化cdev的成员,,并建立立cdev和file_operations之间的连连接分别向系系统删除除一个cdev,完成字字符设备备的注销销,通常常在模块块的卸载载函数中中调用分别向系系统添加加一个cdev,完成字字符设备备的注册册,通常在模模块加载载函数中中调用函数用于于动态申申请一个个cdev内存file_operations结构体file_operations结构体字符驱动动和内核核的接口口:在include/linux/fs.h定义字符驱动动只要实实现一个个file_operations结构体并并注册到到内核中中,内核核就有了了操作此此设备的的能力。。structfile_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(*open)(structinode*,structfile*);int(*flush)(structfile*,fl_owner_tid);int(*release)(structinode*,structfile*);//……………………………};file_operations结构体file_operations的主要成员员:structmodule*owner:指向模块自自身open:打开设备release:关闭设备read:从设备上读读数据write:向设备上写写数据ioctl:I/O控制函数llseek:定位读写指指针mmap:映射设备空空间到进程程的地址空空间fileoperations的初始化structfile_operationsmy_fops={.owner=THIS_MODULE,.llseek=my_llseek,.read=my_read,.write=my_write,.ioctl=my_ioctl,.open=my_open,.release=my_release,};file结构体file结构代表一一个打开的的文件,它它由内核在在应用程序序open时创建,并并将该文件件所对应的的fileoperations记录在file结构中。在应用程序序调用close函数,内核核会释放该该数据结构构。structfile{structfile_operations *f_op;unsignedintf_flags;fmode_tf_mode;loff_tf_pos;struct dentry *f_dentryvoid*private_data;};file结构体file结构体file结构:file_operations结构相关的的一个结构构体。描述一个正正在打开的的设备文件件。成员:loff_tf_pos:当前读/写位置unsignedintf_flags标识文件打打开时,是是否可读或或可写O_RDONLYO_NONBLOCKO_SYNCstructfile_operations*f_op文件相关的的操作,指指向所实现现的structfile_operationsvoid*private_data:私有数据指指针。驱动动程序可以以将这个字字段用于任任何目的或或者忽略这个个字段。inode结构体内核用inode结构在内部部表示文件件,用于存存储文件访访问权限、、属主、组组、大小、、生产时间间等VFS关心的信息息。其字段中我我们只关心心i_rdev(设备号),和i_cdev(和该文件件所对应的的cdev结构)我们在创建建设备文件件时,内核核会自动创创建一个对对应的inode结构体,并并将其i_cdev字段指向对对应的字符符设备结构构体cdev(事先已经在在内核中注注册过)。Inode与file的区别:file表示打开的的文件描述述符,多个个file结构,可以指指向单个inode结构。structinode{dev_ti_rdev;structcdev*i_cdev;//……………………………};Inode结构体Inode结构中的两个个主要字段::dev_ti_rdev;对表示设备文文件的inode结构,该字段段包含了真正正的设备编号号。structcdev*i_cdev;structcdev是表示字符设设备的内核的的内部结构。。当inode指向一个字符符设备文件时时,该字段包包含了指向structcdev结构的指针从一个inode中获得主设备备号和次设备备号:unsignedintiminor(structinode*inode);unsignedintimajor(structinode*inode);字符设备驱动动程序基本结结构注册设备,在模块或驱动动初始化时调调用Linux-2.4及之前Linux-2.6intregister_chrdev(unsignedintmajor,constchar*name,structfile_operations*fops)如何操作字符符设备的接口口voidcdev_init(structcdev*,structfile_operations*);intcdev_add(structcdev*,dev_t,unsigned);字符设备驱动动程序基本结结构注销设备:在模块卸载时时调用Linux-2.4及之前Linux-2.6intunregister_chrdev(unsignedintmajor,constchar*name);voidcdev_del(structcdev*);字符设备驱动动程序基本结结构//设备驱动模块块加载函数staticint__initxxx_init(void){...cdev_init(&xxx_dev.cdev,&xxx_fops);//初始化cdevxxx_dev.cdev.owner=THIS_MODULE;//获取字符设备备号if(xxx_major){register_chrdev_region(xxx_dev_no,1,DEV_NAME);}else{alloc_chrdev_region(&xxx_dev_no,0,1,DEV_NAME);}ret=cdev_add(&xxx_dev.cdev,xxx_dev_no,1);//注册设备...}字符设备驱动动程序基本结结构/*设备驱动模块块卸载函数*/staticvoid__exitxxx_exit(void){unregister_chrdev_region(xxx_dev_no,1);//释放占用的设设备号cdev_del(&xxx_dev.cdev);//注销设备...}字符设备驱动动程序基本结结构打开模块使用计数数加1识别次设备号号硬件操作:检查设备相关关错误(诸如如设备未就绪绪或类似的硬硬件问题);;如果设备是首首次打开,则则对其初始化化;如果有中断操操作,申请中中断处理程序序;intopen(structinode*inode,structfile*filp);字符设备驱动动程序基本结结构关闭模块使用计数数减1释放由open分配的,保存存在filp>private_data里的所有内容容。硬件操作:如果申请了中中断,则释放放中断处理程程序。在最后一次关关闭操作时关关闭设备。intrelease(structinode*inode,structfile*filp);字符设备驱动动程序基本结结构read/writessize_tread(structfile*filp,char__user*buff,size_tcount,loff_t*offp);ssize_twrite(structfile*filp,constchar__user*buff,size_tcount,loff_t*offp);指向用户空间间的缓冲区,,这个缓冲区区或者保存将将写入的数据据,或者是一一个存放新读读入数据的空空缓冲区。用户在在文件件中存存取操操作的的位置置字符设设备驱驱动程程序基基本结结构用户空空间和和内核核空间间之间间的数数据拷拷贝过过程,,不能简简单的的用指指针操操作或或者memcpy来进行行数据据拷贝贝用户空空间的的数据据是可可以被被换出出的,,会产产生一一个页页面失失效异异常。。用户空空间的的地址址无法法在内内核空空间中中使用用。用户空空间和和内核核空间间之间间进行行数据据拷贝贝的函函数::如果要要复制制的内内存是是简单单类型型,如如char、int、long等,put_user()和get_user()unsignedlongcopy_from_user(void*to,constvoid__user*from,unsignedlongcount);unsignedlongcopy_to_user(void__user*to,constvoid*from,unsignedlongcount);字符符设设备备驱驱动动程程序序基基本本结结构构读设设备备模模板板ssize_txxx_read(structfile*filp,char__user*buf,size_tcount,loff_t*f_pos){...copy_to_user(buf,...,...);...}写设设备备模模板板ssize_txxx_write(structfile*filp,constchar__user*buf,size_tcount,loff_t*f_pos){...copy_from_user(...,buf,...);...}字符符设设备备驱驱动动程程序序基基本本结结构构ioctl函数数为设设备备驱驱动动程程序序执执行行““命命令令””提提供供了了一一个个特特有有的的入入口口点点用来来设设置置或或者者读读取取设设备备的的属属性性信信息息。。intioctl(structinode*inode,structfile*filp,unsignedintcmd,unsignedlongarg);事先先定定义义的的IO控制制命命令令代码码arg为对对应应于于cmd命令令的的参参数数字符符设设备备驱驱动动程程序序基基本本结结构构cmd参数数的的定定义义不推推荐荐用用0x1,0x2,0x3之类类的的值值Linux对ioctl()的cmd参数数有有特特殊殊的的定定义义构造造命命令令编编号号的的宏宏::_IO(type,nr)用于于构构造造无无参参数数的的命命令令编编号号;;_IOR(type,nr,datatype)用于于构构造造从从驱驱动动程程序序中中读读取取数数据据的的命命令令编编号号;;_IOW(type,nr,datatype)用于于写写入入数数据据的的命命令令;;_IOWR(type,nr,datatype)用于于双双向向传传输输。。type和number位字字段段通通过过参参数数传传入入,,而而size位字段通通过对datatype参数取sizeof获得。设备类型(type)

序列号(number)方向(direction)

数据尺寸(size)

8bit

8bit

2bit13/14bit字符设备备驱动程程序基本本结构Ioctl函数模板板intxxx_ioctl(structinode*inode,structfile*filp,unsignedintcmd,unsignedlongarg){...switch(cmd){caseXXX_CMD1:...break;caseXXX_CMD2:...break;default:///*不能支持持的命令令*/return-ENOTTY;}return0;}阶段总结结阶段总结结添加驱动动程序到到内核配置内核核编译内核核添加驱动动程序到到内核中中添加驱动动程序到到内核配置内核核配置命令令包括:makeconfigmakemenuconfigmakexconfigmakegconfig可通过““上”、、“下””、“左左”、““右”键键移动菜菜单,选选择某项项按“Y”,取消选择按““N”,如果选选择某项项编译为为模块按按“M”,进入子菜菜单按““Enter”,返回上一级菜菜单按““Esc””使用makeconfig、makemenuconfig等命令后后,会生生成一个个.config配置文件件(是隐身文件件,通过过ls––a才能看到到)添加驱动动程序到到内核编译内核核可用如下下命令编编译内核核:makeARC=armCROSS_COMPILE=arm-linux-zImage源代码根根目录的的Makefile中将ARCH和CROSS_COMPILE直接指定定为arm和arm-linux-,如:这样就没没有必要要每次编编译的时时候都指指定体系系结构和和交叉编编译器了了,只须使用用下面命命令就可可以了::makezImageARCH?=armCROSS_COMPILE ?=arm-linux-添加驱动动程序到到内核添加驱动动程序到到内核Linux2.6内核的配配置系统统由以下下3个部分组组成。Makefile:分布在Linux内核源代代码中的的Makefite定义Linux内核的编编译规则则配置文件件(Kconfig):给用户户提供配配置选择择的功能能。配置工具具:包括配置置命令解解释器(对配置脚脚本中使使用的配配置命令令进行解解释)配置用户户界面(提供字符符界面和和图形界界面)。这些配置置工具都都是使用用脚本语语言编写写的,如如Tcl/TK、Perl等。在Linux内核中中增加加程序序需要要完成成以下下3项工作作。将编写写的源源代码码复制制到Linux内核源源代码码的相相应目目录。。在目录录的Kconfig文件中中增加加新源源代码码对应应项目目的编编译配配置选选项。。在目录录的Makefile文件中中增加加对新新源代代码的的编译译条目目。添加驱驱动程程序到到内核核实例::在内核核源代代码drivers目录下下为ARM体系结结构新新增testdrivertestdriver的树形形目录录:步骤::1、拷贝贝test到drivers路径下下2、为新新增目目录创创建Kconfig和Makefile3、修改改新增增目录录父目目录的的Kconfig和Makefile,以便便新增增的Kconfig和Makefile能够被被引用用4、在arch/arm/Kconfig里增加加source““drivers/test/Kconfig””添加驱驱动程程序到到内核核步骤::1、拷贝贝test到drivers路径下下cp––frtestlinux_kernel_path/drivers2、为新新增目目录创创建Kconfig和Makefile添加驱驱动程程序到到内核核修改新新增目目录的的父目目录的的Kconfig和Makefile在drivers/Kconig中加入入:source"drivers/test/Kconfig““在drivers/Makefile中加入入:obj-$(CONFIG_TEST)+=test/在arch/arm/Kconfig里加入入:source““drivers/test/Kconfig””增加了了Kconfig和Makefile文件之之后的的新的的test树型目目录如如下所所示::用户空空间调调用设设备驱驱动程程序创建设设备节节点$mknod/dev/node_namecmajorminor示例代代码intmain(void){intdev_fd;charread_buf[10];dev_fd=open("/dev/node_name",O_RDWR|O_NONBLOCK);if(dev_fd==-1){printf("Cann'topenfile/dev/node_name\n");exit(1);}read(dev_fd,read_buf,5);ioctl(dev_fd,XXX_IOCTL_CMD,0);close(dev_fd);return0;}9、静夜四无邻邻,荒居旧业业贫。。12月-2212月-22Thursday,December29,202210、雨中黄黄叶树,,灯下白白头人。。。12:29:0812:29:0812:2912/29/202212:29:08PM11、以我独沈沈久,愧君君相见频。。。12月-2212:29:0812:29Dec-2229-Dec-2212、故人江海别别,几度隔山山川。。12:29:0812:29:0812:29Thursday,December29,202213、乍乍见见翻翻疑疑梦梦,,相相悲悲各各问问年年。。。。12月月-2212月月-2212:29:0812:29:08December29,202214、他乡生生白发,,旧国见见青山。。。29十十二月202212:29:08下下午12:29:0812月-2215、比比不不了了得得就就不不比比,,得得不不到到的的就就不不要要。。。。。十二二月月2212:29下下午午12月月-2212:29December29,202216、行动出成果果,工作出财财富。。2022/12/2912:29:0812:29:0829December202217、做前前,能能够环环视四四周;;做时时,你你只能能或者者最好好沿着着以脚脚为起起点的的射线线向前前。。。12:29:08下下午午12:29下下午12:29:0812月月-229、没有失失败,只只有暂时时停止成成功!。。12月-2212月-22Thursday,December29,202210、很多事情情努力了未未必有结果果,但是不不努力却什什么改变也也没有。。。12:29:0912:29:0912:2912/29/202212:29:09PM11、成功就是日日复一日那一一点点小小努努力的积累。。。12月-2212:29:0912:29Dec-2229-Dec-2212、世间间成事事,不不求其其绝对对圆满满,留留一份份不足足,可可得无无限完完美。。。12:29:0912:29:0912:29Thursday,December29,202213、不知香香积寺,,数里入入云峰。。。12月-2212月-2212:29:0912:29:09December29,202214、意志坚坚强的人人能把世世界放在在手中像

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论