📄 linux设备驱动程序学习(1)-字符设备驱动程序 - linux设备驱动程序 - tekkaman ninja.htm
字号:
style="FONT-WEIGHT: normal">主设备号表示设备对应的驱动程序;次设备号由内核使用,用于正确确定设备文件所指的设备。</SPAN><BR
style="FONT-WEIGHT: normal"><SPAN
style="FONT-WEIGHT: normal">内核用dev_t类型(<SPAN
style="COLOR: rgb(0,1,255)"><linux/types.h></SPAN>)来保存设备编号,dev_t是一个32位的数,12位表示主设备号,20为表示次设备号。</SPAN><BR
style="FONT-WEIGHT: normal"><SPAN
style="FONT-WEIGHT: normal">在实际使用中,是通过<SPAN
style="COLOR: rgb(0,1,255)"><linux/kdev_t.h></SPAN>中定义的宏来转换格式。</SPAN><BR></SPAN>
<TABLE style="WIDTH: 447px; HEIGHT: 21px"
cellSpacing=1 cellPadding=1 border=1>
<TBODY>
<TR>
<TD> (dev_t)-->主设备号、次设备号</TD>
<TD> MAJOR(dev_t dev)<BR> MINOR(dev_t
dev)<BR></TD></TR>
<TR>
<TD> 主设备号、次设备号-->(dev_t)</TD>
<TD> MKDEV(int major,int
minor) </TD></TR></TBODY></TABLE><BR
style="COLOR: rgb(0,1,2)"><SPAN
style="FONT-WEIGHT: normal; COLOR: rgb(0,1,2)">建立一个字符设备之前,驱动程序首先要做的事情就是获得设备编号。其这主要函数在<SPAN
style="COLOR: rgb(0,1,255)"><linux/fs.h></SPAN>中声明:</SPAN><BR></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)"><SPAN
style="COLOR: rgb(0,0,255)">int</SPAN>
register_chrdev_region<SPAN
style="COLOR: rgb(0,0,204)">(</SPAN>dev_t
first<SPAN style="COLOR: rgb(0,0,204)">,</SPAN>
<SPAN
style="COLOR: rgb(0,0,255)">unsigned</SPAN>
<SPAN style="COLOR: rgb(0,0,255)">int</SPAN>
<SPAN
style="COLOR: rgb(255,0,0)">count</SPAN><SPAN
style="COLOR: rgb(0,0,204)">,</SPAN><BR><SPAN
style="COLOR: rgb(0,0,255)">char</SPAN> <SPAN
style="COLOR: rgb(0,0,204)">*</SPAN>name<SPAN
style="COLOR: rgb(0,0,204)">)</SPAN><SPAN
style="COLOR: rgb(0,0,204)">;
//指定设备编号</SPAN><BR><BR><SPAN
style="COLOR: rgb(0,0,255)">int</SPAN>
alloc_chrdev_region<SPAN
style="COLOR: rgb(0,0,204)">(</SPAN>dev_t <SPAN
style="COLOR: rgb(0,0,204)">*</SPAN>dev<SPAN
style="COLOR: rgb(0,0,204)">,</SPAN> <SPAN
style="COLOR: rgb(0,0,255)">unsigned</SPAN>
<SPAN style="COLOR: rgb(0,0,255)">int</SPAN>
firstminor<SPAN
style="COLOR: rgb(0,0,204)">,</SPAN><BR><SPAN
style="COLOR: rgb(0,0,255)">unsigned</SPAN>
<SPAN style="COLOR: rgb(0,0,255)">int</SPAN>
<SPAN
style="COLOR: rgb(255,0,0)">count</SPAN><SPAN
style="COLOR: rgb(0,0,204)">,</SPAN> <SPAN
style="COLOR: rgb(0,0,255)">char</SPAN> <SPAN
style="COLOR: rgb(0,0,204)">*</SPAN>name<SPAN
style="COLOR: rgb(0,0,204)">)</SPAN><SPAN
style="COLOR: rgb(0,0,204)">;
//动态生成设备编号</SPAN><BR><BR><SPAN
style="COLOR: rgb(0,0,255)">void</SPAN>
unregister_chrdev_region<SPAN
style="COLOR: rgb(0,0,204)">(</SPAN>dev_t
first<SPAN style="COLOR: rgb(0,0,204)">,</SPAN>
<SPAN
style="COLOR: rgb(0,0,255)">unsigned</SPAN>
<SPAN style="COLOR: rgb(0,0,255)">int</SPAN>
<SPAN
style="COLOR: rgb(255,0,0)">count</SPAN><SPAN
style="COLOR: rgb(0,0,204)">)</SPAN><SPAN
style="COLOR: rgb(0,0,204)">;
//释放设备编号<BR></SPAN></SPAN></CODE></P></TD></TR></TBODY></TABLE><FONT
size=4><BR style="COLOR: rgb(255,1,2)"><SPAN
style="COLOR: rgb(255,1,2)">分配之设备号的最佳方式是:默认采用动态分配,同时保留在加载甚至是编译时指定主设备号的余地。<BR><BR><FONT
size=2><SPAN
style="COLOR: rgb(0,1,2)">以下是在scull.c中用来获取主设备好的代码:<BR><BR></SPAN></FONT></SPAN></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)"><SPAN
style="COLOR: rgb(0,0,255)">if</SPAN> <SPAN
style="COLOR: rgb(0,0,204)">(</SPAN>scull_major<SPAN
style="COLOR: rgb(0,0,204)">)</SPAN> <SPAN
style="COLOR: rgb(0,0,204)">{</SPAN><BR>
dev <SPAN style="COLOR: rgb(0,0,204)">=</SPAN>
MKDEV<SPAN
style="COLOR: rgb(0,0,204)">(</SPAN>scull_major<SPAN
style="COLOR: rgb(0,0,204)">,</SPAN>
scull_minor<SPAN
style="COLOR: rgb(0,0,204)">)</SPAN><SPAN
style="COLOR: rgb(0,0,204)">;</SPAN><BR>
result <SPAN
style="COLOR: rgb(0,0,204)">=</SPAN>
register_chrdev_region<SPAN
style="COLOR: rgb(0,0,204)">(</SPAN>dev<SPAN
style="COLOR: rgb(0,0,204)">,</SPAN>
scull_nr_devs<SPAN
style="COLOR: rgb(0,0,204)">,</SPAN> <SPAN
style="COLOR: rgb(255,0,255)">"scull"</SPAN><SPAN
style="COLOR: rgb(0,0,204)">)</SPAN><SPAN
style="COLOR: rgb(0,0,204)">;</SPAN><BR><SPAN
style="COLOR: rgb(0,0,204)">}</SPAN> <SPAN
style="COLOR: rgb(0,0,255)">else</SPAN> <SPAN
style="COLOR: rgb(0,0,204)">{</SPAN><BR>
result <SPAN
style="COLOR: rgb(0,0,204)">=</SPAN>
alloc_chrdev_region<SPAN
style="COLOR: rgb(0,0,204)">(</SPAN><SPAN
style="COLOR: rgb(0,0,204)">&</SPAN>dev<SPAN
style="COLOR: rgb(0,0,204)">,</SPAN>
scull_minor<SPAN
style="COLOR: rgb(0,0,204)">,</SPAN>
scull_nr_devs<SPAN
style="COLOR: rgb(0,0,204)">,</SPAN><SPAN
style="COLOR: rgb(0,0,255)"></SPAN><SPAN
style="COLOR: rgb(255,1,255)">"scull"</SPAN><SPAN
style="COLOR: rgb(0,1,255)">);</SPAN><BR>
scull_major = MAJOR<SPAN
style="COLOR: rgb(0,1,255)">(</SPAN>dev<SPAN
style="COLOR: rgb(0,1,255)">);</SPAN><BR><SPAN
style="COLOR: rgb(0,1,255)">}</SPAN><BR><SPAN
style="COLOR: rgb(0,1,255)">if (</SPAN>result
< 0<SPAN style="COLOR: rgb(0,1,255)">)
{</SPAN><BR> printk<SPAN
style="COLOR: rgb(0,1,255)">(</SPAN>KERN_WARNING
<SPAN style="COLOR: rgb(255,1,255)">"scull:
can't get major %d\n"</SPAN>, scull_major<SPAN
style="COLOR: rgb(0,1,255)">);</SPAN><BR>
return result<SPAN
style="COLOR: rgb(0,1,255)">;</SPAN><BR
style="COLOR: rgb(0,1,255)"><SPAN
style="COLOR: rgb(0,1,255)">}</SPAN><BR><SPAN
style="COLOR: rgb(0,0,204)"><BR></SPAN></SPAN></CODE></P></TD></TR></TBODY></TABLE><FONT
size=3></FONT>
<P><FONT size=3><BR
style="COLOR: rgb(255,1,2)"><SPAN
style="COLOR: rgb(255,1,2)">在这部分中,比较重要的是在用函数获取设备编号后,其中的参数name是和该编号范围关联的设备名称,它将出现在/proc/devices和sysfs中。<BR><BR
style="COLOR: rgb(255,1,2)"><SPAN
style="COLOR: rgb(255,1,2)">看到这里,就可以理解为什么mdev和udev可以动态、自动地生成当前系统需要的设备文件。</SPAN></SPAN><SPAN
class=search_hit
style="COLOR: rgb(255,1,2)">udev</SPAN><SPAN
style="COLOR: rgb(255,1,2)">就是通过读取</SPAN></FONT><FONT
style="COLOR: rgb(255,1,2)"
size=3>sysfs</FONT><FONT size=3><SPAN
style="COLOR: rgb(255,1,2)">下的信息来识别硬件设备的.<BR><SPAN
style="COLOR: rgb(0,1,255)">(请看《</SPAN></SPAN></FONT><FONT
style="FONT-SIZE: 14pt; COLOR: rgb(0,1,255)"
color=#02368d size=3>理解和认识udev</FONT><FONT
style="COLOR: rgb(255,1,2)" size=3><SPAN
style="COLOR: rgb(0,1,255)">》</SPAN><BR
style="COLOR: rgb(0,1,255)"><SPAN
style="COLOR: rgb(0,1,255)">URL:http://blog.chinaunix.net/u/6541/showart_396425.html)</SPAN><BR></FONT></P>
<P></P>
<HR style="WIDTH: 100%; HEIGHT: 2px">
<P></P>
<P><FONT style="COLOR: rgb(0,1,255)"
size=4>二、一些重要的数据结构</FONT><FONT
style="COLOR: rgb(255,1,2)" size=3><BR><SPAN
style="COLOR: rgb(0,1,2)">大部分基本的驱动程序操作涉及及到三个重要的内核数据结构,分别是file_operations、file和inode,它们的定义都在</SPAN></FONT><FONT
size=3><SPAN
style="FONT-WEIGHT: normal; COLOR: rgb(0,1,2)"><SPAN
style="COLOR: rgb(0,1,255)"><linux/fs.h><SPAN
style="COLOR: rgb(0,1,2)">。<BR></SPAN></SPAN></SPAN></FONT><FONT
style="COLOR: rgb(0,1,255)" size=4><BR></FONT></P>
<P></P>
<HR style="WIDTH: 100%; HEIGHT: 2px">
<P></P>
<P><FONT style="COLOR: rgb(0,1,255)"
size=4>三、字符设备的注册</FONT><BR><FONT size=3><SPAN
style="FONT-WEIGHT: normal; COLOR: rgb(0,1,2)"><SPAN
style="COLOR: rgb(0,1,255)"><SPAN
style="COLOR: rgb(0,1,2)"><BR></SPAN></SPAN></SPAN></FONT><FONT
style="COLOR: rgb(255,1,2)" size=3><SPAN
style="COLOR: rgb(0,1,2)">内核内部使用<SPAN
style="COLOR: rgb(0,1,255)">struct
cdev</SPAN>结构来表示字符设备。在内核调用设备的操作之前,必须分配并注册一个或多个</SPAN></FONT><FONT
style="COLOR: rgb(255,1,2)" size=3><SPAN
style="COLOR: rgb(0,1,2)"><SPAN
style="COLOR: rgb(0,1,255)">struct
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -