% X" U! S, K" f: r+ f1 G2 z1 A 在字符设备驱动模块加载函数中应该实现设备号的申请和cdev 结构的注册,而在卸载函数中应该实现设备号的释放与cdev结构的注销。 ) e. _7 A* F( Q! p" R% }2 e5 ~: S- K- O- w
我们一般习惯将cdev内嵌到另外一个设备相关的结构体里面,该设备包含所涉及的cdev、私有数据及信号量等等信息。常见的设备结构体、模块加载函数、模块卸载函数形式如下: & g" N/ G: H# u" }' \) P 1 G; s2 t! H2 K b* m/*设备结构体*/ % q1 U# E9 d* j) P2 X + S* v! Q, v% ~. F: \" mstruct xxx_dev{2 Q4 c+ ^0 Q& `
, u! T! t* O9 P5 r" M$ P2 P/ b4 U! q struct cdev cdev; % @5 p( n6 Q; f+ g8 s ' w( j% }; B. o5 E- M5 o- p8 H char *data; ! N+ i) @( {- x: J5 l; A 9 M2 k( |/ D9 k" U& U struct semaphore sem;6 C+ N- v% e, h. `
- f- k1 ~! [- y {
...... K/ k+ U8 v/ H2 G ' z$ D9 ^ e$ [; ]/ U- D% M8 s& C};. n( O5 {# z, _9 Y: ?
, Y$ h$ m( I+ i$ C
* e+ q2 A# m/ F! x* x, @
+ }: g6 f! s8 A( o% [/ }
/*模块加载函数*/ / T, j. c1 p7 c* g ! L) Y% Q' M5 o5 w. U! h0 z Y% w2 Sstatic int __init xxx_init(void) 0 z! |% L. g3 J5 {) Q9 n+ C$ P9 f3 G* K8 Z6 m7 o
{6 v6 r% O! _3 _
- t% Q7 a {' u5 L ....... $ O, J4 f j& d5 u+ X) | m/ h+ E4 x5 J l& ?7 L# B 初始化cdev结构; 3 m% V \6 J8 U5 J' a% d% I* |% P 2 m E( W t3 g I 申请设备号; k1 D; H0 D# W% M0 b! ?* a, `2 z1 Z0 z) s
注册设备号; 5 I7 s' R+ t9 g. s. f; o2 | ' o' C6 a1 }9 s% t. w, C4 L3 i0 H; f" d/ R' D6 c- t: Q
5 Y' {7 Q( J+ A6 g2 {+ I* W2 W 申请分配设备结构体的内存; /*非必须*/ : @7 r7 ]- l* y x" I: p% x + D3 h- y0 C7 T6 }} ( p! Q P+ g" i# n3 w! I% r# D" U+ M, S$ l
) A. J$ x9 d$ P+ C; }! Q 1 F# I7 V. b) y/*模块卸载函数*/ / G& D$ O1 ~$ V6 J) K: w 0 q" d9 @# h4 {7 ]& T3 {' A* J8 vstatic void __exit xxx_exit(void) 3 m3 O8 @9 H# U' {, v- \! S' C3 q1 z+ o' j1 ]& t
{1 O$ M4 R% r/ ?$ u