|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
上一节中,我们是手工创建设备节点,大家肯定也会觉得这样做太麻烦了。
) c+ q, X* {+ ~. L$ f6 r
C: y6 }' k( v$ o, p上一节文章:
( H3 D. p0 `- Y问:能不能让系统自动创建设备节点?
' Y( T3 ^' X3 @/ E0 R3 v- t0 \5 u' S5 A" p1 G6 b b
答:可以,linux有udev、mdev的机制,而我们的ARM开发板上移植的busybox有mdev机制,那么就使用mdev机制来自动创建设备节点。+ I; M1 Z2 ]5 c; ]
- y4 o' K7 o3 [" C. y问:文件系统里,在哪里设置了mdev机制?
, a' e, p! c9 p5 O5 ] }8 k: B8 g& P7 H# s. D% l% A9 F
答:在etc/init.d/rcS文件里有一句:: L" G; A: B& L
1 W5 \: `8 U2 d: {, Hecho /sbin/mdev > /proc/sys/kernel/hotplug9 \ e5 ?; r8 q4 X$ a5 R
. R4 q/ N" F7 e+ c7 n1 Z
问:在驱动程序里面如何编写程序,让系统自动创建设备节点?
5 [" k, Z' r6 U' {. s1 R
+ O4 j' ?' v! ^! G1 [# Z- |/ u答:首先创建一个class类,然后在class类下,创建一个class_device,即类下面创建类的设备。
& W: D$ m' X, S( S8 K/ X1 \: \1 O
' {, ]% G. R1 B3 T* X& C: F3 P
, E; x! D3 g! H1 f/ b1 r1 M: Y8 D* F" m& z
详细请参考驱动源码:
/ K' ]) ]$ ~+ x0 g% X- b* v
" w/ c2 t' N, u+ [& Y, b0 |5 ~! c8 o8 m2 N% L3 j, V
#include <linux/kernel.h>0 d+ q9 v6 W( e" ~7 m' y( m5 d5 X! R
#include <linux/fs.h>
2 f# \& ^0 _$ M- x#include <linux/init.h>
6 n8 X& K& O1 F4 V2 Q, I! O* p#include <linux/delay.h>% ~8 N. ^) `& A# ^. d9 q, K: J
#include <asm/uaccess.h>
4 |0 J. W6 A3 B6 _. V/ q" a#include <asm/irq.h>3 T2 H! E# r! E; D" q2 b5 y
#include <asm/io.h>' F. r7 U. U* u1 _- x( @/ ]
#include <linux/module.h>
& Y" z- g$ _: R: r1 j& k+ q8 l#include <linux/device.h> //class_create
/ e$ b6 V9 n& p0 r3 `" s* V
3 M e% Y5 R( H9 j. u' |static struct class *firstdrv_class;& I t& J0 H& j% i# I& G
static struct device *firstdrv_device;3 ?8 g: ^& [3 Y
8 x# A1 V0 y5 R8 @3 t0 }int major;
' ]' B0 a& n' nstatic int first_drv_open(struct inode * inode, struct file * filp)+ M. n7 E* _/ V( L8 H3 m0 { `
{8 s0 k3 ]. _& q! Z7 Q0 K
printk("first_drv_open\n");! B6 W) P( M: D; H
return 0;
, } V9 O/ I# \6 p6 K) H# T9 H}8 L7 n8 c" e E1 b: R
static int first_drv_write(struct file * file, const char __user * buffer, size_t count, loff_t * ppos)
9 B9 u. o1 b: i2 B! k( z{' r5 O, U( ]- {, h( }5 U+ f; ^9 ^
printk("first_drv_write\n");% R. g# U; v d5 C
return 0;
3 F" j$ _& O! L# D6 v}7 h4 V7 Q R1 {1 l! n. i/ _% @
7 c% j5 q% \# S) x
/* File operations struct for character device */; n4 @% o/ g6 m! d$ M1 j8 S* N. s
static const struct file_operations first_drv_fops = {
+ m l' |9 N+ A .owner = THIS_MODULE,
7 o0 C+ @$ X( z% y( c .open = first_drv_open,
4 ~! ]( M8 A( r) P+ A7 s5 N .write = first_drv_write,, N, a' j% V! |* w( q2 @) Q. s
};* n- H4 y4 D$ Y0 S4 L- F" \
! L3 n- c: \ T/* 驱动入口函数 */
9 X) r: t1 f. \3 Y0 ^2 |- u/ }static int first_drv_init(void)
+ m3 J: o- r$ V/ `; q+ g) s{- g0 ^$ i/ ]* w. S
/* 主设备号设置为0表示由系统自动分配主设备号 */, L7 s+ u$ n: v/ l
major = register_chrdev(0, "first_drv", &first_drv_fops);6 W: Y( b7 ?7 [, @6 Z+ R" m
7 Q4 o% |" f* `% x /* 创建firstdrv类 */
x V- C/ N! Q, h7 B, G6 x) { firstdrv_class = class_create(THIS_MODULE, "firstdrv");
% I2 S+ W: ?0 i
% ^, u5 h! |( a0 h- j$ m /* 在firstdrv类下创建xxx设备,供应用程序打开设备*/: {. I: H/ l5 g4 v
firstdrv_device = device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xxx");
) J. g$ ^; I1 e1 h& ]/ {4 ` return 0;
* e n- y; ?, `7 D8 s3 @" X& g}
9 w5 j6 _* M6 T9 m/ e3 W. S1 K+ O6 }3 i7 y" v
/* 驱动出口函数 *// W9 i' V! J! S4 |3 F3 w/ w$ O
static void first_drv_exit(void)
2 ]& C* o8 p8 L$ h' t: {( o* x" i M6 W{
# k- X6 U/ I- m5 H( W* z unregister_chrdev(major, "first_drv");
6 v( W) s/ T' P: V. o6 h( h device_unregister(firstdrv_device); //卸载类下的设备# l8 v3 x+ s, e+ ^
class_destroy(firstdrv_class); //卸载类) G: X: i& L' O$ ^( y) f
}3 `! j3 k. M# N( i
( _( W' {- I( u8 a1 Q; F) G
module_init(first_drv_init); //用于修饰入口函数
( x6 D7 y6 O; e1 [module_exit(first_drv_exit); //用于修饰出口函数
7 G4 ]" _! n% X w3 u# P+ k( m5 n B" z' s% B
MODULE_AUTHOR("LWJ");
- ^# P: C! @2 PMODULE_DESCRIPTION("Just for Demon");# f( V4 P7 n8 z# q
MODULE_LICENSE("GPL"); //遵循GPL协议+ @" S! H" F% \# L0 \% l: R: l! O
i9 U0 k1 J9 R- C: H6 |5 u! D5 ?$ C0 b7 P6 @
注意事项:
6 _* e. y# J3 F4 g% K9 [# \% ?3 q$ N1.因韦老师使用的linux版本跟我使用的linux版本不一致,头文件路径可能有所变动。1 @1 C/ T1 c0 F& S8 m5 _% X
d' ]1 V- H8 S8 N1 N ^2.使用的函数名可能也不一样,例如:
& N3 K7 I) h9 Y. A9 e- _8 K6 X$ W0 A$ ~# M- `9 @2 b H" W" Z
韦老师是这样子创建类和创建类的设备:) ^7 b0 a" w6 N3 S- K. ~3 t* r
/ v/ f% L, {7 g8 {一、定义; a2 Z/ o) o4 n0 T1 \" _8 w
2 E H- x$ w/ t
static struct class *firstdrv_class;
; K" a2 R$ G* u' [static struct class_device *firstdrv_class_dev;) C/ c0 ^6 g! g: Z0 _1 h. L
) w3 J2 c5 F8 ~: F8 G3 m2 G* v
二、入口函数里. o+ F. ?) S0 s# q0 U3 w2 R) s$ O5 z
3 i% o( a. U Ffirstdrv_class = class_create(THIS_MODULE, "firstdrv");' L2 D5 J8 l/ z
firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz"); /* /dev/xyz */
, H' R; @7 H9 O( P/ a0 y' g0 [; E
三、出口函数里
) ~/ J6 L/ o3 }2 N6 f0 B; M# [- s' l& C1 {& C6 m8 _
class_device_unregister(firstdrv_class_dev);
! O! m8 ]. Y" ~+ X6 Nclass_destroy(firstdrv_class);
9 i# v: N/ g# H' |/ D7 I3 U' J* B+ P8 j4 m7 X" v
; r8 Q/ u: t6 f
N7 I* {: Y: d' R( M而在linux2.6.30.4里,并没有class_device_create和class_device_unregister函数0 X: R' \/ t& I( T( F& o' u
! Q1 Y3 z& |2 j+ t+ j我是这样子创建类和创建类的设备:$ Z: B+ T! P( t4 l6 L7 O! x
% J! D% d0 H- `! k一、定义
* p1 s$ C/ G Z* L" r3 P. V0 s1 v
+ V L# J7 |, B9 O0 nstatic struct class *firstdrv_class;$ Q$ D1 U. T2 N7 }5 W
static struct device *firstdrv_device;* Z7 K' R# F. ?0 R2 s7 T& r2 A* e
- T' Y, U! _1 m8 W二、入口函数里6 `$ L3 _; i3 O% [
4 e& G- J. v' l9 U3 @* Q* U
/* 创建firstdrv类 */! b& X6 Q, E, Q/ y' s
4 F- h6 G. ` l# u0 Vfirstdrv_class = class_create(THIS_MODULE, "firstdrv");
6 e' ^' Y$ r6 |6 ~0 r. } r' q6 H, Q: \& K. A
A! }" `$ r$ P. E5 Q
/* 在firstdrv类下创建xxx设备,供应用程序打开设备*/& }3 v, r- k$ n2 I
firstdrv_device = device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xxx");; j+ Z: C! K7 G! q C8 q
4 }1 X% |4 x1 _: ]三、出口函数里7 I0 X3 {- A/ i# y+ Z7 p9 q
. u2 _+ U1 r: i8 {% k7 Q3 v7 [4 rdevice_unregister(firstdrv_device); //卸载类下的设备4 s u/ s% z' I. P; V5 g$ d
class_destroy(firstdrv_class); //卸载类! x4 p* I' {2 _% ]9 p! p* s! B. t
/ p/ _/ ?6 A# E; h8 c
) o7 D) {9 T! z% J# }
/ r# X0 @' D; Xlinux2.6.30.4使用device_create函数替代class_device_create函数;
: [9 {6 I c3 G- x) }# V: A# q, m7 v7 ^* t
使用device_unregister函数替代class_device_unregister函数。
) d, G* k: U/ m" r1 L' Q
. ^5 t/ C8 J) k/ i5 Q' W% ~3 `9 E/ p7 o+ S- A7 ^! z
4 t' W9 V/ J: l) w! G) F; O+ F+ }7 d
测试程序和Makefile没有修改,故再不贴。
) e5 y) U7 t: w# u! w2 ~
/ K- u4 ^; s% N* p4 c; ]测试步骤:8 y- V4 G* ~& D/ Z
% K5 s8 g; T5 h; x8 F
3 R& \! j: P q9 B' n P# F[WJ2440]# ls: S, J6 q2 @8 K7 A. z6 y
Qt driver_test lib root udisk
* Z% ^$ k3 v6 G) l, z* n, {TQLedtest etc linuxrc sbin usr
% U6 Y/ y3 n' e2 |app_test first_drv.ko mnt sddisk var, j2 i' q! c! X3 l# }
bin first_test opt sys web
! S+ U4 G Q! |: ~# O& Rdev home proc tmp
, A! |0 O( e- H. I# Q% K[WJ2440]# ls -l /dev/xxx5 |( C1 @6 f8 k% v$ T' v$ I! B
ls: /dev/xxx: No such file or directory/ C& a" s# ]4 f8 d
[WJ2440]# insmod first_drv.ko . Q& b& b) [2 t6 A& { e
[WJ2440]# lsmod
2 J8 k( D1 }8 L7 n( j$ R: Efirst_drv 1912 0 - Live 0xbf000000& ]0 a+ `9 j$ F0 h/ d. F2 r
[WJ2440]# ls -l /dev/xxx8 Z4 o' M/ M, D2 D: N
crw-rw---- 1 root root 252, 0 Jan 1 23:17 /dev/xxx8 C* L4 M" [1 `2 o
[WJ2440]# cat proc/devices
" y* Y) G( ?9 x5 P2 ~Character devices:2 F% f( A9 n5 r( |5 H, ?5 |& r8 _5 B
1 mem
$ E* O0 F0 l6 z- o/ K! w. S 4 /dev/vc/0
5 R- e' y# d/ j0 y 4 tty
; @: ]! @! ]* C6 b: J 5 /dev/tty7 S9 X" x$ } L
5 /dev/console* ?' L6 {/ g! n, p7 m% ^0 H! E
5 /dev/ptmx
2 v5 \1 ?6 W- _% V 7 vcs
' a+ q/ M5 H& p& y 10 misc1 K4 R- f6 a: t. P" y
13 input1 o9 N1 r' u. L3 G3 F
14 sound8 t% O& L s( w) @
29 fb! R/ h7 r! k8 _
81 video4linux
; T1 d1 B" i, `, ?8 R 89 i2c
, N" A1 w0 Q: i+ L 90 mtd( n. x4 ~, Z# C! M) s# {
116 alsa
$ K3 o1 ~2 ?/ b) x; R2 a128 ptm/ @! K" K+ k. W; Q8 ?4 @
136 pts6 w2 V, x& k$ g( S4 B: i3 o( \
180 usb- K" u5 C' H! x i3 j T7 q
188 ttyUSB
$ R2 ~- P; Q( x! {189 usb_device2 [$ @. m, R; c% y* } L3 r
204 tq2440_serial! `8 J# ~2 }1 N' [) U6 X
252 first_drv
3 _$ C7 M5 S+ W0 }253 usb_endpoint
, e7 I9 ^) g7 j/ R254 rtc/ u2 R0 a: h: T# K+ b2 ^5 d
7 G7 G: f& L+ p% Z$ W; f8 L% V; t3 YBlock devices:
7 j, O% G6 T- m3 q) S259 blkext: t5 M9 Y' k' y9 Y2 I
7 loop* T9 X w' P# b& f) G
8 sd
/ u) G3 s2 E ], P0 e 31 mtdblock
/ T8 n4 S: @; w, u% O1 b3 A 65 sd
+ f$ \. t/ D' U1 o8 s 66 sd( C9 }( N6 {7 r
67 sd# V: r; i) ^) d2 L# I; o
68 sd0 Z) x" T2 { z! u! @: g
69 sd* U* U. s2 A9 k2 d: G; _) }0 Q
70 sd/ J9 {6 X" h/ t. U, M j& v
71 sd% N$ W2 Z; M' F! V$ C3 _
128 sd) G% |) n J0 p+ J: w) N7 K
129 sd* D5 J l' K' q$ A0 J; }( r
130 sd
* k$ U4 j5 ~* Y4 ~9 h" F131 sd
$ Y7 j) q" Z3 H. F- w132 sd
- G0 N/ J/ K. g2 t1 ?' s133 sd' P! |7 Q! b5 }4 I8 r
134 sd
! ?3 N$ l$ T; }1 G135 sd
# k0 }& y. C- Y4 }$ l5 K: k179 mmc
* A! J! H% t3 y5 ][WJ2440]# cd /sys/class/9 H+ T, t4 G: c, Z3 j
[WJ2440]# ls
# W" n5 P! u2 m5 j. s6 qbdi i2c-adapter misc scsi_device usb_endpoint
0 U8 F- n1 ?' Pblock i2c-dev mmc_host scsi_disk usb_host
, H/ |; [3 n8 Z( b( o3 Y7 Lfirmware ieee80211 mtd scsi_host vc- m5 n0 w( \- \
firstdrv input net sound video4linux
9 M" Y. q8 ?) p9 U8 }0 h1 rgraphics mem rtc tty vtconsole
# s* F. C4 U8 `' c0 v4 _' R6 ^3 ~[WJ2440]# cd firstdrv/
* B4 M8 K2 h8 x5 p3 b! X& [[WJ2440]# ls& J ^ ]4 @0 j, L5 [
xxx
1 C0 d2 T' e5 [4 h7 C[WJ2440]# cd xxx/1 k l7 O! s, T3 L/ N
[WJ2440]# ls ; U! ]) h# q1 ]/ v/ ?
dev subsystem uevent% d* s& @3 P4 ]3 j( ^. o
[WJ2440]# cat dev
6 d6 D; V7 ], [& \8 [+ W, C8 X. E9 K252:0
- b; O2 T* o* z" R Y4 ~[WJ2440]# cat uevent
: J: N& {# A0 n8 N- PMAJOR=252, s6 v0 v$ }: M( U1 G6 e. H3 O9 p- n
MINOR=0
- L$ E" v5 |! `" K[WJ2440]# cd / 5 l# F4 L J) a2 E
[WJ2440]# ./first_test , \1 Z6 a/ `! d* w) c
first_drv_open
) a% v# h/ c1 s( O' i) Mfirst_drv_write
2 P( D/ ~9 G7 y. o' Z$ _[WJ2440]#
( T4 P, q' N+ N$ B" t
0 z/ D' F) ~+ g# D8 f
/ x3 B+ W! D: y* z4 `
, Y: z$ H. b3 |1 \: _ t$ p |
|