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

📄 一个简单的演示用的linux字符设备驱动程序.htm

📁 一个嵌入式linux字符驱动的例子。适合于初学者。
💻 HTM
📖 第 1 页 / 共 2 页
字号:
data_size指定缓冲区中有效数据的字节数。我们的设备<BR>只支持读不支持写。我们在char8139_init()中为缓冲区分配空间。<BR><BR>char8139_exit()里面的操作就是char8139_init()里面操作的反向操作。<BR><BR><BR>现在我们来看看,假如用户调用了"cat 
/dev/char8139_3"这个命令会发生什么事情。<BR>根据前面的介绍,我们驱动程序中的open()函数会被调用。<BR><BR>int 
char8139_open(struct inode *node, struct file *flip)<BR>{<BR>int type = 
MINOR(node-&gt;i_rdev)&gt;&gt;4;<BR>int num = MINOR(node-&gt;i_rdev) &amp; 
0x0F;<BR><BR>/* put some char in buffer to reflect the minor device number 
*/<BR>*buffer=(unsigned char)('0');<BR>*(buffer+1)=(unsigned 
char)('x');<BR>*(buffer+2)=(unsigned char)('0'+type);<BR>*(buffer+3)=(unsigned 
char)('0'+num);<BR>*(buffer+4)=(unsigned 
char)('\n');<BR>data_size+=5;<BR><BR>PDBG("Ok. Find treasure! 8139 I/O port 
base: %x\n", detect_8139_io_port());<BR>PDBG("OK. Find treasure! 8139 I/O memory 
base address: 
%lx\n",<BR>detect_8139_io_mem());<BR><BR>MOD_INC_USE_COUNT;<BR><BR>return 
0;<BR>}<BR>这里演示了次设备号的作用,它让我们知道用户操作的是哪一个"次设备",是/dev/char8139_0还是<BR>/dev/char8139_3,因为对不同的"次设备",具体的操作方法可能是不一样的,这样就为一个驱动程序<BR>控制多个类似的设备提供了可能。<BR><BR>我们根据次设备号的不同,在buffer中填入不同的字符(次设备号的16进制表示)。<BR><BR>接着驱动程序中的read()函数会被调用,因为cat程序的实现就是读取文件中的内容。<BR><BR>ssize_t 
char8139_read (struct file *filp, char *buf, size_t count, loff_t 
*f_pos)<BR>{<BR>ssize_t ret=0;<BR><BR>PDBG("copy to user. count=%d, 
f_pos=%ld\n", (int)count, (long)*f_pos);<BR>if(*f_pos&gt;= data_size)<BR>return 
ret;<BR>if(*f_pos + count &gt; data_size)<BR>count = 
data_size-*f_pos;<BR>if(copy_to_user(buf, p_buf, count))<BR>{<BR>PDBG("OOps, 
copy to user error.\n");<BR>return -EFAULT;<BR>}<BR><BR>p_buf += 
count;<BR>*f_pos += count;<BR>ret=count;<BR><BR>return 
ret;<BR>}<BR><BR>要正确的实现一个read()调用,你得想一想一个应用程序是如何调用read()从文件中读取数据的。<BR>如果你想明白了就很简单,驱动程序所要做的就是把恰当的数据传递给应用程序,这是使用<BR>copy_to_user()函数完成的。<BR><BR>另外,我们必须得意识到,这里只是一个很简单的演示。还有很多复杂的问题有待考虑,比如两个<BR>应用程序可能同时打开我们设备,我们的设备应该怎样反应(这取决于具体的设备应有的行为),还有<BR>互斥的问题。<BR><BR>然后我们看看I/O端口和I/O内存的操作。这里使用8139网卡作为一个硬件实例来演示I/O端口和<BR>I/O内存的操作。没有什么特别的,都是标准的步骤。在使用时需要注意,如果你的系统中已经有<BR>8139网卡的驱动程序,必须先关掉网络设备,卸载驱动,然后再使用本驱动程序。<BR><BR>使用程序包的步骤:(在我的Debian系统上如此,你的可能不同)<BR>1. 
解压<BR>2. 编译(/usr/src/linux处必须要有内核源代码)<BR>3. ifconfig eth0 down 关掉网络设备<BR>rmmod 
8139too 卸载原来的8139网卡驱动<BR>insmod char8139.o 插入我们的模块<BR>(insmod会出错, 
如果你现在运行的linux版本不是你编译本驱动程序时使用的内<BR>核源代码的版本,insmod时会报告模块版本与内核版本不一致。这时,你得看看<BR>内核源代码中/include/linux/version.h文件,这个文件中的UTS_RELEASE<BR>定义了内核的版本号,你可以在驱动程序中预先定义这个宏为当前运行的内核的<BR>版本号,这样就能避免上述错误。)<BR><BR>4. 
mknode(见本文前述)<BR>5. 试试我们的设备<BR>./readtest<BR>或者<BR>cat /dev/char8139_0或<BR>cat 
/dev/char8139_1或<BR>cat /dev/char8139_2或<BR>cat /dev/char8139_3<BR>6. 
恢复系统<BR>rmmod char8139<BR>modprobe 8139too<BR>ifconfig eth0 
up<BR>如果你使用dhcp可能还需要运行dhclient <BR><BR></P>
<P class=diaryFoot>【作者: <A 
onclick="window.open('http://publishblog.blogchina.com/blog/postMessage.b?receiver=89297','发送短消息','width=520, height=455')" 
href="javascript:void(0);">linuxipy</A>】【访问统计:
<SCRIPT language=JavaScript 
src="一个简单的演示用的Linux字符设备驱动程序.files/PageServlet.htm"></SCRIPT>
】【2005年01月6日 星期四 23:53】【 <A 
href="javascript:void(keyit=window.open('http://blogmark.blogchina.com/jsp/key/quickaddkey.jsp?k='+encodeURI('一个简单的演示用的Linux字符设备驱动程序')+'&amp;u='+encodeURI('http://linuxipy.blogchina.com/linuxipy/507920.html')+'&amp;c='+encodeURI(''),'keyit','scrollbars=no,width=500,height=430,status=no,resizable=yes'));keyit.focus();">加入博采</A>】【<A 
href="javascript:window.print();">打印</A>】 </TD></P></DIV>
<DIV class=operation><A name=trackback>
<H3>Trackback</H3></A>
<P class=trackback>你可以使用这个链接引用该篇文章 
http://publishblog.blogchina.com/blog/tb.b?diaryID=507920 </P></DIV>
<DIV class=operation><A name=comment>
<H3>回复</H3></A>
<TABLE cellSpacing=0 cellPadding=0 width=700 border=0>
  <TBODY></TBODY></TABLE></DIV>
<DIV class=operation>
<TABLE class=comment cellSpacing=0 cellPadding=0 width=700 border=0>
  <FORM id=replyForm method=post><INPUT type=hidden value=86487 name=blogID> 
  <INPUT type=hidden value=507920 name=diaryID> <INPUT type=hidden 
  value=linuxipy name=blogDomino>
  <SCRIPT>
if(getCookie('userID') == null){        
document.write('<tr><td width="70">发布人:</td>');
document.write('<td width="150"> <input name="remark.authorNameFUI" type="text" size="20" class="inputStyle" maxlength="20"></td>');
document.write('<td width="70">邮箱:</td>');
document.write('<td width="435"> <input name="remark.authorEmail" type="text" size="20" class="inputStyle" maxlength="40"></td>');
document.write('</tr><tr><td>主 页:</td>');
document.write('<td colspan="3"> <input name="remark.authorURL" type="text" class="inputStyle" value="HTTP://" size="63" maxlength="100"></td></tr>');
}else{
document.write('<input type="hidden" name="remark.authorNameFUI" value="Blogchina网友">');
}
</SCRIPT>
   
  <TBODY>
  <TR>
    <TD width=70>验证码:</TD>
    <TD><INPUT class=inputStyle maxLength=4 name=validateCode></TD>
    <TD>&nbsp;&nbsp;<IMG src="一个简单的演示用的Linux字符设备驱动程序.files/getValidateImg.gif" 
      border=0></TD></TR>
  <TR align=left>
    <TD colSpan=4>评论内容:<BR><TEXTAREA class=textStyle id=remark name=remark.remarkFUI rows=8 cols=60>          </TEXTAREA> 
    </TD></TR>
  <TR align=left>
    <TD colSpan=4>              <INPUT onclick=reply() type=button value=提交>   
<INPUT type=reset value=重置> </TD></TR></FORM></TBODY></TABLE></DIV></DIV>
<SCRIPT src="一个简单的演示用的Linux字符设备驱动程序.files/extend3.js" 
type=text/javascript></SCRIPT>

<DIV id=footer><A href="http://blog.bokee.com/">2003-2004 BOKEE.COM All rights 
reserved</A><BR><A href="http://www.blogdriver.com/">Powered by BlogDriver 
2.1</A> </DIV></BODY></HTML>

⌨️ 快捷键说明

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