|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
上一节中,我们是手工创建设备节点,大家肯定也会觉得这样做太麻烦了。
. Q5 U3 l8 Z) {7 x$ {& Z' |) C; W9 i, b2 ~ p- ]$ d$ C/ _
上一节文章:: g. W2 j( Z) F6 X# L' W( ~2 ]
问:能不能让系统自动创建设备节点?3 P2 t, h! K) P9 K, Y/ Z: m6 x
/ I; X% k; c; A* V# p! d2 A$ b
答:可以,linux有udev、mdev的机制,而我们的ARM开发板上移植的busybox有mdev机制,那么就使用mdev机制来自动创建设备节点。" u+ C5 `9 l) V+ x/ c
# }3 ?* p# F0 v5 o: E4 D8 z6 J
问:文件系统里,在哪里设置了mdev机制?
8 [; l0 q: K/ M
6 N; p; }: D' K/ a) ~答:在etc/init.d/rcS文件里有一句:+ ?' ]# q4 ^2 S- ?$ O( G
# d7 H0 X' T3 y; a* Mecho /sbin/mdev > /proc/sys/kernel/hotplug
& h2 x5 X, Q' Y" z1 K
4 P% B" ~. Q5 r. _3 T2 [问:在驱动程序里面如何编写程序,让系统自动创建设备节点?4 G' M7 d" B G. n
. _: g4 x9 t2 m/ B' y& q
答:首先创建一个class类,然后在class类下,创建一个class_device,即类下面创建类的设备。
8 I# V, T2 ], |+ s
% Z/ `5 s& {7 Y6 j: V- { @- h+ L6 |
N" g1 u0 N# {8 n% T# u0 W( |1 U; h2 W2 Z3 j: o" K' u
详细请参考驱动源码:
! W0 D, V# a1 ?0 J# G
3 j k/ X: {* Z' ^6 e7 }4 A$ ?+ L1 s) f( X4 j! ^' P( W
#include <linux/kernel.h>2 ] ~8 {2 G- Y8 a+ k
#include <linux/fs.h>: V" e/ S5 V3 y6 z: [7 U3 G
#include <linux/init.h>
3 g" `4 |+ d: w7 A( c a#include <linux/delay.h>
( ?" o" I5 s, {5 X1 E; h- Z#include <asm/uaccess.h>* w2 E! X$ W5 o+ q
#include <asm/irq.h>" V. ^& I5 a$ z4 y& F
#include <asm/io.h>
1 ]# E; v. V' ?& I( T# ^5 k#include <linux/module.h>. k9 H4 X( h; B. C+ m
#include <linux/device.h> //class_create
0 |0 |+ l0 B% Z
* h( g9 o7 D% B. K9 s* p9 vstatic struct class *firstdrv_class;3 e" k+ ~0 `1 g) p' M
static struct device *firstdrv_device;, k, i, {$ Y1 ]4 Q
$ D |) U& Q8 ?3 o2 ^* W: @
int major;0 Q$ d$ G0 r" e/ l% `2 B
static int first_drv_open(struct inode * inode, struct file * filp)* N9 K& [/ W( T/ e
{& y) l; \4 c4 K
printk("first_drv_open\n");
4 S7 W2 h1 q3 ^& \! ^: W) G return 0;4 ]" z: Y5 d* f3 o
}' T( h& e1 A- A6 H6 ?9 s
static int first_drv_write(struct file * file, const char __user * buffer, size_t count, loff_t * ppos)- a* w0 W/ O( {( G
{% G- F( \: Y# f
printk("first_drv_write\n");6 ]4 w' N9 |( d" U! H
return 0;9 m$ i o" z+ H: Y+ p5 W
}' u" S5 d# Z* C+ _
1 y, w; \/ P8 K/ M" k* n, A
/* File operations struct for character device */
% Q" K1 v& D, `0 ~( ]! y8 ^static const struct file_operations first_drv_fops = {. E# O. l! q: R( f! t. K/ u8 A
.owner = THIS_MODULE,
$ N3 a* Q+ p% }' H; i6 v+ J& N R. u .open = first_drv_open,
6 H2 {% f0 a& J4 M0 }* d: h2 P .write = first_drv_write,. H3 B6 T- t: b% g/ T
};7 w# Q. i4 t+ v* S6 k- n0 Y
7 F4 H w$ K- n! n4 }; G! Q0 W/* 驱动入口函数 */
' R0 }4 b2 z8 f! I) [1 j- Xstatic int first_drv_init(void)
/ R) H2 l+ B2 w6 q# V9 _{
* N/ F) C+ s0 |$ i. O! L/ M /* 主设备号设置为0表示由系统自动分配主设备号 */
2 P* B0 w4 p' s! | major = register_chrdev(0, "first_drv", &first_drv_fops);
2 ]. g3 x" [0 P o- x' b2 Y, x) _2 P: M- O; |2 `
/* 创建firstdrv类 */
, y9 s2 T9 q/ a! P' @1 k firstdrv_class = class_create(THIS_MODULE, "firstdrv");6 [ e. O* M: o1 ?, U
8 |7 Q3 F+ X* L$ x \4 Y: J' W, g
/* 在firstdrv类下创建xxx设备,供应用程序打开设备*/; v; O. Y1 R3 S/ n4 i' p |
firstdrv_device = device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xxx");
/ H% N! h% P6 x' D3 c8 p return 0;
6 O4 R/ z! P) p3 U4 p0 J}; \! u4 ~$ Z* T
; H( g: d0 G/ s" }; |! y
/* 驱动出口函数 */
7 A- S! q4 D' { Ystatic void first_drv_exit(void)0 S+ {8 G- I8 Z& c& {8 `! v
{
8 s6 l- m8 ?. p$ O: j( U unregister_chrdev(major, "first_drv");
, [: E0 y3 P* s" g& [" a device_unregister(firstdrv_device); //卸载类下的设备& N& T8 K% S. |' z
class_destroy(firstdrv_class); //卸载类1 V7 {, I" b7 E! n( I- _+ @
}# |2 g7 q1 h. c$ C* }
, ]& o O0 l1 r5 C1 r7 E/ l
module_init(first_drv_init); //用于修饰入口函数' W% F( ]8 A1 P b2 D# o" g
module_exit(first_drv_exit); //用于修饰出口函数
7 M) j0 o; L" u( f, h; h7 x( ]
% U! c( Q! Q% o) z4 l5 J$ b$ QMODULE_AUTHOR("LWJ");
/ k$ r: }# g/ Z: `! ^- b" XMODULE_DESCRIPTION("Just for Demon");
/ U, }0 K# f6 }: Z- b' K8 r' OMODULE_LICENSE("GPL"); //遵循GPL协议7 T0 g, Q& ~/ K. }
( B" K2 V& H# @% _4 ]* O, w! e: N" G- |( [, T" ~0 ^
注意事项:) j7 o, L0 N- Y" S
1.因韦老师使用的linux版本跟我使用的linux版本不一致,头文件路径可能有所变动。6 c7 {& i* O/ a; G
8 V5 N# q4 D+ U6 I2.使用的函数名可能也不一样,例如:
6 l7 u9 M2 B' j# M0 D6 p. X* \( U) n' w
韦老师是这样子创建类和创建类的设备:3 j. j" K8 j R3 r
5 y4 S- a7 e% q# E
一、定义# [3 Q8 P0 v, r( z/ ?4 E5 O8 k& _
* ^4 ]! Z0 L% f- P3 G
static struct class *firstdrv_class;& o4 R7 P) A" f& i
static struct class_device *firstdrv_class_dev;
# y3 D; K5 Y/ |; S1 y
) @, y* \4 m* _1 b3 Z二、入口函数里
5 a# X: I! n; a& V
+ ?3 p7 `7 A: L9 D! o5 afirstdrv_class = class_create(THIS_MODULE, "firstdrv");8 x" @7 e- z, v+ s" D$ u' e$ I/ a
firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz"); /* /dev/xyz */+ s" a; F; [6 ~4 c7 t. m8 n7 L
% W3 b" X& p! }- q. A" M# D' A
三、出口函数里
5 d6 e1 ?& ]$ W, p8 r# r7 R7 p) @9 U: L* o
class_device_unregister(firstdrv_class_dev);5 H% I/ H% ^+ q; }
class_destroy(firstdrv_class);. \# ^9 t0 C& p& X
, K# R! P3 s! K4 ]
# g0 \7 a; [3 Z9 I( y
$ w/ c* P# U5 u5 B [( f: T/ ^+ \而在linux2.6.30.4里,并没有class_device_create和class_device_unregister函数
4 {4 e1 j/ W: }3 c
3 b: S3 o6 q: A我是这样子创建类和创建类的设备:
! a% @3 I1 ^- e' v0 I( A4 N' y. [, p4 q; p6 }& s& I$ i' {+ J
一、定义: e0 L+ S+ A3 [: |6 E4 A
& W) X% h( }5 Q& p# e2 A, j9 {static struct class *firstdrv_class;
' y' O1 p' X/ m- K. B# n9 Ystatic struct device *firstdrv_device;+ `) |% r) N, Y( W7 x1 ?
* O- @" A1 Q% w7 Y- c1 D二、入口函数里
I: U$ t# N" }7 F
- b$ n1 ^2 ^0 v6 [2 q/* 创建firstdrv类 */
( i1 z6 M- z( V3 Q) k2 u, ]& \* y1 @: f% c4 J
firstdrv_class = class_create(THIS_MODULE, "firstdrv");
9 m3 C' Z- b5 A/ x
0 U2 \- t3 J) q2 D; v l; e( p9 A- M
5 K1 h! `0 q1 p( c* t/* 在firstdrv类下创建xxx设备,供应用程序打开设备*/. d1 k0 I; `/ J+ t
firstdrv_device = device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xxx");4 I. n, C! N' H7 m3 N
6 R0 ~1 D6 \+ e) s( r三、出口函数里
$ D( }) |4 {/ L7 M
( L% y% i; x7 d) r/ H/ R" L2 hdevice_unregister(firstdrv_device); //卸载类下的设备% t1 V E7 X' Q H7 d
class_destroy(firstdrv_class); //卸载类
8 I% C: ~& Z* R7 j9 b7 P
3 c2 c& s7 v% {, t
4 E% n. P' q3 q7 T& `: s+ L
. `- w1 d5 O- p" Nlinux2.6.30.4使用device_create函数替代class_device_create函数;; l. c/ v+ b# M) O+ E7 ^& O! H0 }* t- k
9 v' f1 {2 i- _, s3 B. ~
使用device_unregister函数替代class_device_unregister函数。
9 q! x0 e% w. k) g5 S! F
4 T# U" @8 C, f+ T+ P0 g) `4 n7 S/ X: Q; K9 @8 y
. `9 T4 s& p! X, ~
测试程序和Makefile没有修改,故再不贴。
. |) d% h7 j* N, _3 G3 \6 C& u: a S, g
测试步骤:
, U: G% X R. T4 S) F O- E
8 t. W2 ~/ F' B* a2 Y4 c5 M7 M, I/ U# U) a* `7 v' w
[WJ2440]# ls
1 m" {8 w8 N5 y* { ~Qt driver_test lib root udisk# n, Z; u3 n* w5 x2 t
TQLedtest etc linuxrc sbin usr
0 p3 f; N+ G* d, Wapp_test first_drv.ko mnt sddisk var
5 E! c$ }# x7 A3 jbin first_test opt sys web6 i* i$ m* h: i0 |8 s
dev home proc tmp- H, S$ K6 }5 Y* k1 H" r& x
[WJ2440]# ls -l /dev/xxx
( C* } B' p5 P' U4 Qls: /dev/xxx: No such file or directory
' i5 W: t) i; f- e' k& j1 U. I% h[WJ2440]# insmod first_drv.ko , E& O9 U' u; d. p+ o: E& X
[WJ2440]# lsmod
* u0 Y; M% K8 j* N3 Y6 G9 Pfirst_drv 1912 0 - Live 0xbf000000
6 M0 ~ \% N( H% d7 E/ v[WJ2440]# ls -l /dev/xxx
2 \* M1 _; h) P- F/ kcrw-rw---- 1 root root 252, 0 Jan 1 23:17 /dev/xxx
g1 t' f$ F3 E/ Y& s[WJ2440]# cat proc/devices
( Y6 ]) q: U' a5 B- `Character devices:
+ B5 H+ d5 `( S) t 1 mem
* b J$ }& V/ c2 z7 A 4 /dev/vc/0
+ ^8 _* q2 V- Q' a 4 tty
) v( S8 x. c3 o2 k6 X 5 /dev/tty/ j7 R5 S" F% i# K; a+ ~& q
5 /dev/console5 q: A6 q, J7 n1 y6 a; h- F) f
5 /dev/ptmx, O9 Z1 I1 w; p6 b4 Y8 k
7 vcs
2 R$ S6 t2 x$ s/ U0 J+ M 10 misc5 l, N8 ?7 K( X" ]1 Z$ i+ v5 N2 H1 @
13 input& s; v( s& @( z6 u( }, O
14 sound" S& `* G$ C9 i& ?; b# S$ D5 I! m; H
29 fb
6 B- Q5 O6 O8 T% p 81 video4linux
5 E; \3 f* Q1 ]5 e2 x 89 i2c8 e+ p% l' ]! r! p% k `' h
90 mtd; p0 J* E/ w0 F2 T
116 alsa
. }7 t- Z( G, {+ a128 ptm
2 Y0 x; ?0 K. o; L& `136 pts8 ] o$ z {- [( v \/ J z
180 usb# _+ K' k4 o+ _
188 ttyUSB
0 M8 ?' j: D& j3 \) E189 usb_device
" J4 d; y; u6 n" A `3 R204 tq2440_serial
* ~0 {4 V8 ~! k, Q$ E, W, Z252 first_drv
0 K* l4 G8 j( l& j0 M253 usb_endpoint$ Z& q/ Q) s" B+ \4 M
254 rtc
' Q* I: l% ^5 g; g% ?* C# v, K& z- Q9 D. ?, T: c, ?
Block devices:
5 }- g% w4 E1 m1 ^# Q259 blkext
7 J E7 `- u( w 7 loop
( T. `* J3 i( S; q" @ 8 sd
- T5 v/ i( | z, O 31 mtdblock
, w7 {1 H& w' Q3 c& k3 d 65 sd
L' V$ N/ \' N5 _2 v; c 66 sd
/ R: M, I" F4 I2 g& Z 67 sd5 p2 ]% w( ]( Z& v3 ^9 y
68 sd
' z2 t8 P' z4 q0 `$ ?% l: Z2 Q' v0 k 69 sd) M" C1 l& X) ~( v
70 sd
; f2 I( ]. }- C' z4 o 71 sd
9 F& [* V2 @4 l8 h7 t/ V& J128 sd+ h8 i- O5 D6 G/ }) a+ A
129 sd' {, Y5 M3 [, v3 G
130 sd
4 V: G8 f: e$ m1 o, _( Q |5 p! I131 sd
/ h" `5 h H$ i0 ^2 a- A/ }6 R132 sd
A) m3 D% i/ R1 |. I133 sd! f. P; ^* q q# s6 V
134 sd& L% \ _$ s3 f* I
135 sd
* |; i$ S& ]) U* i) f179 mmc
( D) Y5 W8 y0 G[WJ2440]# cd /sys/class/
8 A: f2 e! q4 Q3 E( C- K& X[WJ2440]# ls
2 j0 ]$ ^6 f E4 Wbdi i2c-adapter misc scsi_device usb_endpoint: [- L: a5 ^( B' V1 m
block i2c-dev mmc_host scsi_disk usb_host
* M- n0 b- [9 Q% tfirmware ieee80211 mtd scsi_host vc/ e8 M0 g. F# Y ^0 Y7 e, H0 S
firstdrv input net sound video4linux Q3 V, U. d* ?% Z, r* W/ p, F
graphics mem rtc tty vtconsole
$ A% l& y! [% V3 {[WJ2440]# cd firstdrv/0 U* ]" O% L+ s, S9 n: i4 g3 y! ^ i9 ^
[WJ2440]# ls5 o! e* k$ {: O+ f# F
xxx# L, y c+ J y# C M+ |/ Z
[WJ2440]# cd xxx/' T- g5 q( c2 Q' s0 T
[WJ2440]# ls
! s. z$ W3 W1 Q$ B) l) O4 b9 idev subsystem uevent
) t/ o7 g, m2 @( {& j8 [[WJ2440]# cat dev
7 \! ? j3 W% z& H2 ~0 u- _1 y) q252:0
# Y4 i/ d* x5 m. V: Q- ?$ V) p5 G[WJ2440]# cat uevent
( K2 F% ], K$ ^6 [MAJOR=252
* B% C% [8 c# l X% s6 L$ }MINOR=0* {7 F |3 ?, n& O4 ]# j9 I# ?
[WJ2440]# cd /
, x: W4 v- u3 T1 E% m9 I[WJ2440]# ./first_test
7 N7 Y- s+ s* u, I4 mfirst_drv_open% B- ^4 i1 ?* a9 F. b/ k
first_drv_write
, q" k, {7 l8 @2 P0 z[WJ2440]# : ~ B" M1 o& f* L
( d- a( i! ]! e! L$ o1 K$ M& S# n/ C
@3 a' x) ?, j6 b) q& h/ q6 N
|
|