⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 linux设备驱动程序学习(4)-高级字符驱动程序操作[(1)ioctl and llseek] - linux设备驱动程序 - tekkaman ninja.htm

📁 Linux设备驱动程序学习(4)-高级字符驱动程序操作[(1)ioctl and llseek] - Linux设备驱动程序.rar
💻 HTM
📖 第 1 页 / 共 5 页
字号:
                              style="COLOR: rgb(0,1,255)">《Linux设备驱动程序(第3版)》</SPAN><SPAN 
                              style="FONT-WEIGHT: normal; COLOR: rgb(0,1,2)">第六章高级字符驱动程序操作的学习。</SPAN></DIV>
                              <DIV>
                              <HR id=null>
                              </DIV>
                              <DIV><FONT color=#0000ff 
                              size=4><STRONG>一、ioctl</STRONG></FONT></DIV>
                              <DIV>大部分设备除了读写能力,还可进行超出简单的数据传输之外的操作,所以设备驱动也必须具备进行各种硬件控制操作的能力. 
                              这些操作常常通过 ioctl 方法来支持,它有和用户空间版本不同的原型:</DIV>
                              <TABLE style="BORDER-COLLAPSE: collapse" 
                              borderColor=#999999 cellSpacing=0 cellPadding=0 
                              width="95%" bgColor=#f1f1f1 border=1>
                                <TBODY>
                                <TR>
                                <TD>
                                <P 
                                style="MARGIN: 5px; LINE-HEIGHT: 150%"><CODE><SPAN 
                                style="COLOR: rgb(0,0,0)"><SPAN 
                                style="COLOR: rgb(0,0,255)">int</SPAN> <SPAN 
                                style="COLOR: rgb(0,0,204)">(</SPAN><SPAN 
                                style="COLOR: rgb(0,0,204)">*</SPAN>ioctl<SPAN 
                                style="COLOR: rgb(0,0,204)">)</SPAN> <SPAN 
                                style="COLOR: rgb(0,0,204)">(</SPAN><SPAN 
                                style="COLOR: rgb(0,0,255)">struct</SPAN> inode 
                                <SPAN 
                                style="COLOR: rgb(0,0,204)">*</SPAN>inode<SPAN 
                                style="COLOR: rgb(0,0,204)">,</SPAN> <SPAN 
                                style="COLOR: rgb(0,0,255)">struct</SPAN> <SPAN 
                                style="COLOR: rgb(255,0,0)">file</SPAN> <SPAN 
                                style="COLOR: rgb(0,0,204)">*</SPAN>filp<SPAN 
                                style="COLOR: rgb(0,0,204)">,</SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<SPAN 
                                style="COLOR: rgb(0,0,255)">unsigned</SPAN> 
                                <SPAN style="COLOR: rgb(0,0,255)">int</SPAN> 
                                cmd<SPAN style="COLOR: rgb(0,0,204)">,</SPAN> 
                                <SPAN 
                                style="COLOR: rgb(0,0,255)">unsigned</SPAN> 
                                <SPAN style="COLOR: rgb(0,0,255)">long</SPAN> 
                                <SPAN 
                                style="COLOR: rgb(255,0,0)">arg</SPAN><SPAN 
                                style="COLOR: rgb(0,0,204)">)</SPAN><SPAN 
                                style="COLOR: rgb(0,0,204)">;</SPAN></SPAN></CODE></P></TD></TR></TBODY></TABLE>
                              <P><FONT 
                              color=#0000ff>需要注意的是:不管可选的参数arg是否由用户给定为一个整数或一个指针,它都以一个unsigned 
                              long的形式传递。如果调用程序不传递arg参数, 被驱动收到的 arg 
                              值是未定义的。因为在arg参数上的类型检查被关闭了,所以若一个非法参数传递给 
                              ioctl,编译器是无法报警的,且任何关联的错误难以查找.</FONT></P>
                              <P><FONT color=#0000ff size=3><STRONG>选择<FONT 
                              face=新宋体>ioctl</FONT>命令</STRONG></FONT></P>
                              <P>为了防止向错误的设备使用正确的命令,命令号应该在系统范围内唯一。为方便程序员创建唯一的 
                              ioctl 命令代号, 每个命令号被划分为多个位字段。要按 Linux 内核的约定方法为驱动选择 
                              ioctl 的命令号, 应该首先看看 include/asm/ioctl.h 和 
                              Documentation/ioctl-number.txt。 要使用的位字段符号定义在 <FONT 
                              color=#0000ff>&lt;linux/ioctl.h&gt;</FONT> :</P>
                              <P><FONT color=#0000ff>type(幻数):</FONT>8 
                              位宽(_IOC_TYPEBITS),参考ioctl-number.txt选择一个数,并在整个驱动中使用它。</P>
                              <P><FONT color=#0000ff><SPAN 
                              class=term><SPAN>number(</SPAN></SPAN>序数):</FONT>顺序编号,8 
                              位宽(_IOC_NRBITS)。</P>
                              <P><FONT color=#0000ff><SPAN 
                              class=term><SPAN>direction(</SPAN></SPAN>数据传送的方向):</FONT>可能的值是 
                              _IOC_NONE(没有数据传输)、_IOC_READ、 _IOC_WRITE和 
                              _IOC_READ|_IOC_WRITE (双向传输数据)。该字段是一个位掩码(两位), 因此可使用 
                              AND 操作来抽取_IOC_READ 和 _IOC_WRITE。</P>
                              <P><FONT color=#0000ff><SPAN 
                              class=term><SPAN>size(</SPAN></SPAN>数据的大小):</FONT>宽度与体系结构有关,ARM为14位.可在宏 
                              _IOC_SIZEBITS 中找到特定体系的值.&nbsp; </P>
                              <DT>&nbsp;&lt;linux/ioctl.h&gt; 中包含的 
                              &lt;asm/ioctl.h&gt;定义了一些构造命令编号的宏: 
                              <DIV></DIV>
                              <TABLE style="BORDER-COLLAPSE: collapse" 
                              borderColor=#999999 cellSpacing=0 cellPadding=0 
                              width="95%" bgColor=#f1f1f1 border=1>
                                <TBODY>
                                <TR>
                                <TD>
                                <P 
                                style="MARGIN: 5px; LINE-HEIGHT: 150%"><CODE><SPAN 
                                style="COLOR: rgb(0,0,0)">_IO<SPAN 
                                style="COLOR: rgb(0,0,204)">(</SPAN>type<SPAN 
                                style="COLOR: rgb(0,0,204)">,</SPAN>nr<SPAN 
                                style="COLOR: rgb(0,0,204)">)</SPAN><SPAN 
                                style="COLOR: rgb(255,153,0)">/*没有参数的命令*/</SPAN><BR>_IOR<SPAN 
                                style="COLOR: rgb(0,0,204)">(</SPAN>type<SPAN 
                                style="COLOR: rgb(0,0,204)">,</SPAN> nr<SPAN 
                                style="COLOR: rgb(0,0,204)">,</SPAN> 
                                datatype<SPAN 
                                style="COLOR: rgb(0,0,204)">)</SPAN><SPAN 
                                style="COLOR: rgb(255,153,0)">/*从驱动中读数据*/</SPAN><BR>_IOW<SPAN 
                                style="COLOR: rgb(0,0,204)">(</SPAN>type<SPAN 
                                style="COLOR: rgb(0,0,204)">,</SPAN>nr<SPAN 
                                style="COLOR: rgb(0,0,204)">,</SPAN>datatype<SPAN 
                                style="COLOR: rgb(0,0,204)">)</SPAN><SPAN 
                                style="COLOR: rgb(255,153,0)">/*写数据*/</SPAN><BR>_IOWR<SPAN 
                                style="COLOR: rgb(0,0,204)">(</SPAN>type<SPAN 
                                style="COLOR: rgb(0,0,204)">,</SPAN>nr<SPAN 
                                style="COLOR: rgb(0,0,204)">,</SPAN>datatype<SPAN 
                                style="COLOR: rgb(0,0,204)">)</SPAN><SPAN 
                                style="COLOR: rgb(255,153,0)">/*双向传送*/</SPAN><BR><SPAN 
                                style="COLOR: rgb(255,153,0)">/*type 和 number 
                                成员作为参数被传递, 并且 size 成员通过应用 sizeof 到 datatype 
                                参数而得到*/</SPAN></SPAN></CODE></P></TD></TR></TBODY></TABLE>
                              <P>这个头文件还定义了用来解开这个字段的宏:</P>
                              <TABLE style="BORDER-COLLAPSE: collapse" 
                              borderColor=#999999 cellSpacing=0 cellPadding=0 
                              width="95%" bgColor=#f1f1f1 border=1>
                                <TBODY>
                                <TR>
                                <TD>
                                <P 
                                style="MARGIN: 5px; LINE-HEIGHT: 150%"><CODE><SPAN 
                                style="COLOR: rgb(0,0,0)">_IOC_DIR<SPAN 
                                style="COLOR: rgb(0,0,204)">(</SPAN>nr<SPAN 
                                style="COLOR: rgb(0,0,204)">)</SPAN><BR>_IOC_TYPE<SPAN 
                                style="COLOR: rgb(0,0,204)">(</SPAN>nr<SPAN 
                                style="COLOR: rgb(0,0,204)">)</SPAN><BR>_IOC_NR<SPAN 
                                style="COLOR: rgb(0,0,204)">(</SPAN>nr<SPAN 
                                style="COLOR: rgb(0,0,204)">)</SPAN><BR>_IOC_SIZE<SPAN 
                                style="COLOR: rgb(0,0,204)">(</SPAN>nr<SPAN 
                                style="COLOR: rgb(0,0,204)">)</SPAN></SPAN></CODE></P></TD></TR></TBODY></TABLE>
                              <P>具体的使用方法在实验中展示。</P>
                              <P><FONT color=#0000ff 
                              size=3><STRONG>返回值</STRONG></FONT></P>
                              <P>POSIX 标准规定:如果使用了不合适的 ioctl 命令号,应当返回-ENOTTY 
                              。这个错误码被 C 库解释为"不合适的设备 ioctl。然而,它返回-EINVAL仍是相当普遍的。 
                              </P>
                              <P><FONT color=#0000ff 
                              size=3><STRONG>预定义命令</STRONG></FONT></P>
                              <DIV>
                              <P>有一些ioctl命令是由内核识别的,当这些命令用于自己的设备时,他们会在我们自己的文件操作被调用之前被解码. 
                              因此, 
                              如果你选择一个ioctl命令编号和系统预定义的相同时,你永远不会看到该命令的请求,而且因为ioctl 
                              号之间的冲突,应用程序的行为将无法预测。预定义命令分为 3 类:</P></DIV>
                              <DT>
                              <DIV>
                              <P>(1)用于任何文件(常规, 设备, FIFO和socket) 的命令</P></DIV>
                              <DT>
                              <DIV>
                              <P>(2)只用于常规文件的命令</P></DIV>
                              <DT>
                              <DIV>
                              <P>(3)特定于文件系统类型的命令&nbsp;</P></DIV>
                              <DT>
                              <DIV>
                              <P>下列 ioctl 命令是预定义给任何文件,包括设备特定文件:</P>
                              <DIV class=variablelist>
                              <DL>
                                <DT><SPAN class=term><SPAN>FIOCLEX 
                                :</SPAN></SPAN>设置 close-on-exec 标志(File IOctl 
                                Close on EXec)。 
                                <DT><SPAN class=term><SPAN>FIONCLEX 
                                :</SPAN></SPAN>清除 close-no-exec 标志(File IOctl 
                                Not CLose on EXec)。 
                                <DT><SPAN class=term><SPAN>FIOQSIZE 
                                :</SPAN></SPAN>这个命令返回一个文件或者目录的大小; 当用作一个设备文件, 但是, 
                                它返回一个 ENOTTY 错误。 
                                <DT><SPAN 
                                class=term><SPAN>FIONBIO</SPAN></SPAN>:"File 
                                IOctl Non-Blocking I/O"(在"阻塞和非阻塞操作"一节中描述)。&nbsp; 
                                </DT></DL></DIV>
                              <P><FONT color=#0000ff 
                              size=4><STRONG>使用ioctl参数</STRONG></FONT></P></DIV>
                              <DT>
                              <DIV>
                              <P>在使用ioctl的可选arg参数时,如果传递的是一个整数,它可以直接使用。如果是一个指针,,就必须小心。当用一个指针引用用户空间, 
                              我们必须确保用户地址是有效的,其校验(不传送数据)由函数<FONT color=#ff0000> 
                              access_ok</FONT> 实现,定义在<FONT color=#0000ff> 
                              &lt;asm/uaccess.h&gt;</FONT> : 
                              <TABLE style="BORDER-COLLAPSE: collapse" 
                              borderColor=#999999 cellSpacing=0 cellPadding=0 
                              width="95%" bgColor=#f1f1f1 border=1>
                                <TBODY>
                                <TR>
                                <TD>
                                <P 
                                style="MARGIN: 5px; LINE-HEIGHT: 150%"><CODE><SPAN 
                                style="COLOR: rgb(0,0,0)"><FONT face=新宋体><SPAN 
                                style="COLOR: rgb(0,0,255)">int</SPAN> 
                                access_ok<SPAN 
                                style="COLOR: rgb(0,0,204)">(</SPAN><SPAN 
                                style="COLOR: rgb(0,0,255)">int</SPAN> type<SPAN 
                                style="COLOR: rgb(0,0,204)">,</SPAN> <SPAN 
                                style="COLOR: rgb(0,0,255)">const</SPAN> <SPAN 
                                style="COLOR: rgb(0,0,255)">void</SPAN> <SPAN 
                                style="COLOR: rgb(0,0,204)">*</SPAN>addr<SPAN 
                                style="COLOR: rgb(0,0,204)">,</SPAN> <SPAN 
                                style="COLOR: rgb(0,0,255)">unsigned</SPAN> 
                                <SPAN style="COLOR: rgb(0,0,255)">long</SPAN> 
                                size<SPAN 
                                style="COLOR: rgb(0,0,204)">)</SPAN><SPAN 
                                style="COLOR: rgb(0,0,204)">;</SPAN> 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -