资源描述:
《linux设备驱动学习4》由会员上传分享,免费在线阅读,更多相关内容在工程资料-天天文库。
1、Linux设备驱动程序学习(4)-高级字符驱动程序操作[(1)ioctlandllseek]今天进入《Linux设备驱动程序(第3版)》第六章高级字符驱动程序操作的学习。一、ioctl大部分设备除了读写能力,还可进行超出简单的数据传输之外的操作,所以设备驱动也必须具备进行各种硬件控制操作的能力.这些操作常常通过ioctl方法来支持,它有和用户空间版本不同的原型:int(*ioctl)(structinode*inode,structfile*filp, unsignedintcmd,unsignedlongarg);需要注意的是:不管可选的参数ar
2、g是否由用户给定为一个整数或一个指针,它都以一个unsignedlong的形式传递。如果调用程序不传递arg参数,被驱动收到的arg值是未定义的。因为在arg参数上的类型检查被关闭了,所以若一个非法参数传递给ioctl,编译器是无法报警的,且任何关联的错误难以查找.选择ioctl命令为了防止向错误的设备使用正确的命令,命令号应该在系统范围内唯一。为方便程序员创建唯一的ioctl命令代号,每个命令号被划分为多个位字段。要按Linux内核的约定方法为驱动选择ioctl的命令号,应该首先看看include/asm/ioctl.h和Documentation/ioctl-numbe
3、r.txt。要使用的位字段符号定义在:type(幻数):8位宽(_IOC_TYPEBITS),参考ioctl-number.txt选择一个数,并在整个驱动中使用它。number(序数):顺序编号,8位宽(_IOC_NRBITS)。direction(数据传送的方向):可能的值是_IOC_NONE(没有数据传输)、_IOC_READ、_IOC_WRITE和_IOC_READ
4、_IOC_WRITE(双向传输数据)。该字段是一个位掩码(两位),因此可使用AND操作来抽取_IOC_READ和_IOC_WRITE。size(数据的大小):宽度与体系结构有
5、关,ARM为14位.可在宏_IOC_SIZEBITS中找到特定体系的值. 中包含的定义了一些构造命令编号的宏:_IO(type,nr)/*没有参数的命令*/_IOR(type,nr,datatype)/*从驱动中读数据*/_IOW(type,nr,datatype)/*写数据*/_IOWR(type,nr,datatype)/*双向传送*//*type和number成员作为参数被传递,并且size成员通过应用sizeof到datatype参数而得到*/这个头文件还定义了用来解开这个字段的宏:_IOC_DIR(nr)_
6、IOC_TYPE(nr)_IOC_NR(nr)_IOC_SIZE(nr)具体的使用方法在实验中展示。返回值POSIX标准规定:如果使用了不合适的ioctl命令号,应当返回-ENOTTY。这个错误码被C库解释为"不合适的设备ioctl。然而,它返回-EINVAL仍是相当普遍的。预定义命令有一些ioctl命令是由内核识别的,当这些命令用于自己的设备时,他们会在我们自己的文件操作被调用之前被解码.因此,如果你选择一个ioctl命令编号和系统预定义的相同时,你永远不会看到该命令的请求,而且因为ioctl号之间的冲突,应用程序的行为将无法预测。预定义命令分为3类:(1)用于任何文件(
7、常规,设备,FIFO和socket)的命令(2)只用于常规文件的命令(3)特定于文件系统类型的命令 下列ioctl命令是预定义给任何文件,包括设备特定文件:FIOCLEX:设置close-on-exec标志(FileIOctlCloseonEXec)。FIONCLEX:清除close-no-exec标志(FileIOctlNotCLoseonEXec)。FIOQSIZE:这个命令返回一个文件或者目录的大小;当用作一个设备文件,但是,它返回一个ENOTTY错误。FIONBIO:"FileIOctlNon-BlockingI/O"(在"阻塞和非阻塞操作"一节中描述)。 使用io
8、ctl参数在使用ioctl的可选arg参数时,如果传递的是一个整数,它可以直接使用。如果是一个指针,,就必须小心。当用一个指针引用用户空间,我们必须确保用户地址是有效的,其校验(不传送数据)由函数access_ok实现,定义在:intaccess_ok(inttype,constvoid*addr,unsignedlongsize);第一个参数应当是VERIFY_READ(读)或VERIFY_WRITE(读写);addr参数为用户空间地址,size为字节数,可使用sizeof()。ac