|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
问:能不能让系统自动创建设备节点?* M& W& Q6 \, a) e# ~$ v
2 Q5 t4 |, u6 w G" D
答:可以,linux有udev、mdev的机制,而我们的ARM开发板上移植的busybox有mdev机制,那么就使用mdev机制来自动创建设备节点。( b8 r+ }: |: ~2 I$ O; F
! `; \5 k8 @3 [5 T( Q. F问:文件系统里,在哪里设置了mdev机制?, c- A( |5 a* ^6 a o/ E# n
7 [+ T% o5 {% A" ]. \1 y答:在etc/init.d/rcS文件里有一句:1 X6 r( `" c7 o: N
1 w( ~ q* ]9 {5 g/ \1 @7 |* m2 q( hecho /sbin/mdev > /proc/sys/kernel/hotplug9 _$ l5 K' |* L
$ P1 T8 f. z9 x) z
问:在驱动程序里面如何编写程序,让系统自动创建设备节点?7 B& [# i7 d) @% n# y. r
9 d) E8 C' V8 G) y0 y, A答:首先创建一个class类,然后在class类下,创建一个class_device,即类下面创建类的设备。5 k( w! ]4 G8 q; l- @
3 |' i M+ \; M5 c* o
# L' X) Z0 D2 g: S! X& F2 g
0 [% _# z3 y# I q% J详细请参考驱动源码:
5 t, ~+ ?9 M' e3 |8 R9 j9 i
: k- i7 C z K+ {& O' o( Y
( J5 N& o. X7 z: B7 Q! }#include <linux/kernel.h>
! ]/ y' E' {/ s1 s" F#include <linux/fs.h>
. b3 M, V8 i$ ]+ D& v4 Y5 \* J#include <linux/init.h>
& W/ ]* n( d3 O4 c1 K! }; I7 c#include <linux/delay.h>
3 Z y9 m, C% Y9 I, h: X2 I6 W#include <asm/uaccess.h>% g( e. ]+ v7 }! T1 W, L
#include <asm/irq.h>* g6 E+ @2 ^5 S) y3 |( J* S" E
#include <asm/io.h>7 q' j: \+ j3 f
#include <linux/module.h>
# U+ u! d9 T. S. G# W#include <linux/device.h> //class_create
, d3 v# Z' Y, a; |3 q
4 m# _! U, |+ |. T U$ Cstatic struct class *firstdrv_class;6 ?+ z- c. ?" Y
static struct device *firstdrv_device;
# H0 g4 Q* E% A" p% m T% u2 a# A& \' M
int major;( l+ H/ [: E9 s7 W Q8 Q0 k
static int first_drv_open(struct inode * inode, struct file * filp)9 d: P I" K# v8 J5 V4 V$ r! l% i
{5 ~) \& ]" d; X
printk("first_drv_open\n");
) D# B- \! L/ F$ O return 0;
! {( i; q/ C: y2 Q}( b. \ v! Y$ M5 {5 ^
static int first_drv_write(struct file * file, const char __user * buffer, size_t count, loff_t * ppos)
* z6 h6 ]# Q; z{* y- T4 f& f* M/ v% L' r
printk("first_drv_write\n");: U& g6 E% u+ h! Z
return 0;
; {: K8 V8 t" H( z* z2 G2 t}
/ Y9 m. x$ r' y" d6 f6 l
' Z; O, n( d2 D/* File operations struct for character device */
% _0 A, N- Q; hstatic const struct file_operations first_drv_fops = {
( Y: `$ J0 j( R8 U$ R! h .owner = THIS_MODULE,
& u0 V$ Q: H5 c+ t$ t .open = first_drv_open,5 \3 R' {0 R/ a6 I" I7 i/ A+ {3 T
.write = first_drv_write,
. I: C( T' N: V. R3 z. i. Q6 v) R' B};
. R0 O1 I. J, P1 ^
5 [: a7 z/ Z8 T C/* 驱动入口函数 */# m9 E3 r! B1 |
static int first_drv_init(void)
; R, {$ _4 F% z" h" n$ O2 `8 D{2 W Q1 f1 `: y4 N" X- E
/* 主设备号设置为0表示由系统自动分配主设备号 */
2 I: \8 K" x5 T" k major = register_chrdev(0, "first_drv", &first_drv_fops);
( ~6 Q+ X! S: } \! D! V/ G% t# L4 g' O& e# `
/* 创建firstdrv类 */; K' _ }5 U# E! L7 h5 j
firstdrv_class = class_create(THIS_MODULE, "firstdrv");. e& ^( P' y& W- y: f
) ]6 s+ o/ m7 E: R
/* 在firstdrv类下创建xxx设备,供应用程序打开设备*/, `1 _1 J7 \# c* c
firstdrv_device = device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xxx");, H+ n P+ T+ o$ ]
return 0;" `, X' [) u. O, H
}7 s' F( u7 u% P+ h) I$ p& |* C0 F
8 l7 I- b* Q! \5 g/ [! N3 E8 w4 M+ C
/* 驱动出口函数 */# a! u8 r: S( C$ Q) h# \& x% [
static void first_drv_exit(void)6 ^* n% l y# ? I5 Y
{! I Z7 B: X; H8 j, {
unregister_chrdev(major, "first_drv");
& M( ^, G, L- c8 X8 W device_unregister(firstdrv_device); //卸载类下的设备5 x6 E* D. {9 C3 b% F
class_destroy(firstdrv_class); //卸载类 Z, t7 O9 P, @- a z# w
}3 N' e3 ]" q% A+ H! J) T, h G
4 C0 o+ ]/ E" e; j! Zmodule_init(first_drv_init); //用于修饰入口函数
" J; v# Z6 `! v3 j( s2 Bmodule_exit(first_drv_exit); //用于修饰出口函数
7 N f7 Z& Z+ R" {, \8 V
9 W& S4 h- ?' K6 GMODULE_AUTHOR("LWJ");
! e5 g, v3 m8 j. `3 q' r2 |; Y) @+ r: wMODULE_DESCRIPTION("Just for Demon");
7 Z! p/ |+ k5 H. x; Q+ X5 [MODULE_LICENSE("GPL"); //遵循GPL协议* `& c7 `, t% A
3 t1 {7 N: ^! p! l! w ~6 @& P
" N" G0 E: u2 b% L D7 K注意事项:; t1 p8 Q2 m6 V- f
1.因韦老师使用的linux版本跟我使用的linux版本不一致,头文件路径可能有所变动。
# K* i3 {. P8 H! C; D4 V8 q3 \
$ j# _: [- Q$ _5 Q2.使用的函数名可能也不一样,例如:
R4 ~" {! x: J6 J, ?, m
! D$ G8 Z1 H* A8 Y% e* L2 c韦老师是这样子创建类和创建类的设备:
) |) v% u" s( ]( c; ]1 J% O
6 K8 K9 P5 U) j0 j) [% M4 B v5 m一、定义. W% C2 ]$ s/ m9 p9 {, @
7 y8 J ]- {( l: b- {static struct class *firstdrv_class;0 ^+ p5 u% J6 _ { y
static struct class_device *firstdrv_class_dev;
$ L. J* C$ ^1 G% ~) R% z9 M- M: b/ ]( ^
二、入口函数里
1 o7 f5 M1 C0 e6 t! m0 t, F5 Q w& I
firstdrv_class = class_create(THIS_MODULE, "firstdrv");! b( _! @5 R( j" L; ?
firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz"); /* /dev/xyz */' k7 `' c8 u! o- l8 [1 u# p
! ?+ B% s+ W/ f& K+ J& i
三、出口函数里" ^' a' l+ h4 f4 i7 @( P
4 y$ w, B$ K( D1 s1 N& e. T
class_device_unregister(firstdrv_class_dev);- `' S1 U# O3 ]0 e$ W+ i
class_destroy(firstdrv_class);; d; [* S% G. i- s3 }
$ E; t7 x- l- m, V9 K
4 M. A2 L: C# z( l j
1 s+ \( r0 M; M& a J( {' }; V" _" e% z
而在linux2.6.30.4里,并没有class_device_create和class_device_unregister函数: J: k7 T: h, l1 T, |
7 x, B3 }3 u( O. e
我是这样子创建类和创建类的设备:, k2 e3 [6 d Z
7 d" g; M& {* F4 z0 T4 u9 U+ L一、定义
1 I! Z. v6 H- d: ?
% t- | ?, H0 C$ _9 Z z$ R4 wstatic struct class *firstdrv_class;
, `( @$ K- I* g4 O1 ~static struct device *firstdrv_device;
) L! t0 B5 S+ v- [
* O- m2 |: n' d3 }& }二、入口函数里* Z0 v: V; V+ K2 u
; n9 G' A! ?( l2 a# L; j h/* 创建firstdrv类 */" }' J" \5 o; t- S# @
/ K& q' c0 }3 K& `4 `& z- o. A8 j
firstdrv_class = class_create(THIS_MODULE, "firstdrv");3 G* v. ?' B0 u8 W2 F2 I
5 e; j1 h5 f' D7 J% b; t: q7 _$ F0 a; W
/* 在firstdrv类下创建xxx设备,供应用程序打开设备*/
8 ]) }2 g+ |7 u2 W, W& [4 sfirstdrv_device = device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xxx");, y. b) w0 ?7 @& ^' o/ |1 _+ O
. b: ?1 Y' G2 R( c" O2 ~4 C- K, R
三、出口函数里; O2 n1 X# R. w. A2 i8 Y' ^
6 l, m2 ^& s- u
device_unregister(firstdrv_device); //卸载类下的设备
, x# B M8 H7 A/ J. X M) I4 Aclass_destroy(firstdrv_class); //卸载类
% g7 I8 @' \+ {! e) Q7 b, D
- J; B4 M( v7 V9 j, d) N8 j; s9 B5 n' [+ }
* R9 G- x# K# O% U4 }# X0 e
linux2.6.30.4使用device_create函数替代class_device_create函数;, @: T/ E+ X* l9 X
, j, j1 `" O( A* c% R& L使用device_unregister函数替代class_device_unregister函数。
6 z6 T& c+ b) k# Z. c t! K6 Q2 g2 I& \! v2 M) J' a5 U
$ `- o6 f5 A' ~
$ G. v4 E; R; J Y& i测试程序和Makefile没有修改。
G A+ J; Q3 [% A# G8 l) U0 E- e3 f" O: o, n$ n$ n4 x
/ u4 ]) _5 R ]0 [) t
测试步骤:" H) K9 W3 s5 @( `
, ^2 c- U* H% M; c. @( j& U8 n; {4 ^3 t1 B( {) i. Y' C% e
[WJ2440]# ls, w# b' U" @% [* |
Qt driver_test lib root udisk
# d& ?; Z/ |) F. [# `# {9 K1 XTQLedtest etc linuxrc sbin usr
S/ G' h4 o/ f& r: G, a/ o7 kapp_test first_drv.ko mnt sddisk var& b# y/ |# }( K, K
bin first_test opt sys web
8 k" k7 s S Fdev home proc tmp
; k; s4 x; a" a. o3 c[WJ2440]# ls -l /dev/xxx
% u5 J: c6 r! A: U6 Gls: /dev/xxx: No such file or directory2 p5 r, }+ m4 h" c3 T- R
[WJ2440]# insmod first_drv.ko ' _ n8 s8 X' n2 B, O4 L- c9 _! X
[WJ2440]# lsmod
+ N* C2 l# M3 S) `7 f- l; W: m8 [first_drv 1912 0 - Live 0xbf000000 T1 k) ?0 O( }+ p9 }# _
[WJ2440]# ls -l /dev/xxx6 T; R" q- s: }- j3 g& v
crw-rw---- 1 root root 252, 0 Jan 1 23:17 /dev/xxx
5 `$ i# D: G+ Z6 r[WJ2440]# cat proc/devices
3 i- n* }7 C4 rCharacter devices:% [: ~$ q2 h3 ^6 D) Q0 f# z Y# f
1 mem
$ [! R9 N. ]6 W 4 /dev/vc/0
3 ~) S x, R2 s U P$ W! Q 4 tty7 e& K6 C' T( a* R! [; L& ^# g0 l
5 /dev/tty
' E$ A2 A2 |& s6 I 5 /dev/console
( N1 |5 D Y( h- C8 E 5 /dev/ptmx
8 u0 @9 k5 g/ r; A( v% ?$ G 7 vcs; ~8 ^$ ^* V. j/ {3 I" a
10 misc$ S' g2 @9 O+ } g* g" i" \
13 input. G3 m3 X/ l; ]. B: U# j0 A
14 sound
9 u" y5 z. M S# D 29 fb
' j' r2 U' k' M1 H) o 81 video4linux' I& x/ t; B1 Y4 } j4 l0 C' M
89 i2c% _# l0 R- W" X3 {: d
90 mtd
' a5 Y5 f; i$ ?8 \1 d116 alsa
- p G: j* q4 h128 ptm
) y, D$ o) L- w- X0 w136 pts
9 D) N' h' b6 Z M180 usb
$ _0 l# c1 X, {$ q188 ttyUSB* Y0 }$ m7 I3 g
189 usb_device( v: f/ R, E( G+ Q3 U
204 tq2440_serial
% \; Z( G# z* G1 u4 l* v252 first_drv* J4 V2 A8 ?3 u) L$ O7 L1 o, C
253 usb_endpoint: i7 _+ I; z* H* {- J: X" W" Z
254 rtc4 K0 c& ^# @) Y$ r7 G6 V9 r
6 @" O7 j/ x( o/ `, |; h& OBlock devices:
$ j+ e0 x" p6 L259 blkext0 c; u& l8 [ s+ l8 R4 X
7 loop- v! L* A# `5 _/ M1 i! f' L0 E
8 sd
4 M: d1 c, x [1 j6 U 31 mtdblock8 v& |; G$ Z: R+ Z' t# j
65 sd
8 d/ z" `. P& F0 ?5 p* v 66 sd# }+ f! S3 e1 D, @6 |, q6 S2 p6 T! `
67 sd% A! j2 A4 J0 B1 K
68 sd
2 w+ b" ~' a& |' y5 b; P 69 sd2 c \5 H2 S0 z; _4 V7 _8 Q3 N5 R
70 sd, W% m6 z. j. p7 Y* v' W
71 sd3 [, W" ^# @; g/ T$ b/ | w! f; o
128 sd
1 U9 @5 }) Y) A+ l129 sd4 h2 M- y3 U$ ?) J* B- m0 h
130 sd
" z( u" W- I" ~) j131 sd
K5 e7 p/ L) p# n, @9 u" f132 sd5 J6 }+ p3 |5 ]( v; d
133 sd
0 { f; }2 T. A* S. P1 I134 sd
8 @, K" d2 U- W135 sd
- P' R9 q6 n+ }! r L179 mmc
" [, C+ C5 Y2 @- B2 X0 e% Q$ p" f[WJ2440]# cd /sys/class/
0 `; o7 t& F+ Y: h[WJ2440]# ls
4 R8 {; g( [/ w5 j- ]: G. Qbdi i2c-adapter misc scsi_device usb_endpoint
3 n7 r7 S( Z1 ?- u# T$ hblock i2c-dev mmc_host scsi_disk usb_host
! x& ^3 l7 ~8 [4 \) p0 Xfirmware ieee80211 mtd scsi_host vc
) l) ]& G2 O3 {& I9 L0 t+ a0 }0 Hfirstdrv input net sound video4linux$ |/ x& P, r: l0 t. L, O& d& g
graphics mem rtc tty vtconsole
4 r: {! k0 H x% b" I[WJ2440]# cd firstdrv/
2 a# X% _, e$ D' A( u" T' U[WJ2440]# ls) Z, e' G( ]: u2 g9 N
xxx
& V8 z7 {9 b" w' Z8 D3 e[WJ2440]# cd xxx/8 Y& P; O) `. K: ?" h6 q
[WJ2440]# ls 8 p* s8 o2 b" f* q2 _, ]( t5 f
dev subsystem uevent9 k! `3 P2 e5 S- f, z( t
[WJ2440]# cat dev
+ }) |2 Y- F! h% A$ g252:0" q- E5 C, ^: l& Y
[WJ2440]# cat uevent
% v4 x# E0 o. l0 }2 DMAJOR=2528 T1 ]6 L" h, G( c& O1 }
MINOR=0
6 ?9 m q2 Z# J* L9 u# D$ P[WJ2440]# cd /
2 G& w" V5 |9 W% Q1 J[WJ2440]# ./first_test ! L+ k1 `( Z5 i! f% D& I
first_drv_open
- B8 b) N6 J0 D; C5 M7 q5 P/ L" lfirst_drv_write0 c+ L1 \) Y0 h$ J
[WJ2440]# , K8 }: d$ g5 P5 I
, J* } G6 i; \! Q7 X
8 Y* v- V/ F, b0 [; X' q- @4 V! d s2 U+ N; m) h# n
. I# q6 D# {7 L |
|