找回密码
 加入怎通
查看: 452|回复: 0

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

[复制链接]
杨莹莹连 发表于 2013-11-11 16:00:05 | 显示全部楼层 |阅读模式
          6 t( ?, X" J7 ?: g% ~& f( w

9 Z1 Y3 v6 E3 a6 {5 A  第6章  简单的字符设备驱动程序
# x7 I5 x2 H, P2 h4 o9 I; L: b0 ?! Z% P5 l, v, R: @( e
  在Linux设备驱动程序的家族中,字符设备驱动程序是较为简单的驱动程序,同时也是应用非常广泛的驱动程序。所以学习字符设备驱动程序,对构建Linux设备驱动程序的知识结构非常重要。本章将带领读者编写一个完整的字符设备驱动程序。
& N- q. h& G5 a" D- q$ A; p
2 w) X4 l% a1 K, m! W& Y  61  字符设备驱动程序框架' ]9 P0 z  w0 Y

+ x  B% v  k& Y( W/ r6 u  本节对字符设备驱动程序框架进行了简要的分析。字符设备驱动程序中有许多非常重要的概念,下面将从最简单的概念讲起:字符设备和块设备。
! b! }6 h, C7 T) ~5 f  \8 U% \  f
- x; k2 O& D. X- H  611  字符设备和块设备
' S" k3 L* {. F, ~6 [: K
8 V& e& ?4 r4 H  S: T4 s  Linux系统将设备分为3种类型:字符设备、块设备和网络接口设备。
1 S# ^& _3 U# C, q  H. }+ C- F0 [* @, W9 ]! ]8 Z
  其中字符设备和块设备难以区分,下面将对其进行重要讲解。6 o# z& Q2 V9 A7 Z/ x" D3 `8 d
; J0 t$ T% Q/ U: }& e  `
  1.字符设备; q, I, F5 Q  W) |8 V% I7 H
1 M  g+ d- U, C: X( U& K
  字符设备是指那些只能一个字节一个字节读写数据的设备,不能随机读取设备内存中的某一数据。其读取数据需要按照先后顺序,从这点来看,字符设备是面向数据流的设备。% T% V5 @1 O  K! M/ |3 Q

. h( ]9 l3 u: N4 I2 a  常见的字符有鼠标、键盘、串口、控制台和LED等设备。2 j/ K! w3 i1 Y9 i$ z; E

9 n2 J: ^- q% q  2.块设备
: i; C% ?* L; V: U6 v" e/ d, q# K# {+ |
  块设备是指那些可以从设备的任意位置读取一定长度数据的设备。其读取数据不必按照先后顺序,可以定位到设备的某一具体位置,读取数据。  j# c3 w5 H$ M7 s/ e
0 O- \/ ~, o8 _3 I# H3 o# R3 t
  常见的块设备有硬盘、磁盘、U盘、SD卡等。( ^" V8 M- k7 c4 l5 t6 K% g
8 |: z* f0 H' T. `) A% \( B
  3.字符设备和块设备的区分
# G: U4 H  Z3 {
) g, n9 i  N1 \$ Y5 E6 r. K% s  每一个字符设备或者块设备都在/dev目录下对应一个设备文件。读者可以通过查看/dev目录下的文件的属性,来区分设备是字符设备还是块设备。5 o0 C: C# E2 H; p* o6 q

8 n& o+ [" d7 [: u6 h# k  使用cd命令进入/dev目录,并执行ls -l命令就可以看到设备的属性。
5 _# @2 d- O6 r0 X2 C& U
1 e4 n6 b/ x( I  [root@tom /]# cd /dev                                                        /*进入/dev目录*/
1 [; J' \2 P7 U8 w  b, n) Z5 ~# n! \% y7 X; w% \8 O3 m
  [root@tom dev]# ls -l                                                         /*列出/dev中文件的信息*/、3 |2 T9 s, t0 b: ~! w

8 l+ l/ G1 @1 y5 F& E0 R  /*第1字段     2  3  4      5    6         7      8  */
$ R  T6 }/ l7 w- S1 `) v: l# C9 q  q! |2 Q8 J* P3 L5 b
  crw-rw----+         1 root root    14,  12         12-21 22:56 adsp
& Q- }7 e4 Y- M- L4 m3 ?2 ?6 ^# x
4 j  m2 |: {3 T' y2 g8 p" a8 S  crw-------          1 root root    10, 175         12-21 22:56 agpgart
7 D% W- m- t3 y1 l0 N% W1 B0 j+ U# a5 M# f2 E
  crw-rw----+         1 root root    14,   4         12-21 22:56 audio7 Y) t8 r  c. T: T8 R' R. E5 x
: _/ O8 \* N, b  s, T1 F
  brw-r-----          1 root disk   253,   0         12-21 22:56 dm-0/ M9 P  V: C/ O6 ?6 J9 R
5 ^: P6 i- _/ C- L+ K8 u
  brw-r-----          1 root disk   253,   1         12-21 22:56 dm-1' Q8 ~5 e3 S. y6 y

0 D4 |+ H0 L, `( V! |2 F4 y8 q  crw-rw----          1 root root    14,   9         12-21 22:56 dmmidi
* E( ~: p3 S1 E6 q; c* q/ J6 U% u/ A' R" q  B
  ls -l命令的第一字段中的第一个字符c表示设备是字符设备,b表示设备是块设备。第234字段对驱动程序开发来说没有关系。" G8 a! _# {; T4 g/ f. d6 E

! L0 F! i9 U7 Y' q1 C# q  第5,6字段分别表示设备的主设备号和次设备号,将在612节讲解。第7字段表示文件的最后修改时间。第8字段表示设备的名字。0 o) {4 o; r8 P7 w0 r2 z8 E
- F/ I  z" _% u3 |) X
  由第1和8字段可知,adsp是字符设备,dm-0是块设备。其中adsp设备的主设备号是14,次设备号是12。9 L( X- I  X8 P- b; S
5 n$ B' d& }* d
  612  主设备号和次设备号
2 K/ q5 Z3 _$ _& i. x9 u; o- m0 |  n; r  j
  一个字符设备或者块设备都有一个主设备号和次设备号。
6 J& D% ?) N0 i$ L9 M) k. \8 U
  主设备号和次设备号统称为设备号。主设备号用来表示一个特定的驱动程序。次设备号用来表示使用该驱动程序的各设备。
, R1 D: y# Q; k, ~# L2 n) \$ N2 p0 T1 U4 ]
  例如一个嵌入式系统,有两个LED指示灯,LED灯需要独立的打开或者关闭。那么,可以写一个LED灯的字符设备驱动程序,可以将其主设备号注册成5号设备,次设备号分别为1和2。这里,次设备号就分别表示两个LED灯。
% U1 I' d2 a- [* H
7 v- o/ A4 p2 ^3 k9 H. D' S  1.主设备号和次设备号的表示
' o' y5 `5 x: J4 o9 H8 H/ P1 N$ o# q/ |& h- K
  在Linux内核中,dev_t类型用来表示设备号。在Linux 26294中,dev_t定义为一个无符号长整型变量,如下:  E) Y$ H# Z. ]. E. C  C
# k5 B0 K8 q3 Z
  typedef u_long dev_t;
2 \, M4 T9 \% i* m
) s4 m, v& ~5 T/ }7 R# M  u_long在32位机中是4个字节,在64位机中是8字节。以32位机为例,其中高12表示主设备号,低20为表示次设备号,如图61所示。) f) N2 O4 `5 `6 J& A) U! {
" _9 \: d+ V7 y/ @6 `
  图61  dev_t结构
, [, M' B! O8 k; S  A" j+ Z. x  A( c7 }2 Q9 j2 U
  2.主设备号和次设备号的获取
- q# l- l( }; P' _4 ~% k8 K% r0 v7 M- l. U2 I' @+ W
  为了写出可移植的驱动程序,不能假定主设备号和次设备号的位数。不同的机型中,主设备号和次设备号的位数可能是不同的。应该使用MAJOR宏得到主设备号,使用MINOR宏来得到次设备号。6 i! N8 ]/ J6 R1 {' R
; g- G, h* x- r* B* p( P0 X
  大发888下面是两个宏的定义:/ K1 q, V1 }4 p1 q
; |1 y0 s0 L# P$ n  J- c/ f
  #define MINORBITS        20                                                                         /*次设备号位数*/% u/ _) p, t+ G2 M4 ?

# I4 K  _, k6 M' n- J  #define MINORMASK        ((1U > MINORBITS))& E8 S' h' ^% j, E: ~

' z  d1 W; ?+ E% w$ {                                                                                           /*dev右移20位得到主设备号*/5 w7 H/ @# E5 E. v9 y

, k. K  r/ ~: A, V2 f( G  #define MINOR(dev)        ((unsigned int) ((dev)  MINORMASK))
6 x; v! a& m6 Y, ^: T2 I4 w* r; n7 i
                                                                                          /*与次设备掩码与,得到次设备号*/
1 s8 M6 U8 k# ?* q! q& b) w+ b, Y/ V' p/ l1 [
  MAJOR宏将dev_t向右移动20位,得到主设备号;MINOR宏将dev_t的高12位清零,得到次设备号。相反,可以将主设备号和次设备号转换为设备号类型(dev_t),使用宏MKDEV可以完成这个功能。
% S6 O3 \# ^# i  @
0 W% ^& _/ d8 I" c+ c( e+ m& y  #define MKDEV(ma,mi)        (((ma)
4 X% c" s! e8 [; a/ X* m, ]' s. Z& j4 V9 R
  MKDEV宏将主设备号(ma)左移20位,然后与次设备号(mi)相与,得到设备号。2 {+ m' j/ p, x4 k( I

; Z. O5 z5 Z9 Z$ O5 R" q  3.静态分配设备号" O' T8 R* @& I* H9 s( O# X
6 ]3 x4 _* `3 `4 H( s
  静态分配设备号,就是驱动程序开发者,静态地指定一个设备号。对于一部分常用的设备,内核开发者已经为其分配了设备号。这些设备号可以在内核源码documentation/ devicestxt文件中找到。- }" W/ Z! e$ G- G( q; _( e( F
" o7 [  a3 N8 s$ C
  如果只有开发者自己使用这些设备驱动程序,那么其可以选择一个尚未使用的设备号。在不添加新硬件的时候,这种方式不会产生设备号冲突。但是当添加新硬件时,则很可能造成设备号冲突,影响设备的使用。
* E% A$ e/ N# t. s6 }0 |6 a
0 L8 s* r8 g7 v  4.动态分配设备号& W8 h( D8 W9 z# r

) r+ w$ F, p8 E. t" I/ q3 @  由于静态分配设备号存在冲突的问题
; G/ N! Y+ U2 e8 i( ?
9 p1 J( X/ E6 \5 B( O+ w9 {
回复

使用道具 举报

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

    本版积分规则

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

    GMT+8, 2026-3-13 17:32 , Processed in 0.127527 second(s), 24 queries , Gzip On.

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

    Powered by Discuz! X3.5

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