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 |! jecho /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 F1 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. Istatic 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 Bint 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  rstatic 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& Gmodule_exit(first_drv_exit);  //用于修饰出口函数        * }4 A0 A! h7 y1 Z

6 K8 R0 z+ I* X  [5 g" iMODULE_AUTHOR("LWJ");9 P+ O7 i  \; _7 _) k
MODULE_DESCRIPTION("Just for Demon");
6 |7 N/ R2 S2 t% P  CMODULE_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 Nfirstdrv_class = class_create(THIS_MODULE, "firstdrv");
1 {0 \$ }' J( p/ C/ E6 wfirstdrv_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- ndevice_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 Dlinux2.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 h5 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; NQt            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        var0 V2 ^) ~6 K* k8 Z2 n0 t# u* e5 q
bin           first_test    opt           sys           web2 {% q+ k% P( W- D1 U% M
dev           home          proc          tmp3 y9 t: @5 u- r. l5 y; b# F
[WJ2440]# ls -l /dev/xxx
, W# U0 `; Y9 ils: /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" Nfirst_drv 1912 0 - Live 0xbf000000! \, B3 A$ c1 J( v6 i/ ~( `
[WJ2440]# ls -l /dev/xxx
0 r+ I" F" Z3 ~% W& d! X& pcrw-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" fCharacter devices:
3 Z$ }5 a& W' E. x: P% T" }$ E  1 mem2 ]$ |0 z& k: i+ H) M
  4 /dev/vc/0( P8 S+ \5 w0 Z9 w" J! d
  4 tty7 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/ptmx0 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 R128 ptm
# e( @) A7 u- z+ n  l136 pts, X; q" G, @5 K+ t8 g2 @4 V
180 usb  i& @- ^( q, d7 X) d  f( V0 K
188 ttyUSB8 {- n2 S- m* i7 O
189 usb_device" R# n: U; L. r2 r
204 tq2440_serial
% b6 r6 T% W3 _8 _' L" C252 first_drv
% M* u; w' d# _1 [' `8 O9 L253 usb_endpoint0 `1 e* {4 v! ]
254 rtc: x: k6 c4 ~7 v

* d0 z+ b0 {- v* U' yBlock devices:
3 X' Q" K! x1 r  m7 d+ W259 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 sd5 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 sd4 K" q) t/ D' G
128 sd
3 x& [" I0 ~+ E$ H  O129 sd  y. p! x. t% d& n4 I, o9 r
130 sd
+ F  ?" o& A. G  o, ]/ w; R131 sd8 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 Dbdi           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- tfirstdrv      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 R252: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 rfirst_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