EDA365电子论坛网
标题:
linux字符驱动之自动创建设备节点
[打印本页]
作者:
ulppknot
时间:
2020-4-26 10:42
标题:
linux字符驱动之自动创建设备节点
问:能不能让系统自动创建设备节点?
- F# T. w! L# p
" h( P2 N6 H7 i8 w6 W# Y2 }( B
答:可以,linux有udev、mdev的机制,而我们的ARM开发板上移植的busybox有mdev机制,那么就使用mdev机制来自动创建设备节点。
5 X( \/ l: M. d
0 n: t; S @( G7 \0 H. S, w
问:文件系统里,在哪里设置了mdev机制?
# `1 N# X% o' @. F$ D3 n
# E' g$ J3 j5 F5 E! c
答:在etc/init.d/rcS文件里有一句:
K- M6 q; L& @- w
$ X" g3 b! Z7 V5 ]2 |! j
echo /sbin/mdev > /proc/sys/kernel/hotplug
5 S' y5 H' y% u: }$ t6 Z% h
/ j' B3 G6 f3 U
问:在驱动程序里面如何编写程序,让系统自动创建设备节点?
4 I8 ~; g4 _8 @% F4 ?& P
2 _! k( D1 H2 y+ [) c p: U; `3 d5 n2 t
答:首先创建一个class类,然后在class类下,创建一个class_device,即类下面创建类的设备。
- g0 T0 \; j5 [! H0 p
* Z) S6 c3 C# H- U2 C7 H6 U2 \/ Z6 F
1 H+ p, B( I% @' N- H' t
& y% E$ C5 P1 F& I, I
详细请参考驱动源码:
8 l4 m: T7 s6 C. X4 T) |
. B! D. x7 [3 T& u
2 ~" ^6 k& `3 o6 V# B
#include <linux/kernel.h>
3 F3 r/ ?) e- j) W; ^
#include <linux/fs.h>
: S) |# H5 B( e$ J- c3 |
#include <linux/init.h>
0 u5 z B: R5 P9 u
#include <linux/delay.h>
4 ?! j) }0 U6 R5 q. h, I, |
#include <asm/uaccess.h>
+ s, m1 }' d" C/ W; i7 M) K
#include <asm/irq.h>
/ ]! E, J9 [$ N7 g- T( h* l& M
#include <asm/io.h>
' J6 m, h% w) S
#include <linux/module.h>
, u" e5 J* e9 o2 o) c
#include <linux/device.h> //class_create
) L) _7 h# e, `
9 m$ x2 f. r. I
static struct class *firstdrv_class;
6 m4 T$ R$ M$ y% S& S; Q: ^& V
static struct device *firstdrv_device;
9 `' [( Y+ I# O% k
9 E8 n: _0 v$ `1 I2 B
int major;
! O" d7 C# Y% }' Z
static int first_drv_open(struct inode * inode, struct file * filp)
4 X: o+ {6 N/ [8 D! Y4 ]! j, N: Z# G
{
" D4 x; v1 X6 V8 W& n! ?- ]
printk("first_drv_open\n");
- N& F O/ e6 u& e# i! X7 k
return 0;
( n5 }/ c- c) N& d
}
" y2 I* ^; t3 y: S. @
static int first_drv_write(struct file * file, const char __user * buffer, size_t count, loff_t * ppos)
$ d5 J# [: E" A) B# k4 V
{
: p) |! E/ u: n
printk("first_drv_write\n");
5 r# O# F5 h9 p* I
return 0;
8 U% i) g2 ~; {( z, Y; ]% ]
}
- @; a3 h& }% a" Q5 T( z, Z2 G% m
! `& E& a9 g4 k8 A% Q: l! t
/* File operations struct for character device */
$ _- r B7 I) e2 K6 f1 z
static const struct file_operations first_drv_fops = {
6 U) m* D( Q& I3 I! Q& x6 ~
.owner = THIS_MODULE,
' E3 n6 f" d5 [- P1 c
.open = first_drv_open,
8 p9 A( ?" z. A7 h
.write = first_drv_write,
0 W. \" k$ _& q: W8 Z% H# p
};
: G/ m" Y( r7 [3 S# |
& [# f; ]8 }, F j) V, L$ B8 Z1 B
/* 驱动入口函数 */
) G a5 N2 T; w; e$ F' u1 v r
static int first_drv_init(void)
, y N' [) z; |& w) Q1 [
{
0 |, f( N4 g r- H5 t
/* 主设备号设置为0表示由系统自动分配主设备号 */
/ y3 p# W$ }% y* t4 `& z3 ~
major = register_chrdev(0, "first_drv", &first_drv_fops);
3 u" m/ N. g1 m6 F$ o& o
) q5 v. K5 k! I; g6 E
/* 创建firstdrv类 */
% W4 L/ U, I6 p6 g' t
firstdrv_class = class_create(THIS_MODULE, "firstdrv");
?6 ?) k* q/ P! }$ j. J
! f) R( S; [7 L) B! ~# ` U& O
/* 在firstdrv类下创建xxx设备,供应用程序打开设备*/
' B# {6 A8 P3 N% c9 M
firstdrv_device = device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xxx");
2 _, e( {' N+ L# a& c* _/ V
return 0;
( v' L( s7 g! [
}
% _7 T& P3 @ F+ ]7 d, y: T/ [
6 o! d( A& `6 @& e5 F
/* 驱动出口函数 */
6 S8 I* p9 p- Y- L' V2 |5 f" E3 E
static void first_drv_exit(void)
5 r2 k& J5 e& c T8 x
{
: M i; W2 w* `! O/ \
unregister_chrdev(major, "first_drv");
: J& H( d; Y" Z4 c: g6 _2 R
device_unregister(firstdrv_device); //卸载类下的设备
4 B- ^3 r1 D5 _. F9 h- o
class_destroy(firstdrv_class); //卸载类
& l, j: }; [% x# w5 m2 Y+ T2 R
}
+ }% d8 V4 S2 |! S9 Y1 a) u- Q( m
! n8 p9 ]. p! U* a/ o
module_init(first_drv_init); //用于修饰入口函数
# V0 _. j8 {/ f9 E& G
module_exit(first_drv_exit); //用于修饰出口函数
* }4 A0 A! h7 y1 Z
6 K8 R0 z+ I* X [5 g" i
MODULE_AUTHOR("LWJ");
9 P+ O7 i \; _7 _) k
MODULE_DESCRIPTION("Just for Demon");
6 |7 N/ R2 S2 t% P C
MODULE_LICENSE("GPL"); //遵循GPL协议
# E: g) i% |# C0 ?
3 v; g6 t8 T, j. c( l' }
, p/ |0 ~+ _2 W. T2 ]- G! O
注意事项:
- P2 u/ N) t7 @& @
1.因韦老师使用的linux版本跟我使用的linux版本不一致,头文件路径可能有所变动。
# H8 i% E( A. F4 x' w t! q
# m7 T2 @* b: C( {9 ^/ }
2.使用的函数名可能也不一样,例如:
- m! }* d: [8 Y" F% s0 u+ M+ a/ z# M
% B% D. O5 O1 V0 A( {$ F, R
韦老师是这样子创建类和创建类的设备:
# q6 g$ M0 g: K5 I% A4 F/ [; h8 J. ]
0 R Y! t- j" k5 X
一、定义
/ e, [; X9 F# o) D
, w3 t4 p9 \' H
static struct class *firstdrv_class;
( n- ~/ B1 ]. j R) @
static struct class_device *firstdrv_class_dev;
. p [9 {) y+ i4 C8 e! w2 F/ U: o' f
" s+ @/ W% E# e1 ~- w4 @
二、入口函数里
' o6 N! h" W$ ]0 ?
/ U$ G! Z( {$ g; M; d8 N
firstdrv_class = class_create(THIS_MODULE, "firstdrv");
1 {0 \$ }' J( p/ C/ E6 w
firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz"); /* /dev/xyz */
( g/ l v: t* m/ K. m+ {
7 d2 `. M9 @: x5 V8 r7 ]0 [
三、出口函数里
* @, O+ C6 j# C8 Q6 h( S
8 ]0 b; s* W8 I9 V0 Q. F$ C0 S) ^
class_device_unregister(firstdrv_class_dev);
/ e+ ^; [* f( n: s$ a: W6 ^
class_destroy(firstdrv_class);
7 Q! I h/ N+ t( B j
" G0 k+ E- @- P
; [/ H% D! x. r$ c& |. Y6 r. ^7 \! q/ E
& i' Y& w) }! Q# F+ Z& a- t' ^
而在linux2.6.30.4里,并没有class_device_create和class_device_unregister函数
2 E* t* h6 V& j! t" V6 V
# N% a" J) \# F# |
我是这样子创建类和创建类的设备:
* L: {) ^/ m4 {9 X" z, b- e
( f/ d) ^: u6 R. O: m
一、定义
! q, K, g' E5 L& z! o$ E4 ^
& ], J% Z' V$ A/ Z
static struct class *firstdrv_class;
: v" {+ S# ^% S' [4 p! i
static struct device *firstdrv_device;
" F! K1 {1 ^5 c1 ?# F- M3 C# A
& Z c! ^1 [0 o" z
二、入口函数里
" D# O& i- V) x) u
) T& h& y/ E: r
/* 创建firstdrv类 */
' i* Z+ | K. N) p
: h- a3 o) p& G/ D- a' `
firstdrv_class = class_create(THIS_MODULE, "firstdrv");
( u1 @- b8 @- Y3 r8 R; n
, e7 D& W! Z6 D* ]0 ?, R9 c
, J) W) p, Z& W3 w9 d
/* 在firstdrv类下创建xxx设备,供应用程序打开设备*/
. o+ ^9 w& b- k) H/ x1 Z
firstdrv_device = device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xxx");
+ }1 @' c, o& `5 R
, x! I; @ T X$ M- N0 M
三、出口函数里
6 \9 M* a5 @. O: P! }
6 [* R8 E! E1 o Q6 y: ~ i4 i- n
device_unregister(firstdrv_device); //卸载类下的设备
: }3 z3 X/ k% h
class_destroy(firstdrv_class); //卸载类
, [- X8 I( o& s% a" I
2 c1 l6 F* q: o& A' ]
}* O6 u, {4 P! v
4 O; I% c+ X# g0 D
linux2.6.30.4使用device_create函数替代class_device_create函数;
; [, f8 s4 |+ j- [5 \. L$ W
" I- M$ b T# _) u! }& t% Y) A7 v
使用device_unregister函数替代class_device_unregister函数。
2 a$ }. H4 }2 k4 }5 Z
& n4 S- r; J A/ j
4 d' |5 m2 ?: k$ E
/ I3 u% e" A; P( Y2 V
测试程序和Makefile没有修改。
1 Q) ?5 h, ~) F3 o$ \% f( {% X
' D- d6 ]0 u8 h
5 R' |2 _( f! T8 h% M
测试步骤:
+ j& h8 D' \& ?# m& e+ Q8 B4 [
9 k( E& s: a7 M4 \
7 c: E1 V9 V _, W/ @
[WJ2440]# ls
. E5 v# X! F; |( m$ [0 R1 P; N
Qt driver_test lib root udisk
! `7 ~& L7 [ v1 ?
TQLedtest etc linuxrc sbin usr
, o/ c! l* b2 g {7 m7 H
app_test first_drv.ko mnt sddisk var
0 V2 ^) ~6 K* k8 Z2 n0 t# u* e5 q
bin first_test opt sys web
2 {% q+ k% P( W- D1 U% M
dev home proc tmp
3 y9 t: @5 u- r. l5 y; b# F
[WJ2440]# ls -l /dev/xxx
, W# U0 `; Y9 i
ls: /dev/xxx: No such file or directory
t$ v: ]; a5 B0 C! B7 ]2 y
[WJ2440]# insmod first_drv.ko
: [- {1 C6 ^3 i8 l5 E( q- U- e; h1 F
[WJ2440]# lsmod
3 E" [0 \5 f" N
first_drv 1912 0 - Live 0xbf000000
! \, B3 A$ c1 J( v6 i/ ~( `
[WJ2440]# ls -l /dev/xxx
0 r+ I" F" Z3 ~% W& d! X& p
crw-rw---- 1 root root 252, 0 Jan 1 23:17 /dev/xxx
" b/ D8 \5 Z2 v' ~7 e- g: l8 V) U
[WJ2440]# cat proc/devices
6 \& @3 S0 d: N6 f" f
Character devices:
3 Z$ }5 a& W' E. x: P% T" }$ E
1 mem
2 ]$ |0 z& k: i+ H) M
4 /dev/vc/0
( P8 S+ \5 w0 Z9 w" J! d
4 tty
7 a+ i. u" Z' W
5 /dev/tty
' j& B3 }# t3 G* q: S9 f
5 /dev/console
5 Q* ]0 S1 c% I( d1 j
5 /dev/ptmx
0 Z# R6 o3 ?* J. G4 u4 {/ l5 M
7 vcs
" g0 e* l8 ~5 m! y6 |
10 misc
% }5 Z& e8 y1 O# r$ v* t
13 input
- n. l7 {$ t0 @% ~! K
14 sound
3 ?# `0 W# i1 H; h6 J, _
29 fb
! r2 b; U& @; R
81 video4linux
( |: q8 a) Z1 O
89 i2c
- W: B0 ?0 P) }0 Q( f2 j
90 mtd
& K! [/ C/ J- I$ P3 b3 _
116 alsa
2 B6 F, Z9 S6 F) U6 b4 O4 R
128 ptm
# e( @) A7 u- z+ n l
136 pts
, X; q" G, @5 K+ t8 g2 @4 V
180 usb
i& @- ^( q, d7 X) d f( V0 K
188 ttyUSB
8 {- n2 S- m* i7 O
189 usb_device
" R# n: U; L. r2 r
204 tq2440_serial
% b6 r6 T% W3 _8 _' L" C
252 first_drv
% M* u; w' d# _1 [' `8 O9 L
253 usb_endpoint
0 `1 e* {4 v! ]
254 rtc
: x: k6 c4 ~7 v
* d0 z+ b0 {- v* U' y
Block devices:
3 X' Q" K! x1 r m7 d+ W
259 blkext
6 I# H* @& \8 {- W
7 loop
7 q: R& J: B8 [% {, _6 u- C- z
8 sd
C# ?# a% U6 G6 s/ n: j* M
31 mtdblock
- N( z0 X& q' s! p: k9 p
65 sd
6 N$ i0 h) x$ U' j; D
66 sd
7 l0 e7 n2 ?. f2 c; A
67 sd
5 p( Z2 E8 q1 n4 J5 |# v- C
68 sd
|4 U; B6 D3 Z% C) t% Q" t
69 sd
: l4 f( P; f7 k% t; l y+ m
70 sd
! m( ?& x% W/ U: J5 A4 P2 d: Y
71 sd
4 K" q) t/ D' G
128 sd
3 x& [" I0 ~+ E$ H O
129 sd
y. p! x. t% d& n4 I, o9 r
130 sd
+ F ?" o& A. G o, ]/ w; R
131 sd
8 G ~( r/ i9 w4 Z) b) M& X6 V
132 sd
) j) [5 J5 P8 J9 R& F. Y; Z5 G. Q% ~
133 sd
" F+ a$ p+ o* ~8 _
134 sd
, R" p7 _7 j$ H7 i- g$ p( L$ C2 ?
135 sd
: D1 @- \2 s- @+ P
179 mmc
+ q" {. h" h& ^) \9 Q
[WJ2440]# cd /sys/class/
, o2 X; y% j+ C$ p
[WJ2440]# ls
' T! W; ^- p+ n" E4 D
bdi i2c-adapter misc scsi_device usb_endpoint
( O' E: g/ B, d
block i2c-dev mmc_host scsi_disk usb_host
; h8 }) I' a8 ?; ]( h$ X) Z2 S
firmware ieee80211 mtd scsi_host vc
0 n* {0 J9 X3 Y; m- t
firstdrv input net sound video4linux
8 f/ z% B' S9 z2 \& o0 _
graphics mem rtc tty vtconsole
; E/ N6 M' L0 O* A! a1 k
[WJ2440]# cd firstdrv/
0 |6 l% u# Y- q. a* h% @/ D, Q
[WJ2440]# ls
1 ]6 r6 k5 r5 w8 g6 | c, ?
xxx
+ z/ F" H3 c3 e& {7 ?& H: b
[WJ2440]# cd xxx/
* ~& Z! A( {+ n6 g0 `! q5 e3 A3 |* V: Q
[WJ2440]# ls
: r3 z" b3 @2 N6 V; R0 c( }/ T* L- t5 W
dev subsystem uevent
* D# a9 M, J w8 x) y: }. e" W0 A! _/ e
[WJ2440]# cat dev
7 K4 Z" H' O7 o# l) c: f0 R
252:0
) e/ u; J+ q: y; c9 [
[WJ2440]# cat uevent
6 L9 _3 @$ S% j2 ~
MAJOR=252
, O [& r3 X3 ]" }/ `6 ^
MINOR=0
. r/ ^& {& I5 T
[WJ2440]# cd /
$ A: ?$ M+ j% V! L. u* U1 b
[WJ2440]# ./first_test
; ^+ w! K% l5 u/ x
first_drv_open
. ]# q) j( F, } ]5 r
first_drv_write
+ ~* j& F! c+ @
[WJ2440]#
% P! Q) u. R4 C; [
/ H$ }5 l" D3 h O( u- I
: ^5 I; p1 y0 D3 o: f
" t- s! P' W* F
9 w& c1 S& y) g% O" ~" ]6 L
作者:
NNNei256
时间:
2020-4-26 14:09
linux字符驱动之自动创建设备节点
欢迎光临 EDA365电子论坛网 (https://bbs.eda365.com/)
Powered by Discuz! X3.2