flag = 0;/ I z% `* c) K3 m! k$ D
9 }4 i$ t% S' D8 A `
wp = rp = buf;
/ j! D& n" A8 z8 K3 w7 s8 F" N
" s" p: t# T7 J3 l% \- V result = register_chrdev( 54,"buf",&buf_fops );
6 G3 o' u* M U/ Q1 p 6 I/ s$ N# B3 q) `- W4 `
if ( result < 0 ) {2 V4 {: |' _2 {6 Z B8 U! b
I+ Y* K: J2 m0 e printk( "buf: cannot get major 54 " );
, i+ i/ @: b/ d8 f* x3 h
2 h ?6 ~$ x' Q8 i+ _5 T# a. E return result;1 K% H9 T6 t6 I$ w
/ p, h# i0 W( T1 g6 \2 \: q: [
}* ]5 G) [7 h+ o% r: p
( ]" i X. E- o8 I, ` return 0;5 f1 U) ^" c8 X: w7 B/ Q6 l) A: W
V$ y Q, j' [1 B/ ?' V" O. F init_buf() 做的事就是去注册一个 character device driver.在注册一个 character device driver 之前,必须要先准备一个型别为 file_operations 结构的变量,file_operations 里包含了一些 function pointer.driver 的作者必须自己写这些 function.并将 function address 放到这个结构里。如此一来,当 user 去读取这个 device 时,kernel 才有办法去呼叫对应这个 driver 的 function.其实,简要来讲。character device driver 就是这么一个 file_operations 结构的变量。file_operations 定义在 这个档案里。它的 prototype 在 kernel 2.2.1 与以前的版本有些微的差异,这点是需要注意的地方。
% E2 u1 G/ p E
7 \* R, w( l/ E2 w/ j: | register_chrdev() 看名字就大概知道是要注册 character device driver.第一个参数是此 device 的 major number.第二个是它的名字。名字你可以随便取。第三个的参数就是一个 file_operations 变量的地址。init_module() 必须要传回 0,module 才会被加载。) A: u# k" u- A, a8 o0 U; ` L" P
5 u) P7 R$ l' Y2 r# c+ p 在 cleanup_module() 的部分,我们也是只呼叫 buf_clean() 而已。它做的事是 unregister 的动作。, z& y) |; V+ K7 V, n6 `' e
$ _! Y* f+ i o2 ~! [) w1 S if ( unregister_chrdev( 54,"buf" ) ) {
5 I) b4 q" h) `0 X # H3 H) n+ Z0 L/ S' n
printk( "buf: unregister_chrdev error " );
0 e/ M- E( n2 ]5 Z# f0 h( z; |
/ X, n, v' K8 z6 l9 n }
- U, H2 h- `; D& Y0 t6 V4 }
" R$ ?% f. b+ p" M: `3 V+ | 也就是将原本记录在 device driver table 上的资料洗掉。第一个参数是 major number.第二个则是此 driver 的名称,这个名字必须要跟 register_chrdev() 中所给的名字一样才行。* \: q' V$ E8 Z$ q
" a9 X) I* [; K# g! p" z7 P( @. `. [
现在我们来看看此 driver 所提供的 file_operations 是那些。
1 z& Q$ E' S- n" R! z : Q4 Q$ G+ S0 s6 I' T1 S+ P
static struct file_operations buf_fops = {+ g. [& P5 Q- a0 b, C. n
+ t# B- [! g) n. r* n
NULL, /* lseek */
8 y I' G, d9 k* R) z. N) G, r
3 I3 w; ^0 v9 r8 {5 \ buf_read,
' U3 `9 F9 a" z$ y$ D
% O1 _( A1 B( k4 f# `2 a buf_write,
/ H' [0 d7 }* Y- L8 ?0 s, Y) Y) ~/ F , j8 E5 I$ W4 V! ?
NULL, /* readdir */
1 y* U- P$ W+ Q ! ~7 P! N' V0 C$ }+ P
NULL, /* poll */0 w$ T! J' Q2 I p& U% \# d4 i
8 f. @! X- G3 {" X0 O NULL, /* ioctl */$ z9 D4 |: Z6 T' ~* G \- p3 o
# M! X3 V9 e# x' \5 e H NULL, /* mmap */% D& `6 K* T+ y" I( H& s
1 o7 N) K$ ~' W! G/ C$ P9 C( q
buf_open, /* open */
9 f* |4 k! P+ e& }
( v+ m% X# N; [, s0 B; p1 ~ NULL, /* flush */
1 F! @6 B' z9 p1 L
. q- K; i! o2 `/ Z" `( _( P buf_release, /* release */" P3 A7 S, \' @& N- A
; }! B: r4 F& M* H( R& o* ~/ I6 a NULL, /* fsync */
4 n: q3 ], p% h2 T. q - [! l3 p+ w; U5 u
NULL, /* fasync */. Y9 o( U# i d
6 M; z7 B. |2 \: N) y. J2 e
NULL, /* check_media_change */
# d$ N$ T* i/ Q# x & ~0 s$ [- x: |+ Y! q# y' ?
NULL, /* revalidate */
: @ [9 C9 u+ {# `1 N3 O5 g0 ~ A
8 n/ [; _0 F( l/ r NULL /* lock */
! g1 {4 {. l+ \8 P/ z: G
@* a4 e; k' q8 G z+ L$ g# Z }; |