|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
上一节中,我们是手工创建设备节点,大家肯定也会觉得这样做太麻烦了。* L9 q# Q$ Q, t
% [4 w3 w& m* I上一节文章:( T- ?8 \. b1 }
问:能不能让系统自动创建设备节点?5 l/ A$ c" _, C) a
1 {# U l* ^& u5 A答:可以,linux有udev、mdev的机制,而我们的ARM开发板上移植的busybox有mdev机制,那么就使用mdev机制来自动创建设备节点。$ z7 @% b. i" Q6 h% K( d
. K/ D( J0 _0 u" h8 o# L3 o
问:文件系统里,在哪里设置了mdev机制?9 f _# H- v: D/ I- d
3 n# n; E6 ]7 _# H" w. n
答:在etc/init.d/rcS文件里有一句:$ [8 T3 H9 u7 H# w4 a
; |0 }# K) S) s+ \echo /sbin/mdev > /proc/sys/kernel/hotplug7 Q, Q/ W7 @5 f. d% i
% q9 u2 w' r: O% u) `# Z1 t问:在驱动程序里面如何编写程序,让系统自动创建设备节点?
' K! y1 V) G* J& T& v$ W" h' E R7 @5 n
答:首先创建一个class类,然后在class类下,创建一个class_device,即类下面创建类的设备。
) _# ~, v. ?3 r; \4 l# i' S
4 h( _" X0 v/ T- y6 f; M6 r/ f' t6 W; Y% i
7 @, g& ?; V- J7 v( D, {" f# K详细请参考驱动源码:- K/ A# a* q8 E
, G' M0 {$ p% m- q3 H: S; w( a% ^, U- l; U: ^; Y8 w
#include <linux/kernel.h>
0 U0 H' U8 W/ A/ U* s#include <linux/fs.h>
]" L9 Z1 O5 n% ?5 p1 ^ r" @$ @#include <linux/init.h>
" {8 {4 R0 ~7 C! Q3 B6 _#include <linux/delay.h>+ {8 M7 U7 c" H8 B7 w# |
#include <asm/uaccess.h>
; i& }* L2 k0 w ~1 L4 b#include <asm/irq.h>8 W0 d' B; R: ?$ c- L5 H
#include <asm/io.h>
. i' l# M9 r0 u! ?#include <linux/module.h>1 l- @9 b2 @5 f* S, x
#include <linux/device.h> //class_create9 w8 T5 I& m3 u8 X5 \8 l- \
( S( L8 t* `+ mstatic struct class *firstdrv_class;
$ i2 r7 N0 S0 Z0 Z9 P2 z jstatic struct device *firstdrv_device;0 d! M! x0 u2 Q8 o8 V {" }
. d# K1 X. T4 x1 p# A3 Y7 x1 I
int major;; P" g% [. W$ H/ t) s* n: A' c
static int first_drv_open(struct inode * inode, struct file * filp)4 O* ]# G( N. r0 K& R' S8 J" H
{
2 Y `. h; g& A) @! W printk("first_drv_open\n");
9 K, L: E% Z; o5 i3 E return 0;
1 ]1 T4 D( e/ o+ N! T, J% T0 w}+ F) Q- G1 H, q; ^& Q# x: D6 R
static int first_drv_write(struct file * file, const char __user * buffer, size_t count, loff_t * ppos)/ I, `$ m2 y! i- Z
{, P/ Y: W8 a7 a% S) ?. `( ?
printk("first_drv_write\n");
8 {$ j' f% e/ [( H5 W return 0;
( v4 N" S/ F0 W}
2 T" M A5 k B. B2 O0 u* B6 m8 g1 z
/* File operations struct for character device */
r7 @: j& u& ?% istatic const struct file_operations first_drv_fops = {
& m( J R/ n3 ? .owner = THIS_MODULE,9 D* ^2 {: a6 O2 r# b
.open = first_drv_open,; B$ @1 ~! O0 y9 ?0 R( i
.write = first_drv_write,
4 o4 b0 ?" J3 H4 `2 _/ U) [};9 b4 J* P5 G9 @5 ^" c" ^+ T
0 Q$ a, g# h f0 U6 E! D, ]3 p/* 驱动入口函数 */' i. y: b! U1 p# n) s
static int first_drv_init(void)) V( t$ L3 Y7 j, L; T& X# x
{
2 }( ~0 Q. m) y2 F' I2 q$ ^ /* 主设备号设置为0表示由系统自动分配主设备号 */8 p, t. ]: q1 p( e7 ~1 j4 z; f- K
major = register_chrdev(0, "first_drv", &first_drv_fops);
/ L; O4 ]/ b1 N$ X( A9 P q- _) M% ]0 O
/* 创建firstdrv类 */
& x: l, B; o) i6 Z firstdrv_class = class_create(THIS_MODULE, "firstdrv");. l, h$ y& H$ \% q p& j
5 B. o0 f5 G& z /* 在firstdrv类下创建xxx设备,供应用程序打开设备*/
9 q8 W6 Q) A, M% |6 u6 } firstdrv_device = device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xxx");; V/ Y, o) t- F" P B4 |4 m, ]8 h
return 0;( ^8 x. S$ j' W, n' }9 l$ g
}
3 R6 u+ Y0 O9 N8 b" `
9 ]5 p" D9 m# n1 M/* 驱动出口函数 */! H3 C7 W& i! D" s2 j
static void first_drv_exit(void)
/ a8 ?! U" {0 E4 ]( H2 h/ E{
" t6 c/ _1 c: }8 X" H; t unregister_chrdev(major, "first_drv");
# u3 K U$ d0 d. [ device_unregister(firstdrv_device); //卸载类下的设备
! h8 k5 z# d% {9 s5 t class_destroy(firstdrv_class); //卸载类
U* T% T( H2 j* Y- Y}
" F1 ?9 t' [& j q0 P4 R \, J- z" i, L9 X6 w* ~: J4 |5 Y2 o
module_init(first_drv_init); //用于修饰入口函数" \6 z% t6 K: M' |" ~1 I8 k; |. U
module_exit(first_drv_exit); //用于修饰出口函数
# Y( c" _$ Z x0 Q) N) t7 S$ P7 n& R+ U
MODULE_AUTHOR("LWJ");
( a1 W9 y2 O) V, A$ V0 I" NMODULE_DESCRIPTION("Just for Demon");
4 X' ^4 M: V$ Z4 uMODULE_LICENSE("GPL"); //遵循GPL协议
9 b0 w4 B, D( W5 X. \) W
9 l7 u* _& |' b, r; U$ N# k( D. E4 J3 w
注意事项:$ }, Q, w7 D9 K; K' G
1.因韦老师使用的linux版本跟我使用的linux版本不一致,头文件路径可能有所变动。
3 y* w+ w9 U, `" k) E
+ g# |% k" \. z W0 C1 |2.使用的函数名可能也不一样,例如:3 z+ A1 E }+ y3 D1 }8 p6 l
3 b4 D+ M! h' M# V" C2 n6 O, n韦老师是这样子创建类和创建类的设备:& Y( s- F2 C8 I0 f3 t3 f6 S
. x8 D$ g) O3 ~3 |; i+ t
一、定义2 A7 P7 e- Z. F; t$ l% c" Y
8 T b& u4 e0 m0 R/ F/ q" x6 \static struct class *firstdrv_class;& U# m; T2 n$ Z( P. Y
static struct class_device *firstdrv_class_dev;8 H0 v' Z0 F6 ^3 L: j/ y0 j, ]
& ?& D3 q4 C- E1 M二、入口函数里
$ L: W7 k# r+ ]" _" K9 X- L
+ [7 T3 ~( S; f- ffirstdrv_class = class_create(THIS_MODULE, "firstdrv");3 N1 p0 K3 K- Q1 Z% s$ E2 i
firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz"); /* /dev/xyz */! y$ k; y( m' i$ P3 i/ S. r+ N' c
) r' d$ Z8 ]9 x5 G
三、出口函数里
8 r+ j8 r# t( X# v1 }8 j$ S, a6 z- A# X5 S \
class_device_unregister(firstdrv_class_dev);
9 G' G" o- O0 D8 ~0 V' Rclass_destroy(firstdrv_class);( _" X3 H. U* [7 x. F! q
3 T' c3 k& x9 [# l
+ i' x. _$ F% J5 i7 l% J; Q& G8 u: ]4 [
+ ]. ~3 ?( q5 a而在linux2.6.30.4里,并没有class_device_create和class_device_unregister函数( }3 q$ n }" L; N' k$ z
: M0 u5 ?" a- \3 s6 M: D o我是这样子创建类和创建类的设备: n7 W1 A" x8 b
8 I# ` J* x. x一、定义( E# B x& j8 o
% z3 r6 ^# i v8 a$ C6 R+ H a3 P
static struct class *firstdrv_class;, v$ h$ j% H' Q7 C/ m8 d
static struct device *firstdrv_device;
7 h5 O! [) y5 c/ R# S( Q% Q
8 E) r d f' [& ?8 W二、入口函数里) J7 h/ _1 ?$ V# @: O. j( D9 w$ }9 A
6 X- [7 c1 H0 R1 E7 ?& |5 n& T
/* 创建firstdrv类 */8 F1 k( W0 w+ L" T4 t9 W- b5 h
' O8 _7 @! \: X6 C! Pfirstdrv_class = class_create(THIS_MODULE, "firstdrv");
8 v* H( o2 l* }+ o9 N9 S! F8 I, C" S1 Q2 x# F4 k; f/ q
5 b M/ S3 E9 L: c/* 在firstdrv类下创建xxx设备,供应用程序打开设备*/+ K ?/ R' m/ T( L, K# b
firstdrv_device = device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xxx");
8 x, |5 t4 s& M. _. ~0 u8 P! f7 [/ ~3 K' }" l- u' k) u% O
三、出口函数里9 L* L9 n/ U2 h3 {, }9 s5 r) ^+ K
8 u: x9 c8 _. S" \0 j
device_unregister(firstdrv_device); //卸载类下的设备' {" L2 |( |5 A: Y0 E8 \2 L
class_destroy(firstdrv_class); //卸载类9 z- H8 \, U4 f4 c3 u& A" z
4 X) e. W: Z; d
4 I+ r; O8 t3 X
/ `# M. z2 g/ y: U* O4 G# Flinux2.6.30.4使用device_create函数替代class_device_create函数;/ |5 g) W$ w" y
) e5 D j* f2 X0 C, [使用device_unregister函数替代class_device_unregister函数。
- z, g" [/ G1 {" \/ B( |+ u2 T+ f- X6 F m4 U2 T. F
2 B# S( [' D3 r" w+ n, Y! r/ ^: b+ d: b) F) ]" N
测试程序和Makefile没有修改,故再不贴。! K; ]) |$ t; T* `
1 ~" H2 ~) c" k) |5 @( e测试步骤:
5 I3 O1 d7 x; U7 \, v
8 @9 m4 V& t4 `# G. I1 o! \% E
/ D" s- I) `" x[WJ2440]# ls9 E- T1 ~7 r$ i, Z" c8 K& l
Qt driver_test lib root udisk' C: ^9 z: ]. w7 N" ]' C
TQLedtest etc linuxrc sbin usr
3 W2 J# F4 |: Z3 ?1 C- napp_test first_drv.ko mnt sddisk var
8 F* I+ k) d. _6 I5 Nbin first_test opt sys web2 M- I- ^" H$ B6 G# V) e9 g
dev home proc tmp
$ |, o# @* a: U U5 [: W6 G5 v+ P3 X[WJ2440]# ls -l /dev/xxx; [) w/ K, i0 {1 s/ `) y
ls: /dev/xxx: No such file or directory
) d, C5 i7 v) T1 h/ [9 e# P[WJ2440]# insmod first_drv.ko
3 L9 a- y5 h/ W& |[WJ2440]# lsmod
+ v, P& T8 u, ]; Z" {first_drv 1912 0 - Live 0xbf000000$ D. G2 ~- j5 Q' }: @
[WJ2440]# ls -l /dev/xxx
2 w' k" a/ E q8 ^/ L; ]0 a& qcrw-rw---- 1 root root 252, 0 Jan 1 23:17 /dev/xxx
3 D& y0 ]) @, l0 ~6 {7 I[WJ2440]# cat proc/devices 7 r+ W0 K6 H7 _
Character devices:
7 w; n/ ] m1 p) {8 Y/ J/ ?" r 1 mem
% E" @8 A: i9 q2 W, b E 4 /dev/vc/0# q: t2 t& o9 Y; N6 S8 [
4 tty
' Y5 u& l8 q/ h% f5 Y( m 5 /dev/tty
2 F+ h2 x9 b. s0 X* }1 ] 5 /dev/console
* y. p- L* m+ E$ \& x 5 /dev/ptmx) p, @, K5 E3 ?0 x5 Q8 E* G2 ~/ m
7 vcs, M- u& n9 y7 H3 F+ y9 w" `# O' ~ ^
10 misc
% X4 u0 y% S/ P' X. _5 p3 w 13 input2 [' i" T: p/ {" v; t- ]
14 sound
6 }5 p- h' d1 X9 k$ e: W 29 fb
/ a' p! ^! [' A! l 81 video4linux7 Q* B% ~5 I+ `7 j) e
89 i2c
7 E- z: w* @: i* H6 K1 R. w 90 mtd
0 _+ g' o9 M% Q/ k7 H116 alsa
3 D9 N6 ~( [* |) p3 ]& i- r1 A' i128 ptm
( m9 q6 X4 U5 `+ x! t7 a3 T136 pts9 u! ]3 e/ C: q$ \2 T, x
180 usb/ s" T$ g4 ]8 y" x- `
188 ttyUSB
* Q1 p& B+ ?6 l" ~189 usb_device
" i& L6 ~1 J6 }2 G" `3 f204 tq2440_serial- m5 n7 {* k. Y# j a
252 first_drv( o- B. J6 J& R4 S/ E6 ^) v+ N
253 usb_endpoint
5 u7 w" j& K5 K2 U( E& v& ~254 rtc2 b3 y6 T5 Q6 s4 m/ ] o
! W! t; W" W. {# Z* [
Block devices:* v9 K+ n# G% V1 X9 y: S
259 blkext
o7 n# s6 r* C* f+ q, p+ Q$ `$ o 7 loop! u1 z: |0 q4 m# p
8 sd2 P* W; P' R% {9 H8 C& P* {! R
31 mtdblock
8 `# ?. Y7 W# V$ `" C3 t9 S0 p; h 65 sd/ w4 l, t! q- m" Q& U/ ~* Z# R
66 sd2 ^. P; U$ B }
67 sd! D9 v* p. X5 e; L; H
68 sd
; F" V: P" P8 U& e9 t8 Y$ n* s 69 sd2 }/ h |5 }- d4 B2 L8 u( P
70 sd
* B4 P' [& g/ u0 T+ s6 N' d 71 sd; O' ?( Z. k) C+ N3 s U
128 sd
$ }* e/ r$ s3 P7 A. P: Z129 sd
2 D6 {6 e5 i z: \130 sd9 Q8 [& |1 c9 l! @9 {
131 sd/ N& C' i+ {: O
132 sd
4 d- I% g; e6 }& A" D133 sd
6 l: s R/ a* Q134 sd6 z' \9 a) a: _" [8 j! [ X( d
135 sd
* P' ~( E- w' U. Q; a% x179 mmc
2 y) M/ k" [0 o2 e+ s6 [7 I+ K[WJ2440]# cd /sys/class/
5 G$ }* i5 ?9 Z* A[WJ2440]# ls- T5 c8 F* a1 b$ [: U& p- c
bdi i2c-adapter misc scsi_device usb_endpoint& m( C$ E, b1 `
block i2c-dev mmc_host scsi_disk usb_host
# T9 w, s% ?9 }5 b7 S: }2 pfirmware ieee80211 mtd scsi_host vc' C: w( f8 h E& ?" Q
firstdrv input net sound video4linux% B5 N# A" r$ Z* t1 _
graphics mem rtc tty vtconsole4 Y4 f: D# j! m U( t( j* a
[WJ2440]# cd firstdrv// y$ T. m. T" R8 j; L
[WJ2440]# ls, Z' }9 ~. h# v% v6 Q: I* F
xxx- X; f, i9 q7 p4 \
[WJ2440]# cd xxx/+ U4 Y3 K Y7 ~6 C5 t2 j Y, Q v
[WJ2440]# ls
) P- s8 p, w" Jdev subsystem uevent
9 ?. O* L6 D# s8 p- T[WJ2440]# cat dev 1 c6 }- m+ |3 Q' s d
252:0; O: M8 X* X1 r- q: q! t ^2 i( f
[WJ2440]# cat uevent
! K6 e$ q. y# B i( EMAJOR=2527 [6 N1 L& Z8 [0 g
MINOR=0
/ G! V7 P- r4 b" x% Z6 t[WJ2440]# cd /
7 K4 P" a5 t3 T+ C4 U5 W$ M# I5 z[WJ2440]# ./first_test ; F) M9 S6 \( L; m' O. j: X( ?
first_drv_open" Z% e0 I( U* M. }% A9 r- }7 a, i
first_drv_write
( F" Z6 B# N" O[WJ2440]# * U$ \: p; Y4 F2 o) [7 n
: s' @& L5 J" b4 e, I9 `1 |( p5 r
- g8 i, i J0 m% M2 C' c8 R6 M* Z1 Z l6 r% r
|
|