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

📄 linux设备驱动程序学习(3-补)-linux中的循环缓冲区 - linux设备驱动程序 - tekkaman ninja.htm

📁 Linux设备驱动程序学习(3-补)-Linux中的循环缓冲区 - Linux设备驱动程序.rar
💻 HTM
📖 第 1 页 / 共 5 页
字号:
                              face="Times New Roman, serif"><FONT 
                              face="SimSun, serif"><SPAN 
                              lang=en-US>kfifo_init</SPAN></FONT></FONT>只会接受一个已分配好空间的<FONT 
                              face="Times New Roman, serif"><FONT 
                              face="SimSun, serif"><SPAN 
                              lang=en-US>fifo-&gt;buffer</SPAN></FONT></FONT>,不能和<FONT 
                              face="Times New Roman, serif"><FONT 
                              face="SimSun, serif"><SPAN 
                              lang=en-US>kfifo_free</SPAN></FONT></FONT>搭配,用<FONT 
                              face="Times New Roman, serif"><FONT 
                              face="SimSun, serif"><SPAN 
                              lang=en-US>kfifo_init</SPAN></FONT></FONT>分配的<FONT 
                              face="Times New Roman, serif"><FONT 
                              face="SimSun, serif"><SPAN 
                              lang=en-US>kfifo</SPAN></FONT></FONT>只能用<FONT 
                              face="Times New Roman, serif"><FONT 
                              face="SimSun, serif"><SPAN 
                              lang=en-US>kfree</SPAN></FONT></FONT>释放。” 
                              </FONT><FONT color=#ff0000>阅读源码可以得出这样的结论:<FONT 
                              face=宋体><SPAN lang=en-US>kfifo_init和<FONT 
                              face=新宋体>kfifo_alloc分配的<SPAN lang=en-US><FONT 
                              face=宋体>kfifo都</FONT></SPAN><FONT 
                              face="Courier New">能用</FONT><FONT 
                              face="Times New Roman, serif"><FONT 
                              face="SimSun, serif"><SPAN 
                              lang=en-US>kfree</SPAN></FONT></FONT><FONT 
                              face="Courier New">释放。已经用实验证实。</FONT></FONT></SPAN></FONT></FONT></DIV>
                              <DIV><FONT color=#000000><SPAN lang=en-US>原文链接地址: 
                              <FONT face="Times New Roman, serif"><A 
                              href="http://www.kerneltravel.net/jiaoliu/kern-kfifo.html">http://www.kerneltravel.net/jiaoliu/kern-kfifo.html</A></FONT></SPAN></FONT></DIV>
                              <DIV>
                              <HR id=null>
                              </DIV>
                              <DIV>在学习到<FONT color=#0000ff>第十章&nbsp;中断处理</FONT> 
                              时,其中的中断驱动的I/O需要使用缓冲区,我觉得与其自己实现一个缓冲区,不如利用内核已经写好的fifo。内核里有一个通用的循环缓冲区的实现在 
                              <FONT 
                              color=#0000ff>&lt;linux/kfifo.h&gt;。</FONT></DIV>
                              <DIV><FONT 
                              color=#0000ff><STRONG>使用的数据结构如下:</STRONG></FONT></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: #000000"><SPAN 
                                style="COLOR: #0000ff">struct</SPAN> kfifo <SPAN 
                                style="COLOR: #0000cc">{</SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;<SPAN 
                                style="COLOR: #0000ff">unsigned</SPAN> <SPAN 
                                style="COLOR: #0000ff">char</SPAN> <SPAN 
                                style="COLOR: #0000cc">*</SPAN>buffer<SPAN 
                                style="COLOR: #0000cc">;</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;<SPAN 
                                style="COLOR: #ff9900">/* 使用的缓冲区头指针 
                                */</SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;<SPAN 
                                style="COLOR: #0000ff">unsigned</SPAN> <SPAN 
                                style="COLOR: #0000ff">int</SPAN> size<SPAN 
                                style="COLOR: #0000cc">;</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;<SPAN 
                                style="COLOR: #ff9900">/* 缓冲区总大小 
                                */</SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;<SPAN 
                                style="COLOR: #0000ff">unsigned</SPAN> <SPAN 
                                style="COLOR: #0000ff">int</SPAN> in<SPAN 
                                style="COLOR: #0000cc">;</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;<SPAN 
                                style="COLOR: #ff9900">/* 
                                已写入缓冲区的数据总量,当前缓冲区写指针的偏移量:(in % size) 
                                */</SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;<SPAN 
                                style="COLOR: #0000ff">unsigned</SPAN> <SPAN 
                                style="COLOR: #0000ff">int</SPAN> out<SPAN 
                                style="COLOR: #0000cc">;</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;<SPAN 
                                style="COLOR: #ff9900">/* 
                                已读出缓冲区的数据总量,当前缓冲区读指针的偏移量:(out % size) 
                                */</SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;spinlock_t 
                                <SPAN style="COLOR: #0000cc">*</SPAN>lock<SPAN 
                                style="COLOR: #0000cc">;</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;<SPAN 
                                style="COLOR: #ff9900">/* 为避免竞态的自旋锁 
                                */</SPAN><BR><SPAN 
                                style="COLOR: #0000cc">}</SPAN><SPAN 
                                style="COLOR: #0000cc">;</SPAN><SPAN 
                                style="COLOR: #ff9900">/*当in==out时,缓冲区为空;当(in-out)==size时,缓冲区已满*/</SPAN></SPAN></CODE></P></TD></TR></TBODY></TABLE>
                              <P><FONT face="Times New Roman, serif"><FONT 
                              face="SimSun, serif"><SPAN 
                              lang=en-US>kfifo</SPAN></FONT></FONT>提供的循环缓冲的部分函数分为2类:</P>
                              <P>(1)以双下划线开头,没有使用自旋锁函数;</P>
                              <P>(2)没有双下划线开头,需要额外加锁的情况下使用的函数。</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: #000000"><FONT 
                                face=新宋体>&nbsp;&nbsp;&nbsp;&nbsp;<SPAN 
                                style="COLOR: #0000ff">unsigned</SPAN> <SPAN 
                                style="COLOR: #0000ff">long</SPAN> flags<SPAN 
                                style="COLOR: #0000cc">;</SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;spin_lock_irqsave<SPAN 
                                style="COLOR: #0000cc">(</SPAN>fifo<SPAN 
                                style="COLOR: #0000cc">-</SPAN><SPAN 
                                style="COLOR: #0000cc">&gt;</SPAN>lock<SPAN 
                                style="COLOR: #0000cc">,</SPAN> flags<SPAN 
                                style="COLOR: #0000cc">)</SPAN><SPAN 
                                style="COLOR: #0000cc">;</SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;<SPAN 
                                style="COLOR: #ff9900">/*第一类函数*/</SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;spin_unlock_irqrestore<SPAN 
                                style="COLOR: #0000cc">(</SPAN>fifo<SPAN 
                                style="COLOR: #0000cc">-</SPAN><SPAN 
                                style="COLOR: #0000cc">&gt;</SPAN>lock<SPAN 
                                style="COLOR: #0000cc">,</SPAN> flags<SPAN 
                                style="COLOR: #0000cc">)</SPAN><SPAN 
                                style="COLOR: #0000cc">;</SPAN></FONT></SPAN></CODE></P></TD></TR></TBODY></TABLE></P>
                              <P>以下我按使用的顺序介绍每个函数的使用,部分函数源码在<FONT 
                              face="Times New Roman, serif"><FONT 
                              face="SimSun, serif"><SPAN 
                              lang=en-US>kernel/kfifo.c</SPAN></FONT></FONT>中定义,这些接口是经过精心构造的,可以小心地避免一些边界情况,原理其实很简单,建议去看源码弄清楚实现的原理,可以学到一些编程技巧。</P>
                              <P>(0)声明循环缓冲数据结构<FONT color=#ff0000>指针</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: #000000"><FONT face=新宋体><SPAN 
                                style="COLOR: #0000ff">struct</SPAN> kfifo 
                                *tekkamanfifo<SPAN 
                                style="COLOR: #0000cc">;</SPAN></FONT></SPAN></CODE></P></TD></TR></TBODY></TABLE></P>
                              <P>(1)初始化循环缓冲结构体 
                              <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: #000000"><FONT face=新宋体><SPAN 
                                style="COLOR: #0000ff">struct</SPAN> kfifo <SPAN 
                                style="COLOR: #0000cc">*</SPAN>kfifo_init<SPAN 
                                style="COLOR: #0000cc">(</SPAN><SPAN 
                                style="COLOR: #0000ff">unsigned</SPAN> <SPAN 
                                style="COLOR: #0000ff">char</SPAN> <SPAN 
                                style="COLOR: #0000cc">*</SPAN>buffer<SPAN 
                                style="COLOR: #0000cc">,</SPAN> <SPAN 
                                style="COLOR: #0000ff">unsigned</SPAN> <SPAN 
                                style="COLOR: #0000ff">int</SPAN> size<SPAN 
                                style="COLOR: #0000cc">,</SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gfp_t 
                                gfp_mask<SPAN style="COLOR: #0000cc">,</SPAN> 
                                spinlock_t <SPAN 
                                style="COLOR: #0000cc">*</SPAN>lock<SPAN 
                                style="COLOR: #0000cc">)</SPAN><SPAN 
                                style="COLOR: #0000cc">;</SPAN><BR><SPAN 
                                style="COLOR: #ff9900">/*调用kfifo_init必须保证size是2的整数次幂,而且<FONT 
                                color=#000000>buffer</FONT>只接受一个已分配好空间的指针。也就是说之前要使用kmalloc分配好空间,将返回的指针传递到buffer*/</SPAN><BR><SPAN 
                                style="COLOR: #0000ff">struct</SPAN> kfifo <SPAN 
                                style="COLOR: #0000cc">*</SPAN>kfifo_alloc<SPAN 
                                style="COLOR: #0000cc">(</SPAN><SPAN 
                                style="COLOR: #0000ff">unsigned</SPAN> <SPAN 
                                style="COLOR: #0000ff">int</SPAN> size<SPAN 
                                style="COLOR: #0000cc">,</SPAN> gfp_t 
                                gfp_mask<SPAN 
                                style="COLOR: #0000cc">,</SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
                                spinlock_t <SPAN 
                                style="COLOR: #0000cc">*</SPAN>lock<SPAN 
                                style="COLOR: #0000cc">)</SPAN><SPAN 
                                style="COLOR: #0000cc">;</SPAN><BR><SPAN 
                                style="COLOR: #ff9900">/*调用kfifo_alloc不必保证size是2的幂,它内部会把size向上调整到2的整数次幂。空间分配的内部实现使用kmalloc。函数内部调用kfifo_init/</SPAN></FONT></SPAN></CODE></P></TD></TR></TBODY></TABLE></P>
                              <P><FONT 
                              face=新宋体>buffer:之前要使用kmalloc分配好的空间指针;</FONT></P>
                              <P><FONT face=新宋体>size:循环缓冲空间大小;</FONT></P>
                              <P><FONT 
                              face=新宋体>gfp_mask:和kmalloc使用的分配标志(flags)一样。(参阅<A 
                              title=Linux设备驱动程序学习(8)-分配内存 
                              href="http://blog.chinaunix.net/u1/34474/showart.php?id=428673" 
                              target=_blank><FONT 
                              color=#800080>Linux设备驱动程序学习(8)-分配内存</FONT></A>)</FONT></P>
                              <P><FONT face=新宋体>lock:是<FONT 
                              color=#ff0000>事先声明并初始化好的</FONT>自旋锁结构体指针;</FONT></P>
                              <P><FONT face=新宋体><FONT color=#0000ff>返回值</FONT> 
                              为初始化好的</FONT><FONT face="Courier New">循环缓冲数据结构指针 
                              。</FONT></P>
                              <P><FONT face=新宋体>(2) 向缓冲区里写入数据</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 

⌨️ 快捷键说明

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