|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
问:能不能让系统自动创建设备节点?" ~4 {% @5 @) Q0 i9 {% S7 D% D
( O. o3 b' q6 S! R- Y答:可以,linux有udev、mdev的机制,而我们的ARM开发板上移植的busybox有mdev机制,那么就使用mdev机制来自动创建设备节点。& x* j3 n, s" x, q# o
- \& A$ u$ o9 g5 B6 B' x. W* h
问:文件系统里,在哪里设置了mdev机制?% _% Z! J( ^- P
( K: P q. P9 U8 B- b) F答:在etc/init.d/rcS文件里有一句:7 r# ?2 y2 m% S4 I& J& {
* _; R: l& k# g0 \/ fecho /sbin/mdev > /proc/sys/kernel/hotplug2 M8 }! ]1 f W
7 u3 I. }- o3 _# E9 k" l9 L
问:在驱动程序里面如何编写程序,让系统自动创建设备节点?
( B; ?2 _, w: F
- V$ U X& I% Q5 B答:首先创建一个class类,然后在class类下,创建一个class_device,即类下面创建类的设备。
4 o$ G5 ]( l0 [ b8 K- s3 G9 X. l2 I& {
' n/ Z. ?* g Q- N! K
1 x2 N4 j+ u) ^
详细请参考驱动源码:
9 g1 s9 h. d3 a& H. J; \+ w' }/ f( b" W! a/ X$ o" ]5 F# l
0 F3 R) d: w/ b#include <linux/kernel.h>
* [1 r& W' g, j8 P#include <linux/fs.h>( z+ |/ m+ e: E. Q+ t+ p) D. B
#include <linux/init.h>/ C. Q5 ?( c5 @8 A* S# s. V
#include <linux/delay.h>
0 i* |; c8 ?7 l' f( u#include <asm/uaccess.h>1 y8 t& d8 Q' S" c% S. i
#include <asm/irq.h>5 B% L" `& c- } q( c
#include <asm/io.h>
: ?' U f, w. i" P) v4 Z6 F#include <linux/module.h>
% n' g0 n. q! Q4 ^. J7 u3 }#include <linux/device.h> //class_create8 B+ p5 h$ b2 b$ `
- ~3 {4 V# l7 d* R3 Sstatic struct class *firstdrv_class;
! {2 ~. I. V9 `3 nstatic struct device *firstdrv_device;
/ V. K: b6 \/ |9 h9 l2 u. g5 ~ ~0 o* ]1 `4 \# g/ l2 G
int major;
* k# v9 O: L7 J( q# ostatic int first_drv_open(struct inode * inode, struct file * filp)
( Q0 B7 H2 R3 g+ i{8 K$ P2 b+ q/ ]: i( J6 F3 E
printk("first_drv_open\n");
* F/ a7 s; g, K9 }) F4 S return 0;2 t6 G6 M& R- n0 A0 l" c
}
: b. @9 c4 F. ? \. Pstatic int first_drv_write(struct file * file, const char __user * buffer, size_t count, loff_t * ppos)# X* ]9 Q$ ^ f* }* X8 c
{* j# ?+ N3 F$ Z0 p9 o
printk("first_drv_write\n"); F3 _ r* ~ ?4 a
return 0;5 X9 N3 n; J9 b8 w+ [# P3 {
}3 S, C7 S: t* F
4 }/ c. P- g) `- L! g$ o, J+ o
/* File operations struct for character device */! T) k8 O' X H% O5 `
static const struct file_operations first_drv_fops = {
% |: X8 z" ~6 ]* j8 P .owner = THIS_MODULE,; y; b2 x4 a2 \' B+ d' v5 b
.open = first_drv_open, l4 P2 D* k) z" e% Y2 t. K" H
.write = first_drv_write,
; `* d1 D% ]9 }6 ?- I9 S, g};
. M0 n- E. N5 B
; Q& ]+ G. y0 n. |) G& O/* 驱动入口函数 */+ }1 r3 i6 V- O" W8 R+ x+ F* Q0 h" M
static int first_drv_init(void)" T$ z+ I. ~; Q. ~: B
{) ]* ~* \6 q* ^& Q
/* 主设备号设置为0表示由系统自动分配主设备号 */6 v; x5 ?) h! u8 `/ N' c% N" A
major = register_chrdev(0, "first_drv", &first_drv_fops);& T/ Z0 |( x2 B& r3 u9 ?- I
! q, o4 x& m- d
/* 创建firstdrv类 */
. K0 }# w$ t, Z/ G1 x firstdrv_class = class_create(THIS_MODULE, "firstdrv");" E3 h6 k. a1 v2 p, f
* ]" o2 L/ {5 d8 T: }; L /* 在firstdrv类下创建xxx设备,供应用程序打开设备*/' u3 t$ j5 H: Z( p. d* ]
firstdrv_device = device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xxx");9 b h; z7 e3 J2 W6 D
return 0;
+ N6 V; o' C4 A}
) l& H& ]0 w* d' {4 w, M
3 x0 k. I$ v; i" M9 t7 N# Y! t+ F/* 驱动出口函数 */
# I- ]! S7 j3 X' A6 gstatic void first_drv_exit(void)- e3 k* |& s' c1 z* ^
{: I6 q; {, V5 Y
unregister_chrdev(major, "first_drv");# m: I0 P' C( Z4 C- L
device_unregister(firstdrv_device); //卸载类下的设备% O M; S6 j7 m2 ~
class_destroy(firstdrv_class); //卸载类- `! C( ^& I; W
}
' l* K7 v+ m0 x( W
" q& B( T8 Q, m' N% Omodule_init(first_drv_init); //用于修饰入口函数
; M1 R' W. f' R# b) z) V9 Dmodule_exit(first_drv_exit); //用于修饰出口函数
- [2 @7 M h; j5 A: `: W1 q& N4 |# W( e& t
MODULE_AUTHOR("LWJ");- @9 y& e; J! v% n" U3 C
MODULE_DESCRIPTION("Just for Demon");. o5 w( `- W _ k* Q; g" I6 z
MODULE_LICENSE("GPL"); //遵循GPL协议% x9 d- L; |, P+ \& \
4 ?" W- n1 w& L1 O3 v- t
; \# w. V% E0 B+ _注意事项:1 ]& }, y$ h, X( ^" k3 P& m' v
1.因韦老师使用的linux版本跟我使用的linux版本不一致,头文件路径可能有所变动。* M0 U" y& @# q8 r& S1 ?) v5 Y2 n( y
* V5 i# g Q# D0 L' O" F! T l+ r& n
2.使用的函数名可能也不一样,例如:
/ T& i6 J9 [: a& P0 e" K* b2 n, b( \. E
韦老师是这样子创建类和创建类的设备:! R' G' L3 M9 ^) Y, p$ s
6 d! v. W g3 y+ F* r
一、定义7 `+ Y$ L0 `3 u/ {
" M' s3 W' B: r3 i* `/ {
static struct class *firstdrv_class;
# ]; @9 f: {6 G; d1 Gstatic struct class_device *firstdrv_class_dev;
1 @$ B. ?" s3 H6 ~# I0 C
# h! o" g9 }* h, A/ D二、入口函数里0 w$ i1 |6 h2 r% d* ~2 E
0 x# ^3 V* H" C( O9 v; H- m
firstdrv_class = class_create(THIS_MODULE, "firstdrv");
1 Z; ~9 S# l8 I4 W' Ffirstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz"); /* /dev/xyz */
* B+ ]) m" Z- N4 }) j/ ~+ _% }3 H/ K6 F5 C$ Y& f- W; X
三、出口函数里4 k# q: j1 l7 B N8 \
Z1 d3 I, I* ]& g
class_device_unregister(firstdrv_class_dev);
5 ]9 n- [; D0 P9 i% y8 Fclass_destroy(firstdrv_class);0 O4 c# w W" J. O" [- M
. P. ]. _- w0 F" L F+ p( f, b% m0 I9 Y+ z' O
% J% ?4 g2 P$ Z9 B K8 l而在linux2.6.30.4里,并没有class_device_create和class_device_unregister函数" y, J: t8 h9 Z) k: D# z( K4 m
# K* R. t; T: g
我是这样子创建类和创建类的设备:3 x* u% V3 z5 s, o
9 `: ~$ q. {& R8 E0 }
一、定义
2 d+ n h" I7 x% R1 G
3 ?" o* _! n( pstatic struct class *firstdrv_class;
+ Y4 r% j. k# }! J: }static struct device *firstdrv_device;! Q+ u; y3 {4 B
: U+ B; K: @9 p: u& `# b二、入口函数里
8 o$ C3 C' q5 ~5 T2 z
6 `# T7 S; @$ k. l3 G/* 创建firstdrv类 */
: v" ^. B0 ]1 i7 @: J
9 l m/ i! Q; E( {/ u9 G6 e$ D( @firstdrv_class = class_create(THIS_MODULE, "firstdrv");
7 a& `0 s& E" K1 A- o: G$ F7 R. Q9 N. j$ }& r* H/ h
# u# C# {6 f+ p O% t* j. K/* 在firstdrv类下创建xxx设备,供应用程序打开设备*/6 i& v* X" H6 u" ^/ m+ }7 W
firstdrv_device = device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xxx");
* a5 c2 L8 c, z. \! w" |9 {" Y7 T9 z& {8 V x) r f
三、出口函数里
0 {( f1 c& S8 e3 ?6 y, t/ k; r
# H6 I* ? T& v% N7 L7 Y* Ldevice_unregister(firstdrv_device); //卸载类下的设备
' @1 O, n8 I- A6 ^# y: F0 m7 Tclass_destroy(firstdrv_class); //卸载类
7 O2 |1 A; g/ r: K/ [: G; t% z' k
$ `( U$ ~) E# I& P% x: X5 f6 Z+ Q8 q$ p( C1 ]+ i
linux2.6.30.4使用device_create函数替代class_device_create函数;5 T; e6 }1 w/ F9 F6 t1 X* {! P1 ~
0 ^) B+ N0 |8 G6 I0 v使用device_unregister函数替代class_device_unregister函数。" T& {# R" ^. C+ p8 Q! @/ H
# _8 K" p; n. j: {; @3 [% b# J) B2 o* t, k; v% z1 d
+ }- {- Y! e5 }" S3 y
测试程序和Makefile没有修改。& K; d* ?( [$ v8 m! }# D! ^* Z
0 F! [& U( |! l
0 _6 @* E( K& e
测试步骤:# z! s9 |2 h1 E2 e3 M
/ Z% F$ F4 d" d) }3 P1 k9 \
/ {5 m( P5 Y8 f. |
[WJ2440]# ls
5 W8 {5 z6 E$ ]Qt driver_test lib root udisk3 F4 L8 |8 }, P; \ M1 w: @$ q
TQLedtest etc linuxrc sbin usr L1 j: z6 m- g, R
app_test first_drv.ko mnt sddisk var
: ~2 A) ` X' l/ _3 v+ u" fbin first_test opt sys web
# [/ F% x: x$ m4 `! e2 p1 u" Q- W5 Rdev home proc tmp
. r. R3 k% n" w/ Y9 L# Q/ l% W[WJ2440]# ls -l /dev/xxx
$ J* j1 I- A- Y& x7 Sls: /dev/xxx: No such file or directory
* F. D/ Z3 l7 s2 ?( H. `+ Q- R[WJ2440]# insmod first_drv.ko
- X- J1 W! b0 K, F5 N[WJ2440]# lsmod
6 r& N4 d% ~2 t$ A8 yfirst_drv 1912 0 - Live 0xbf000000* E8 V* [. @8 o2 G: o3 l
[WJ2440]# ls -l /dev/xxx
. o! }* T) `5 s* t, Icrw-rw---- 1 root root 252, 0 Jan 1 23:17 /dev/xxx
1 x* i; u* `" Q/ V8 P[WJ2440]# cat proc/devices / s7 M' Z% h6 S( Q
Character devices:' M0 m& z+ y. K
1 mem
: o/ D+ I8 C- B% R. A* J' Q2 x- x' m 4 /dev/vc/0/ |4 [ D3 }- W3 M8 x6 l) k
4 tty* `% v, [0 l. I# u0 \
5 /dev/tty
) X4 `$ f( n6 N1 Y 5 /dev/console, I' i: @9 e0 s8 E
5 /dev/ptmx# c3 g1 M8 j9 P! f' r
7 vcs# \2 @+ T6 W4 H u' G
10 misc3 S/ Z) f+ S9 ~1 ~7 h( f. j
13 input
: f0 ]3 n7 p+ T$ A* G 14 sound- K* _1 l6 o2 D8 [
29 fb4 Y: g' S M( X7 Y
81 video4linux
) {. w6 y* L$ f3 X; e9 c( D 89 i2c
9 v5 T7 Z; g) h9 M K 90 mtd
+ e: l$ g- |$ F5 I116 alsa
& o% i/ J. u" k8 T128 ptm
) ]8 C) I' {/ _136 pts" o/ r% o/ b9 o5 G- H& d
180 usb
( `9 |2 V7 B: l ]* D0 O! M8 J188 ttyUSB
4 _" ?! X, O4 {( p189 usb_device
% @7 F7 z9 ?1 j1 w2 t7 @& L5 u204 tq2440_serial2 a/ m! S e* t, [! v
252 first_drv
+ ?, p6 X2 U3 i# C5 s253 usb_endpoint
! z* G7 h5 v. n& |6 p) V3 M254 rtc
* e& Z: p# {8 F: k
9 c( y, D2 p; VBlock devices:8 \0 ], c2 A, U Z
259 blkext
) f3 M# c/ F# l0 k3 Q) N$ n 7 loop
. @/ x Q$ B! W 8 sd( x; l8 t6 L ]. T' U
31 mtdblock" E" x% O2 z" e+ Y% G' ]
65 sd
$ E9 D8 D1 l- U+ W. a/ Z 66 sd9 } Q2 h# q, p7 E2 Y
67 sd8 P2 \+ D) i! G7 {
68 sd+ k8 Q1 c3 V& b+ N
69 sd
: d( }% R' f0 n6 K 70 sd! _$ ?' e7 S# J- }9 X. D
71 sd2 S) T$ P) m6 i1 A* i
128 sd4 H2 q: `; ~" T% v; W# }) N& }9 M
129 sd
) T: X5 @: o- _+ r/ p' Q8 t2 I1 r130 sd8 Q5 ], C, J8 ]. J7 P9 \
131 sd$ D' Z5 @' {, M7 Z9 M9 b8 ~7 G" {
132 sd2 q2 p# n1 d5 @5 S
133 sd* E+ [* e/ h) J( M x- @
134 sd' G# L/ |) |7 |1 v1 y$ t C: R3 y
135 sd
% h$ E$ O5 S9 [- N( m179 mmc
- F6 j1 d$ G( Z O' V! a, l[WJ2440]# cd /sys/class/ x6 Z: [7 G$ Y, q- g) w' ^
[WJ2440]# ls
# L+ c, | b# Q& j2 i& c# n h& h4 Abdi i2c-adapter misc scsi_device usb_endpoint
8 f& O, K; n: d% Pblock i2c-dev mmc_host scsi_disk usb_host+ U- U+ [* B5 M6 u3 C/ u1 v' T
firmware ieee80211 mtd scsi_host vc
# A, F w$ G* c, \: ~firstdrv input net sound video4linux
% _! n* [5 X) ^' [% ngraphics mem rtc tty vtconsole
, {) Q- S' |4 H" {6 ?% g[WJ2440]# cd firstdrv/
/ G: R, _ j1 I: Y& r[WJ2440]# ls
# u6 r7 F/ \& }8 Z' D& w3 f4 Axxx1 v& Y* U( _( ?0 x
[WJ2440]# cd xxx/
( s h1 n) |. O7 W' [( V# q[WJ2440]# ls
6 u+ _2 Q9 j2 ^0 b! a, \dev subsystem uevent
& Q# X# a! Z$ j4 }[WJ2440]# cat dev
; e# O7 ?6 C. n' x: ?252:0, H; k4 n) z# F* G3 h
[WJ2440]# cat uevent
$ |5 l* i: z4 a! bMAJOR=252" F6 A7 p' c" O; P" B# J# ~
MINOR=0$ U n/ N- e( @& Y
[WJ2440]# cd / 6 h$ k9 j$ J2 s, @) `& L
[WJ2440]# ./first_test
& b" U! b/ Z+ n" C. J9 Lfirst_drv_open% B0 }; f G1 y' L: R8 t4 R/ [
first_drv_write
6 |* \8 o6 J9 i9 c[WJ2440]# : ^8 N, P7 U/ S' X
& t1 O: S3 l7 V; i5 E/ e
' ?' z" C( f$ H0 c- F! [1 L5 |& D4 y% s! c) o; k
f) O n+ o$ A# i2 q |
|