|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
上一节中,我们是手工创建设备节点,大家肯定也会觉得这样做太麻烦了。
- q# ]6 A) x, Q) ?
: X/ l* r5 Z6 p9 b# ?3 K上一节文章:) j( c8 m& S5 D' v
问:能不能让系统自动创建设备节点?7 a+ V$ C6 J# {6 p, x
' r, L9 } x4 H; m) k' o6 h2 G
答:可以,linux有udev、mdev的机制,而我们的ARM开发板上移植的busybox有mdev机制,那么就使用mdev机制来自动创建设备节点。. A4 w* Z4 j6 O4 ~- w
. Q2 |7 W: C& |" D8 l问:文件系统里,在哪里设置了mdev机制?- ~# ]: ^) l3 F+ N! q) q
( y8 G+ S7 D! g7 |答:在etc/init.d/rcS文件里有一句:
; M1 N+ V+ N* }3 S
$ I9 @/ e- ~ a, X7 |echo /sbin/mdev > /proc/sys/kernel/hotplug* r2 n' ?! ]. l3 u/ W5 ` G8 F: ?
; N; X. @- j( u# d1 Z问:在驱动程序里面如何编写程序,让系统自动创建设备节点?1 H$ r3 N7 q$ o0 Y
3 j4 |8 s8 V5 a' ]3 n5 r答:首先创建一个class类,然后在class类下,创建一个class_device,即类下面创建类的设备。
5 m; _ B% f" J; V1 H
* A3 M) w, y3 m1 J7 t+ {) r: f4 Y
. f l5 }4 o3 z# t
0 z+ V; n( z: u+ H3 v4 ~( V `9 G, `: C详细请参考驱动源码:! s0 \* M6 o& z/ L `
! k9 n2 [- u. \3 i2 J
1 |- E7 n! B/ t6 N, K, l#include <linux/kernel.h>
% l# I, |0 D8 F* m _' P#include <linux/fs.h>6 x" c9 u4 H1 w, C# S8 |" z1 V8 y
#include <linux/init.h>
# p7 I% Z1 F! k#include <linux/delay.h>; Y% W( _# k" n& H( B* Y" z
#include <asm/uaccess.h>+ U- q3 L" j+ ^) s0 L' [/ n) b1 g; }
#include <asm/irq.h>$ c: v( s/ h3 @7 C5 w4 W) k
#include <asm/io.h>
8 V( ~7 O# p0 q2 z( O6 I5 L6 K9 t+ M#include <linux/module.h>6 e, N: V$ o% m( |+ @/ E5 @ G
#include <linux/device.h> //class_create
- m( l. ^& W# _3 J# r" p+ s5 q0 M; g& J
static struct class *firstdrv_class;0 v8 e/ k3 m' B
static struct device *firstdrv_device;/ o6 r! Y4 m0 i* Y" H, R' @
. X% _2 ?( r8 Y9 I
int major;( x. O5 S% Z7 r! z* W, K* ^* H: f
static int first_drv_open(struct inode * inode, struct file * filp)& r7 ~1 e# J$ ]& ~4 O7 t A& _
{
$ D1 G% y+ ^; M5 L printk("first_drv_open\n");7 ]4 p3 i6 ^8 G
return 0;: C) g* D8 \' d8 J% B$ [
}- z; {* z$ \( u+ D$ K
static int first_drv_write(struct file * file, const char __user * buffer, size_t count, loff_t * ppos)4 N$ K# Y/ B! G/ W; F
{
# Q* t' u: W8 B- ]7 H# @: U" o printk("first_drv_write\n");" n$ M' g) L: ^: ]0 J, \2 l' z
return 0;, j, z8 H: L T$ h- j& z' B
}0 `3 y$ P, ?5 [% C2 V
5 K8 j% T8 E- d/ J/* File operations struct for character device */6 ^2 t& U/ C& w. w
static const struct file_operations first_drv_fops = {, B, h2 v8 w+ p" P0 S4 g) X
.owner = THIS_MODULE,
) ^: B$ D9 G3 v* J | .open = first_drv_open,
4 i/ N2 Y( k5 M9 v .write = first_drv_write,1 t/ ^5 l/ d$ s$ p
};
) m. [4 R2 I, i( M2 V% \; O: V4 ?5 o4 u1 w+ x c& V, W
/* 驱动入口函数 */6 m) i. ^9 `( z) G
static int first_drv_init(void)
! {5 u# a0 p. O' S{
$ E1 ~6 c9 x/ h7 z- y /* 主设备号设置为0表示由系统自动分配主设备号 *// `5 q" {' w; q+ q5 X0 s
major = register_chrdev(0, "first_drv", &first_drv_fops);
+ k/ P# ?$ p1 O. y. N& g+ G) } q4 M- P3 t, q
/* 创建firstdrv类 */
; A3 x+ O3 ~. H6 D9 _7 C. I firstdrv_class = class_create(THIS_MODULE, "firstdrv");: }8 l2 l. ]+ Z0 b8 Y. L( G
% L: z# n2 L$ J) ]! V: [ /* 在firstdrv类下创建xxx设备,供应用程序打开设备*/. x, J% d$ |5 |5 b& l0 I+ R+ \$ o
firstdrv_device = device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xxx");
3 S: @) b3 b$ I H( m* \: Z8 V8 a return 0;
4 r" r' {2 h( u! d; {: E- i0 \0 @}
- D% Z0 u- z/ _/ e* T9 [7 C/ \( c" c! _! N- D) o
/* 驱动出口函数 */
- F9 C+ B8 W+ T% E! ostatic void first_drv_exit(void)
' z* r3 B+ J# V) m{
* e" Q* j! W6 q8 H* s2 X% p6 h/ l; ?5 I) s unregister_chrdev(major, "first_drv");
; n$ P" k a/ J2 @* E6 l( F device_unregister(firstdrv_device); //卸载类下的设备
6 V4 w' j3 g4 ?0 w# Z" I% q4 j* A" P$ u class_destroy(firstdrv_class); //卸载类
" h9 f1 D2 d6 E' @ H) a* a}$ H7 M' K( R2 P! P5 c3 C$ N* u
( Y# j0 r# \4 n2 C5 I9 d( h& v$ Fmodule_init(first_drv_init); //用于修饰入口函数
1 H; \$ N9 Y! ]& cmodule_exit(first_drv_exit); //用于修饰出口函数
1 T" g0 m2 R% n8 c; d
7 z/ ^( S. ?: l$ l, u cMODULE_AUTHOR("LWJ");$ u& A( }0 |1 J# }+ n! C; S
MODULE_DESCRIPTION("Just for Demon");9 V K' @1 A0 E) I* c; K0 p$ h
MODULE_LICENSE("GPL"); //遵循GPL协议
" o) e+ v' C, F. i2 Q& _4 f( p7 G4 z' o5 P! h) Q1 z
4 C8 i6 g3 Z3 [# y9 C7 R# U! m3 a( G
注意事项:) p5 P. L. C1 u" y
1.因韦老师使用的linux版本跟我使用的linux版本不一致,头文件路径可能有所变动。
4 T, J0 w" ]; F. b. Q- n/ _
; ^7 a( f7 S" B& |7 n) i2.使用的函数名可能也不一样,例如:
+ A# `' |* _4 C* D
# \8 N. T; [9 q$ D" j6 M韦老师是这样子创建类和创建类的设备:
; S( ^2 Z8 H/ |0 {! X8 H" _3 ~# K6 ]* g9 I" b" v
一、定义
( H- J9 k# P* Y6 ~8 N; \+ X9 E/ V& Q3 H+ v) [" p+ _" y
static struct class *firstdrv_class;: Y7 K u, W; m1 K. S! e# a5 N
static struct class_device *firstdrv_class_dev;
$ ]+ A6 @4 ^% s) Z3 R! w% M+ k9 T
二、入口函数里
. E$ i0 h5 F) p3 {; ]
2 a% t6 Z# ]/ x: b5 yfirstdrv_class = class_create(THIS_MODULE, "firstdrv");
" N( q& d2 y) n6 R: O: ofirstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz"); /* /dev/xyz */% C. P# g% i" K) Q# g' {8 |% A2 d
/ D/ F) C4 P/ n) n% e% a$ S
三、出口函数里9 c7 i. c ?3 l; `
. d6 c. S1 s4 t' n* h2 X% ?
class_device_unregister(firstdrv_class_dev);3 K- Z3 s. y' o/ E
class_destroy(firstdrv_class);
6 W* y6 D& {1 I8 B, j2 S# A6 Z: e+ I( D& {, g# M
; g: f6 q1 T/ l: u& Z
" y, d3 b3 p' y, c而在linux2.6.30.4里,并没有class_device_create和class_device_unregister函数
, k* }0 r: f/ S; d$ g
3 w ?6 s$ N: f5 f0 V3 t2 K我是这样子创建类和创建类的设备:
8 b) M# Z! G% x) Z; R
# E# v5 B; A/ p/ k0 y一、定义
9 o2 `! L9 u6 T1 h( Y0 p- @7 Z" A0 f; y/ W# f# [; e3 V8 j; M
static struct class *firstdrv_class;
+ r) G" i0 @) w- Q1 Istatic struct device *firstdrv_device;" }, Z7 w' D2 V) V! o$ z1 [
! `% |6 B0 J. j; |) V, v
二、入口函数里# M: `# v+ o$ R& h
0 ]( M1 c4 C f& J! Y( A7 s/* 创建firstdrv类 */7 ~2 C" A# K. w1 I+ C' u: f
; k' j0 j; b: Ifirstdrv_class = class_create(THIS_MODULE, "firstdrv");
9 c# L/ Y2 U" ]5 n* l
* `: M9 y2 _8 T5 g* r% O8 p- Y& s- k$ T6 W- g
/* 在firstdrv类下创建xxx设备,供应用程序打开设备*/
; w' B9 {$ o% F! H: a% s/ tfirstdrv_device = device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xxx");" k$ [, I1 b. v. C. @1 X% j) M1 }
3 \; d: m- f- @ U三、出口函数里) o- h2 w4 h5 |5 k# e
/ v( x- ~- x r) e" ]" Kdevice_unregister(firstdrv_device); //卸载类下的设备
* B8 O T: o: x/ l+ ~class_destroy(firstdrv_class); //卸载类8 d7 b" }/ E5 M) t
0 m9 E' }. [' p+ e Y6 ^
d v5 P l( G
6 N: A+ W. P2 M$ i/ llinux2.6.30.4使用device_create函数替代class_device_create函数;
" C- w. n/ Y7 |& H, ~
% }8 ]! W" ]" a$ I! @使用device_unregister函数替代class_device_unregister函数。, u1 @5 a5 \6 H* A$ f/ D$ |
% y5 ~8 I& S! _
8 L5 P2 C+ r2 Q' ? S6 S6 R, W: f1 g3 ^! b- @8 Q+ a2 `
测试程序和Makefile没有修改,故再不贴。
0 B0 f" u2 e$ W* m& ~7 E; Q; D' q- t# U
测试步骤:7 z9 d5 S( B% c6 s( G- v2 k9 x6 F
. w: k3 q9 @8 w/ u) @$ x" A# L: Y7 K* q, b
[WJ2440]# ls# |# u I- E+ _, \
Qt driver_test lib root udisk
# V! b6 {7 z1 \; e4 {6 l" ], ITQLedtest etc linuxrc sbin usr
1 h3 H3 o0 y6 y* l$ gapp_test first_drv.ko mnt sddisk var$ |# Y8 o9 {6 g1 V" g
bin first_test opt sys web
- ]- x7 E" e; W8 z* X! Zdev home proc tmp; g& p' [" Q% w; P' ?- |1 g; p
[WJ2440]# ls -l /dev/xxx, O2 T ?' o0 e
ls: /dev/xxx: No such file or directory
; d* B% D1 [, l2 w2 b/ @[WJ2440]# insmod first_drv.ko
7 d! w5 o" [9 k! U. N0 m) }3 k[WJ2440]# lsmod# }1 n+ j* T5 e4 m
first_drv 1912 0 - Live 0xbf0000000 e: P; M0 I3 K4 Z
[WJ2440]# ls -l /dev/xxx
% w0 f V- I/ A% H2 y5 }) ^. ^crw-rw---- 1 root root 252, 0 Jan 1 23:17 /dev/xxx3 H! s* Z' a0 P2 K
[WJ2440]# cat proc/devices
, z( s3 D" W3 b( GCharacter devices:
) C8 e. u' ]; p; E7 b1 k1 E 1 mem
' n" ~* X6 x7 D/ b. Z 4 /dev/vc/09 I7 A9 P: S. a m6 W: v
4 tty
4 b5 o8 \3 k" N/ I& G 5 /dev/tty
) f" q$ F9 F1 [ 5 /dev/console- S/ N0 [/ Q4 y! R
5 /dev/ptmx
4 J' [: ]3 s: Z. l 7 vcs
" ]+ h U' |2 p. `3 d2 } 10 misc
* S: h1 A0 `- o: c 13 input
B; B1 d$ a4 g3 W; g: g+ H' b 14 sound) ]0 Z5 P, C1 O4 W [& P( w. N
29 fb
) N. \- @# D3 K% t1 x* H& h9 C0 | 81 video4linux
) G9 E9 Q8 T& |) f 89 i2c
0 y' g6 {( v6 R- L, N0 H! F7 T- ~ 90 mtd
% r; ?4 l. \5 n3 X4 B6 b( D' M$ u2 u116 alsa
/ V% \( L( j/ w% |) h( l128 ptm" P$ ~; l) ^% X3 O' K
136 pts: j- O$ Q* a, t! b! y
180 usb
" ]4 U! {% c4 B9 V, V( i: g188 ttyUSB
& u) _7 ~! x# }' P) {: X189 usb_device; R% d; n1 C4 [' D! ]9 e
204 tq2440_serial
* k5 @$ M- i) j$ h$ D7 I' S* ~' N252 first_drv
: z5 I: c* P6 b; k3 Q4 i253 usb_endpoint" {0 d' `5 f8 g
254 rtc) h/ L3 n7 _. f0 I* F6 @! s) i$ G6 @
% i8 f# r3 @: GBlock devices:0 K" z9 Q4 `5 V9 r
259 blkext+ H' [+ V: L; B/ e u! I" R
7 loop
0 l9 Y3 d8 `. r, ` 8 sd. x* W8 @1 a6 w1 a+ {
31 mtdblock2 Z, ]7 \/ K4 [" \6 e; _4 s" L
65 sd
! S! v7 I; z: x F | 66 sd3 f- T5 i# p: c
67 sd: i5 v$ Q2 n0 h$ i! Q) ^: @5 h
68 sd. f/ x- B9 n5 z
69 sd
: ^% h$ Y! A( ?9 ] 70 sd# u0 y8 k( g; K; H+ e0 C& s" m( j( \% u
71 sd
2 |8 Y( N& v# C1 d128 sd. x5 ~4 G' N) _, d' a$ X/ O- J
129 sd- Q3 V# e$ F' J- E) n
130 sd
9 q! W7 @9 K' @. ?131 sd8 v0 I1 ~7 ~% x. [% J0 h' ]2 ?) X
132 sd( K. K: h, ?$ B7 Z$ n) @
133 sd. T- s" Y+ G6 B0 f9 D ?& |
134 sd
8 w2 @$ W* \6 s& [135 sd
5 Y4 [3 P) w" f# i179 mmc9 \$ g" ~) o. R* f7 H( n" Y2 X7 d
[WJ2440]# cd /sys/class/
6 W3 c" l/ o5 r0 }( N2 q- O# m$ r[WJ2440]# ls
* E7 B8 Z7 [* h/ @7 Hbdi i2c-adapter misc scsi_device usb_endpoint4 d+ I/ W+ ?0 ~
block i2c-dev mmc_host scsi_disk usb_host; ]5 W, Q' _ O1 d% U
firmware ieee80211 mtd scsi_host vc- k3 T) ?) D. B2 l0 {) m* l# x
firstdrv input net sound video4linux: T. { A& L6 r5 |" M6 V
graphics mem rtc tty vtconsole: f* X8 v( P7 W1 A
[WJ2440]# cd firstdrv/
5 r, i3 F. Y: C# L+ H' y. x[WJ2440]# ls
/ C. n6 t+ _ ?- P$ axxx
- ?0 o6 G3 z! D[WJ2440]# cd xxx/
; ]" P& |% u! B. @5 C5 O4 l0 r; u3 \[WJ2440]# ls
( e! z% W$ C2 `$ L/ Y* Hdev subsystem uevent
I6 e# h" q+ J7 q+ H[WJ2440]# cat dev $ }( H4 U+ ^- I
252:0
* ^" X5 D' Z# K; [2 w: c9 I7 D) S[WJ2440]# cat uevent
" w& f; I: I- I9 QMAJOR=252
G1 S3 {" m+ @* o0 KMINOR=0' a# q* A/ k: i
[WJ2440]# cd / + T. c: T, a& Q( g
[WJ2440]# ./first_test ) m- e3 }, G' o/ R
first_drv_open7 T/ k5 r' }7 `
first_drv_write
4 @% c( @' O7 p" `$ f2 A$ P5 _[WJ2440]# & i! W1 J& W: O' H
' I/ J' I% H1 b6 p: q4 o+ ?1 ]
! ~! w/ N, {" F9 W
5 t1 j u8 W: D( p+ _ h# H
|
|