|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
问:能不能让系统自动创建设备节点?
3 q; z3 W+ j& ]5 U! v& U( W; J3 i+ x5 \2 r
答:可以,linux有udev、mdev的机制,而我们的ARM开发板上移植的busybox有mdev机制,那么就使用mdev机制来自动创建设备节点。' o/ C5 w* q/ Z, N
2 r: \- b) w' q, H2 y9 P% I
问:文件系统里,在哪里设置了mdev机制?
7 L# C0 |9 R- o( W2 m# x% Y! s
7 o/ f# y) [ ^/ Z4 m' N答:在etc/init.d/rcS文件里有一句:) }' ^. V; n6 }+ i$ t/ b, X
8 T+ p8 T) U$ y1 U0 _5 B8 O3 L
echo /sbin/mdev > /proc/sys/kernel/hotplug
0 R+ h; t; w& z i5 }) `3 q5 D1 P
1 {0 m7 @$ W+ z2 i2 G' Y' J- a6 J& {问:在驱动程序里面如何编写程序,让系统自动创建设备节点?3 _7 `( r; x* n& n) @0 O: u; R
2 V! D5 h# }$ P( r; b6 [; `/ p( R/ @3 f
答:首先创建一个class类,然后在class类下,创建一个class_device,即类下面创建类的设备。* |4 w# h+ |0 L
& d6 h+ \% e( \0 _" {6 J k! V. X. r. D& Q
) e; c1 h' d6 Q# j% h; m详细请参考驱动源码:
: Q( Q+ t9 F5 _( k! V$ q8 Z, C# d4 y7 X
- K, T% c4 P7 P" O' A8 ~" Y) q
#include <linux/kernel.h>
- r0 a: n" n, [2 i2 [3 s$ x- l#include <linux/fs.h>
) n* @" Z0 r# m9 f9 w#include <linux/init.h>
5 }* s# ]' L% k( ?% e2 Q% |- j#include <linux/delay.h>
4 C% W2 T6 y6 P9 T7 E5 a#include <asm/uaccess.h>$ F) k5 c/ k' x$ H. d$ n8 |" Z/ ?: p
#include <asm/irq.h>
; ^( i4 d( d% g q#include <asm/io.h>
' [/ Y/ J/ S0 ^; r# Y! F#include <linux/module.h>" R# i6 Q. F$ F7 g/ Y0 ~8 E
#include <linux/device.h> //class_create7 ?: J/ w4 Q* H+ f5 Y$ h% Y
/ q; \8 }9 r$ [8 ^* [% h, X/ m
static struct class *firstdrv_class;
/ a. t0 ^ J7 _2 ^7 D- K9 Q- ?static struct device *firstdrv_device;/ e y( B/ Y# _2 e, u
2 P" ~: T6 }1 h; Hint major;
. w$ M ~* t# k4 k; {2 Estatic int first_drv_open(struct inode * inode, struct file * filp)
( p q3 I/ V, o* [{# Y4 r$ @) ~" }/ c$ H6 E
printk("first_drv_open\n");
" R! {: l) p: _3 k/ R return 0;
1 G2 a- e8 f' _/ j* l8 f}
0 _# d' J! W, lstatic int first_drv_write(struct file * file, const char __user * buffer, size_t count, loff_t * ppos)9 {& D/ P- ~$ F( b& @, m
{
! V! Z# `8 L! d- j. I% o- T* x9 F printk("first_drv_write\n");2 g0 G% B# z/ o* g6 ]; ]
return 0;# @& x, B9 y) J: I& @/ s$ ]
}0 v0 l' b4 m& K$ J
1 a* }1 y4 V9 O: k- v6 ~* V2 K/* File operations struct for character device */
0 p1 D/ I& o; C0 Q+ I4 M- T$ E" ostatic const struct file_operations first_drv_fops = {& Y* G' w" W. s/ H4 F$ q
.owner = THIS_MODULE,, |4 j) ~/ k$ i
.open = first_drv_open,
% |' @! ~, u, j6 p# z .write = first_drv_write,
& J' F% a" v) u# \8 p' F};: {' I. w, f/ {
: s% E5 L4 d( Z5 {- q- u
/* 驱动入口函数 */
8 S+ Q7 @8 Y* i% B. q7 jstatic int first_drv_init(void)8 C3 W$ U9 w# V0 j
{
0 W7 y. w( [# n) I5 _ /* 主设备号设置为0表示由系统自动分配主设备号 */
9 i( N! e1 B, U( _# `% x major = register_chrdev(0, "first_drv", &first_drv_fops);
* T' o3 r: u x4 y: Z( q3 {$ r2 h) Z3 _! \, `( s/ a" q% Q0 t
/* 创建firstdrv类 */
A: N% \" m/ N2 ~9 J3 H firstdrv_class = class_create(THIS_MODULE, "firstdrv");2 R, h* j* x# ~/ T, \* S. T, {
5 s5 [, V0 s p/ Y /* 在firstdrv类下创建xxx设备,供应用程序打开设备*/6 c. e- d0 D/ x
firstdrv_device = device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xxx");
" \4 D7 e& E1 F0 T1 W3 d- _4 ` return 0;) t% R9 G, \ V2 g, |/ ?& O4 I
}# d$ {3 J! y* {0 w: O
) |3 M% _3 Q0 O: G! w/* 驱动出口函数 */
+ n1 }7 `" h1 l0 b, Z4 h: Tstatic void first_drv_exit(void)) z1 L7 f8 t5 ]" f
{
. e T5 G6 @! W3 n) U8 j! ], s unregister_chrdev(major, "first_drv");
; ?( G+ r1 A7 b2 ~7 r" A5 P device_unregister(firstdrv_device); //卸载类下的设备
+ x) ?. Y' W2 Q8 v class_destroy(firstdrv_class); //卸载类
$ D+ B H) X* r}$ |; X* c) W8 P% H; r
; B5 | f9 n' m! c+ s+ o
module_init(first_drv_init); //用于修饰入口函数
% H- k, R( X7 E# U1 |* r6 a/ Jmodule_exit(first_drv_exit); //用于修饰出口函数
! o2 J- O) ?6 c5 z' c; x' t; K1 L
4 N7 ?3 T& O3 [! a$ M" OMODULE_AUTHOR("LWJ");- L m! p7 I: I: m' K: C- M. M. N
MODULE_DESCRIPTION("Just for Demon");
* L: a6 n+ b+ }3 F5 n% j0 d7 _MODULE_LICENSE("GPL"); //遵循GPL协议$ A' V9 o0 R9 ~6 U; R
6 |! P# o( ]; U4 {: M& z
. Z1 G& U d9 N" L5 m! ?注意事项:8 J( u5 t% W, ~% \6 |
1.因韦老师使用的linux版本跟我使用的linux版本不一致,头文件路径可能有所变动。
/ m* z5 r7 |) F; Z9 Z
* O6 ~; K$ c% O& _" h8 E2.使用的函数名可能也不一样,例如: T0 i' ^2 y5 ]. s0 C
0 ]( y; e( q5 n! V% |+ g# d韦老师是这样子创建类和创建类的设备:
4 t# C' B& ^8 O, ~/ r2 @" c, B, _9 I& q1 Z8 J
一、定义2 @- v8 |0 \) r3 r; x4 e
" N( _5 Z' i" p2 b6 s0 Ystatic struct class *firstdrv_class;
. O7 H( `0 `' ]+ ?4 V, sstatic struct class_device *firstdrv_class_dev; N1 e5 K! ?+ J! t
7 }' t* V h! M0 j, A
二、入口函数里
& V6 C% V2 R' l: \' K* z
4 E' o/ k0 }: D0 Sfirstdrv_class = class_create(THIS_MODULE, "firstdrv");
; ]: R0 z0 k; P1 X. l4 ufirstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz"); /* /dev/xyz */
) r0 i; H8 r8 B: o
/ K9 Q+ C5 v4 D9 o! t三、出口函数里9 y0 g! Q, J* w, Z
8 X$ e3 O5 z- h4 nclass_device_unregister(firstdrv_class_dev);
3 @. a% V Q# M. oclass_destroy(firstdrv_class);1 d8 A. r4 e% ?
+ ~6 j5 A! ]. t! f9 s" {1 J x1 O: }* b+ p5 i
! t1 w# O& K0 s1 Y
而在linux2.6.30.4里,并没有class_device_create和class_device_unregister函数
, V" W- L. F$ b. y+ i
; v( }- ^5 t/ }7 B, c6 h我是这样子创建类和创建类的设备:
% A: \; z% r0 }2 E3 O6 X: r6 q9 s6 t- k
一、定义
2 W3 P- b$ s3 q0 O k' I
9 W( _5 _% M2 M8 e% [% Hstatic struct class *firstdrv_class;
! X3 Q9 y& `0 }# `, o; f. wstatic struct device *firstdrv_device;
, D/ r5 X% A. f
6 l1 @7 r7 z2 b& A2 ]8 J1 G二、入口函数里8 L+ T6 c4 d% O$ Z5 N2 y4 W
5 R& X0 P( v8 _2 V4 @
/* 创建firstdrv类 */
S3 M* {' M$ p
/ ]8 J6 Z- l( t0 X2 wfirstdrv_class = class_create(THIS_MODULE, "firstdrv");9 _: A; ^; w& t& L8 A
) u1 z; L _ U0 C. N9 g$ Y
% H# {; J3 D5 O+ {: W/* 在firstdrv类下创建xxx设备,供应用程序打开设备*/
+ H% R2 F& F3 P9 w: R3 l& a4 Y# bfirstdrv_device = device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xxx");
w' \$ b+ W- \7 N/ w0 ]4 h- n
- B, w0 @$ W: c' Y5 |. W三、出口函数里3 G: @4 V" d( Q1 H. `
7 k. }% D$ ?4 R f9 k9 ~device_unregister(firstdrv_device); //卸载类下的设备
; C0 _4 Z# s9 \$ o5 |3 f# T! G1 f/ tclass_destroy(firstdrv_class); //卸载类- n( x& p0 N9 s6 P8 j3 Q
( a3 E# F% g4 o# n3 o$ ]" e5 Z y
0 E3 c* t2 a; p; H1 n( R0 }: N0 y" `5 b1 A7 K) v
linux2.6.30.4使用device_create函数替代class_device_create函数;8 K" {' P( G# P. I) F; ?
3 u! a6 }% L- u; B3 d/ T
使用device_unregister函数替代class_device_unregister函数。
7 k- B9 ^! H# p* F! D* |
5 n j" l% s, O/ K! ~$ C" @
+ \; I, r# O4 T. S1 _0 v, P2 k: I5 g1 e& H. U) E0 r) ]) \
测试程序和Makefile没有修改。
3 P# d' N4 W! R6 g! r0 X
( t, D( W. n3 M1 b8 h2 Y+ y" n1 e- G4 [8 p# _
测试步骤:
6 k; ]2 l. P% P1 J+ t
# S N4 u" A7 k: Y
( p! v' ~7 U# j' S# B& e( e8 W[WJ2440]# ls- p5 }/ m" m" W0 T7 W% l( x
Qt driver_test lib root udisk% X" d" y9 f, j
TQLedtest etc linuxrc sbin usr$ h+ B4 n# J; S/ D6 e9 F
app_test first_drv.ko mnt sddisk var
+ h* x5 k+ I& [5 B( I- y* G1 H! Jbin first_test opt sys web4 `( U1 g6 Q* I$ g( |
dev home proc tmp4 m* c0 Y$ c: S( P* Z( [) W( m( H
[WJ2440]# ls -l /dev/xxx
+ K" r( w5 w0 @; u. v' [* h: Gls: /dev/xxx: No such file or directory
" [" M/ x3 f' ^) n4 t4 |[WJ2440]# insmod first_drv.ko
: V# {4 |7 |4 @/ K3 u0 ? E[WJ2440]# lsmod
7 g6 G5 p7 H8 |' ~# F* Q. Kfirst_drv 1912 0 - Live 0xbf000000
0 R( A, h0 L K* w- @" n[WJ2440]# ls -l /dev/xxx
K& }% r% {0 H( P& x) ecrw-rw---- 1 root root 252, 0 Jan 1 23:17 /dev/xxx
5 N4 m3 |3 j' ^( j3 P* K( s' r" y[WJ2440]# cat proc/devices ' i3 m* ]6 P! ?1 R3 G; v
Character devices:' c3 O/ t! k$ f( l/ V* W, g
1 mem
5 p) d% w& u0 M' Z" Y 4 /dev/vc/0# M+ n; Z. `. @; C
4 tty
+ H; o/ }5 o$ o" o8 c 5 /dev/tty
0 {% h, t+ r# z! v( N* l1 o 5 /dev/console4 B1 u) Y8 g+ E' ~5 j7 G/ w
5 /dev/ptmx$ v/ x) X5 E/ Z' S/ t0 D3 w
7 vcs7 p- w" X) K5 o1 Y N. I1 a3 c
10 misc5 o1 F Q# T3 R; C
13 input
& e8 _' S% W! G* z 14 sound0 y% u: U# P& v ^. [
29 fb
' |1 j) p0 I# g. U! T2 R } 81 video4linux; c: x0 {1 Z0 P( n* T; \$ m2 b! c
89 i2c
" N7 F# m; l5 Y; S 90 mtd
1 m1 e& ^1 K7 z3 C+ E# j116 alsa8 R2 A, x# o" R* ]2 _
128 ptm0 \: r: q! ^2 E$ P. D5 L/ P% T) i
136 pts
8 {3 j; P" Y$ h3 J0 O180 usb
1 `$ _/ p1 M6 |3 j" O188 ttyUSB. E8 c2 q! q( S1 o) v+ e. V- X, P
189 usb_device
Q+ j$ \1 }$ L# \( `204 tq2440_serial3 X/ C% _; i+ {9 n" n
252 first_drv1 \0 s; j% _ S
253 usb_endpoint
$ s( p) q& C3 u4 D4 B/ M4 u3 R254 rtc
4 C# S ? T0 a, M& }( P6 ]. Z/ x
; h$ h4 B: x9 @. P, ]Block devices:4 \9 r' L% r8 T# V5 u" n
259 blkext: {, m3 _; z3 k2 o- U; v/ c
7 loop( T0 d3 Z5 F. i: H0 E- k5 r3 c
8 sd8 c* ~/ b' D; V ?5 W. ]2 b
31 mtdblock6 r' \! w0 E s4 m& j j) H7 k
65 sd
5 r1 E# }2 f* ?/ L. b) t5 Y 66 sd5 C, U6 r* E. e0 n2 r. K8 w
67 sd
! ~8 ]% d4 }# T& F4 X% l/ h, f4 ` 68 sd
( G7 G. g" h$ T) C* _% E& ~- c 69 sd
6 M3 n1 s9 M+ J$ T! m7 l) ]8 d 70 sd# f5 a# O2 v0 t" d, T* V7 |1 Q
71 sd
r/ t1 e8 }; F. S. q3 h128 sd' s, q6 Y: B. K7 s' d! {/ B
129 sd
0 _7 ^# [& K! f( _# s( D130 sd
" S2 f1 M6 n" X: [% T" e/ i& N131 sd
" l7 ~+ q: G8 `# A3 U/ B$ V6 j w. i, G132 sd" V& b3 O& y. T5 M
133 sd
* E- f. l1 _ O134 sd w# q7 Z0 l1 `6 a. D1 Q
135 sd
( M& D- H' W: `6 ?179 mmc
/ k- o6 H: w0 u. _4 l; K+ P[WJ2440]# cd /sys/class/' H$ D" X8 ^& w% w/ f6 q
[WJ2440]# ls
& R% [' u; b% F4 I" {bdi i2c-adapter misc scsi_device usb_endpoint
$ Z9 k9 D8 l# n0 P+ H1 Fblock i2c-dev mmc_host scsi_disk usb_host: D; |( U& A- S, \* y; v9 ]
firmware ieee80211 mtd scsi_host vc
. X( G" ?/ ~; g4 m* M3 S' Qfirstdrv input net sound video4linux
8 y4 G4 C/ N7 d0 \- c. B+ ]6 h3 Egraphics mem rtc tty vtconsole, z: J6 L. k1 r9 c( Y
[WJ2440]# cd firstdrv/
2 e9 ~8 A- u, @& A- g& J% L+ H[WJ2440]# ls' k. s X3 a3 b: X0 q; J, ~
xxx# u0 b$ J# f, k4 ~3 G8 u
[WJ2440]# cd xxx/+ |! \$ e3 X7 q H- m6 X4 k8 E
[WJ2440]# ls / G: F! k+ v1 x) R; A' T' |
dev subsystem uevent" o. @5 b9 r8 h4 p. i; v* Z# |
[WJ2440]# cat dev 4 z: E, V. U4 o
252:0
/ ]& G$ W# s3 \1 P[WJ2440]# cat uevent ( J! M- T0 ?9 {+ T0 z- p" e
MAJOR=252
$ x+ x/ O, R# `4 P$ K6 Q a. q5 ^9 xMINOR=07 O* ?3 M. t# t% u' x- D
[WJ2440]# cd / 4 s' O. T! S! O4 x
[WJ2440]# ./first_test + [' R$ _( s, i0 E! J5 I7 H1 d. L
first_drv_open
: m% X- ^' x4 Q" u- t7 Mfirst_drv_write
: B$ q7 n8 i P' t9 s! V- ] W[WJ2440]# g; V$ }6 K b; S2 ~! z& n! j; S
# h/ L+ g0 `: Z7 r$ Q' E
2 m2 l- U) \, y( C
9 t" r% f+ p# _% S8 F8 }" F4 h
2 A; ^, x/ V+ S) R; k0 W |
|