找回密码
 加入怎通
查看: 507|回复: 3

[其他] Linux驱动开发入门与实战.txt

[复制链接]
杨莹莹连 发表于 2013-11-11 16:00:05 | 显示全部楼层 |阅读模式
            j" R  g  W* t7 b7 ~
. |) O/ E4 _2 ?5 O. s. r* ?4 I
  第6章  简单的字符设备驱动程序
% m$ c/ r& o( C2 l, n( X; v  y1 A
3 z/ [4 }$ Q+ f  C$ h0 X& h5 p  z  在Linux设备驱动程序的家族中,字符设备驱动程序是较为简单的驱动程序,同时也是应用非常广泛的驱动程序。所以学习字符设备驱动程序,对构建Linux设备驱动程序的知识结构非常重要。本章将带领读者编写一个完整的字符设备驱动程序。1 p/ D8 _: e$ q% U! C

2 G# u! c1 o7 I$ e" E  K, h  61  字符设备驱动程序框架0 H- M0 S$ f  W; e  w
+ ^5 }% _' N  [$ z0 x1 Y- P
  本节对字符设备驱动程序框架进行了简要的分析。字符设备驱动程序中有许多非常重要的概念,下面将从最简单的概念讲起:字符设备和块设备。
1 m* j8 J4 h1 b- h6 V- f* A) H/ b2 P( E8 `, J9 H3 v
  611  字符设备和块设备
! H+ x8 e3 O: ]/ z3 O2 R# l+ z0 |+ z' \, A
  Linux系统将设备分为3种类型:字符设备、块设备和网络接口设备。' O1 h; @1 I  g' s# g/ l8 y! N% a

4 ]' P$ d2 n/ j% N. }- q  其中字符设备和块设备难以区分,下面将对其进行重要讲解。
% S/ s' I5 L  }5 u9 c7 o/ d# N& z
6 O+ u  y1 B+ _& v  p8 O. y  1.字符设备
" f! M3 D; R7 A
( y9 V* [' I0 Y0 Z7 a" h' x+ B  字符设备是指那些只能一个字节一个字节读写数据的设备,不能随机读取设备内存中的某一数据。其读取数据需要按照先后顺序,从这点来看,字符设备是面向数据流的设备。
& m* i  x* U5 e! `# u/ |4 L# Q: e9 A4 b5 |, j& B
  常见的字符有鼠标、键盘、串口、控制台和LED等设备。* [: e, T; S( A' G' ^* s
8 |8 I; C1 X$ N/ W+ S* ~
  2.块设备
! `& D, b: T5 E9 F9 T% o, W7 D+ X) N+ E- b2 t4 {. u0 N" X- h8 H& X
  块设备是指那些可以从设备的任意位置读取一定长度数据的设备。其读取数据不必按照先后顺序,可以定位到设备的某一具体位置,读取数据。+ z: I! d9 B( R

+ a' F* Y" z( r  常见的块设备有硬盘、磁盘、U盘、SD卡等。
! ?5 D' w2 h+ R  y0 d! s
+ s& |9 l5 q) r* k4 f& \  3.字符设备和块设备的区分
5 \: k+ B7 L* g6 U9 B/ r, [1 i2 [3 j' y- `
  每一个字符设备或者块设备都在/dev目录下对应一个设备文件。读者可以通过查看/dev目录下的文件的属性,来区分设备是字符设备还是块设备。
) ^$ y8 o! E( }* i* ]. l4 D$ D& r1 Z9 i' d$ q4 P/ L
  使用cd命令进入/dev目录,并执行ls -l命令就可以看到设备的属性。" G" c# C  o6 }! X7 g! w

2 J/ Y5 Q3 x4 _( [. O  [root@tom /]# cd /dev                                                        /*进入/dev目录*/: q" J; F) E5 A' o4 D6 z) {* ~
7 `) d! _2 {; ]! z
  [root@tom dev]# ls -l                                                         /*列出/dev中文件的信息*/、
  ]- L* E0 R2 Y6 |' P1 K
: Z0 B& A, _& d! f6 y  x  /*第1字段     2  3  4      5    6         7      8  */
) i5 `. q; v# C' L1 E: W2 L6 @: D- C! R3 `
  crw-rw----+         1 root root    14,  12         12-21 22:56 adsp( _# q. d8 l$ A

6 U7 m! v: O1 O9 Y  crw-------          1 root root    10, 175         12-21 22:56 agpgart
/ t( \, @6 x& u* W7 T
1 u6 r* {. N. G, u: w4 v  crw-rw----+         1 root root    14,   4         12-21 22:56 audio
7 m8 ~! ?) B% L5 x0 _' V  f5 q# ^" z6 _) d8 V$ m! Y
  brw-r-----          1 root disk   253,   0         12-21 22:56 dm-0
5 K  a& @! ^/ c" c. z, q' F
  P) T7 L; |5 r/ j! ?  y  brw-r-----          1 root disk   253,   1         12-21 22:56 dm-1
" Q* y7 M& f* r- B# m
& `+ u' B' h! _0 ^7 t/ z; m9 _  crw-rw----          1 root root    14,   9         12-21 22:56 dmmidi, \! H5 k4 N* a! A& P. D3 O+ F
' Q4 _8 u, ]0 n. W8 l
  ls -l命令的第一字段中的第一个字符c表示设备是字符设备,b表示设备是块设备。第234字段对驱动程序开发来说没有关系。& n; L/ S( c  N# b# w

0 \6 f# X4 z3 |5 `' ^) ?  第5,6字段分别表示设备的主设备号和次设备号,将在612节讲解。第7字段表示文件的最后修改时间。第8字段表示设备的名字。
6 b6 L  P5 a; a. q+ g9 i3 O/ X$ u0 E4 t$ R) p% e7 `
  由第1和8字段可知,adsp是字符设备,dm-0是块设备。其中adsp设备的主设备号是14,次设备号是12。
2 {( j$ D% }0 W5 Z. h
7 X  D2 {( I& V9 X  612  主设备号和次设备号8 r1 u# R2 |& L& f

  g( r/ K& |" |, C% E  一个字符设备或者块设备都有一个主设备号和次设备号。0 }6 ?$ h  m! s$ U/ N
5 x5 U( n5 n, X/ V# O0 L1 e, ?
  主设备号和次设备号统称为设备号。主设备号用来表示一个特定的驱动程序。次设备号用来表示使用该驱动程序的各设备。$ [" M  j" p: A- n
6 E/ w- K$ T% g; D: `1 I, ^$ y
  例如一个嵌入式系统,有两个LED指示灯,LED灯需要独立的打开或者关闭。那么,可以写一个LED灯的字符设备驱动程序,可以将其主设备号注册成5号设备,次设备号分别为1和2。这里,次设备号就分别表示两个LED灯。/ Y. n) H8 G5 i# n
/ L/ l- f$ x7 E; X- C
  1.主设备号和次设备号的表示
& {+ _7 F# K" Y. {9 d9 t1 O
, B) m( f0 I: k# j: A/ R1 x  q6 R  在Linux内核中,dev_t类型用来表示设备号。在Linux 26294中,dev_t定义为一个无符号长整型变量,如下:
5 |# i/ x! |, L' d" ?" N
) A+ l9 w1 P3 L2 f/ x  w# K  typedef u_long dev_t;: U+ b  ^2 C0 K8 L; U8 k' G0 W

, O0 {- t/ J% N; h  |  u_long在32位机中是4个字节,在64位机中是8字节。以32位机为例,其中高12表示主设备号,低20为表示次设备号,如图61所示。
$ m! @$ m) a* J1 u: j/ b2 n' d
8 f+ \+ O9 w) H8 M/ i' D4 _  图61  dev_t结构
' l# e0 D4 `* z  Q
( y! }2 T9 j0 T0 l/ k7 I2 y2 G  2.主设备号和次设备号的获取3 _' d0 \) S0 x' [$ S
+ ?4 x+ K: A% ^7 |0 D* d7 `% {
  为了写出可移植的驱动程序,不能假定主设备号和次设备号的位数。不同的机型中,主设备号和次设备号的位数可能是不同的。应该使用MAJOR宏得到主设备号,使用MINOR宏来得到次设备号。
% b  W' ]! L. h# L: a' ^7 Z/ N0 [1 c. U% z0 x+ ?  Z
  大发888下面是两个宏的定义:8 P, e, c% H' {; i$ S; W7 X  m

8 @. F( o, [" B( e! [, G  #define MINORBITS        20                                                                         /*次设备号位数*/6 G6 P8 l7 ^% z2 g0 E" Y

- t2 d5 H3 m$ ]4 S  #define MINORMASK        ((1U > MINORBITS))! n, t/ {+ Y% k  |6 m, R
: P- F8 Z" _  _- b7 F$ L2 w
                                                                                           /*dev右移20位得到主设备号*/" O. }& A& N& J# {& u' H8 X9 `
/ T* R( ~( e6 z2 P! ]/ S2 [( V
  #define MINOR(dev)        ((unsigned int) ((dev)  MINORMASK)); `6 `- x7 O( V3 Z1 z
1 w" a3 B& a: i: ^# A
                                                                                          /*与次设备掩码与,得到次设备号*/5 |5 E" P' B! u6 q5 C0 }7 f
4 t( n$ @6 r7 o; I% @, Z
  MAJOR宏将dev_t向右移动20位,得到主设备号;MINOR宏将dev_t的高12位清零,得到次设备号。相反,可以将主设备号和次设备号转换为设备号类型(dev_t),使用宏MKDEV可以完成这个功能。; C, p0 e/ |- B+ H) v
$ _) n  \6 `; l- |, e: g5 D" n0 ~
  #define MKDEV(ma,mi)        (((ma)
0 @5 y8 Y1 l6 U( Z4 ]
+ K+ e' L% W  J* p$ o  MKDEV宏将主设备号(ma)左移20位,然后与次设备号(mi)相与,得到设备号。( c9 z/ f2 |( l/ W" j

. S2 Z2 j% F6 O* d+ l. f  3.静态分配设备号
# P, q  s3 u. a/ r7 y9 V; e1 f  n
* @$ j. Q3 ^/ ]9 |* c  静态分配设备号,就是驱动程序开发者,静态地指定一个设备号。对于一部分常用的设备,内核开发者已经为其分配了设备号。这些设备号可以在内核源码documentation/ devicestxt文件中找到。
$ ?' q5 o1 O' {8 X- z
! F) A) q% D6 y" @2 O7 k, F* I7 P5 Z: N  如果只有开发者自己使用这些设备驱动程序,那么其可以选择一个尚未使用的设备号。在不添加新硬件的时候,这种方式不会产生设备号冲突。但是当添加新硬件时,则很可能造成设备号冲突,影响设备的使用。
" i- r6 g, x+ U) o5 n- N) s
  U& Q2 j- z) o. Y. j- J  4.动态分配设备号
+ L6 _2 g9 z' S) O% ?1 B# K8 e% O3 R9 w
  由于静态分配设备号存在冲突的问题
# Z0 \9 e$ b* W
) I$ _% J; o! M# p# r; E

暂时无法加载帖子列表

回复

使用道具 举报

yue_菇凉 发表于 2026-05-29 22:16:42 | 显示全部楼层
楼主辛苦了,整理这么多内容,必须点赞收藏
回复

使用道具 举报

csyp2017 发表于 2026-06-30 03:33:38 | 显示全部楼层
刚好遇到类似问题,看完这个帖子心里有底了
回复

使用道具 举报

dpjanebass 发表于 2026-08-25 00:51:50 | 显示全部楼层
这个分享太实用了,刚好能用到,感谢楼主!
回复

使用道具 举报

    您需要登录后才可以回帖 登录 | 加入怎通

    本版积分规则

    QQ|手机版|小黑屋|网站地图|真牛社区 ( 苏ICP备2023040716号-2 )

    GMT+8, 2026-10-26 20:34 , Processed in 0.052306 second(s), 26 queries , Gzip On.

    免责声明:本站信息来自互联网,本站不对其内容真实性负责,如有侵权等情况请联系420897364#qq.com(把#换成@)删除。

    Powered by Discuz! X3.5

    快速回复 返回顶部 返回列表