找回密码
 注册
关于网站域名变更的通知
查看: 202|回复: 1
打印 上一主题 下一主题

linux字符驱动之自动创建设备节点

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2020-4-27 10:25 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
上一节中,我们是手工创建设备节点,大家肯定也会觉得这样做太麻烦了。& Q) b  L3 \7 g

1 m. h4 @+ g1 W, o+ l上一节文章:
. Q: y" C* Q# w5 P% ^: ]9 V( t
问:能不能让系统自动创建设备节点?" a, I9 e+ _1 \1 ?% W

) d( e" M2 o8 E. D1 l答:可以,linux有udev、mdev的机制,而我们的ARM开发板上移植的busybox有mdev机制,那么就使用mdev机制来自动创建设备节点。& D. C5 Q. r+ y

: U+ B) v, G$ o3 x  @0 h+ ^问:文件系统里,在哪里设置了mdev机制?( U' z7 S; J3 C  s6 ^3 ^# b
$ b# Q. W: l  l
答:在etc/init.d/rcS文件里有一句:: h4 x  p. g. n4 d: }+ A$ ]

( }% b, S2 N! E6 p' Qecho /sbin/mdev > /proc/sys/kernel/hotplug* J" _, D' i- I; J# z- R8 Q+ ?1 J
( U) L0 @8 H; a3 T% U+ j1 j
问:在驱动程序里面如何编写程序,让系统自动创建设备节点?
( n' @' S- y& ?1 ], @/ g3 O% ]' E- k! w) C
答:首先创建一个class类,然后在class类下,创建一个class_device,即类下面创建类的设备。4 o6 q+ r7 q. P" X3 a' r: C8 t

8 Y$ G. t3 s* e* \1 ^. C0 D  T/ M" U& J4 m1 |

% d" A, v! S0 p7 C; n详细请参考驱动源码:! V8 k9 e( l7 n8 t

! p- Q  h$ K1 a( d# Y) M# i$ Z6 K7 Z: c
$ _+ [- k$ [7 p! q+ _, S#include <linux/kernel.h>
( U+ W6 l6 Q; n' Z8 n#include <linux/fs.h>/ }$ }3 _. l- o: t; y0 ~
#include <linux/init.h>- R$ W8 }2 b3 M& ~
#include <linux/delay.h>
9 B% o) c9 X8 R4 B5 R6 y#include <asm/uaccess.h>" x0 L) b2 [6 F
#include <asm/irq.h>! H6 K3 K2 _" f! e( j
#include <asm/io.h>' c- P3 \' p% b& I" W* J- H
#include <linux/module.h>7 e  a6 b) G/ S- a6 ^' p
#include <linux/device.h>         //class_create
! F4 `8 N3 m( p1 m( D2 k% z5 x2 @* P/ a8 i
static struct class *firstdrv_class;9 S/ w$ z/ x4 C& W% S* }& I) V
static struct device *firstdrv_device;0 H' R' u0 c4 }. B
6 f/ z, a/ P5 k8 `' k0 h# a" ]
int major;
8 ?- d: t% q/ E1 F2 U, ystatic int first_drv_open(struct inode * inode, struct file * filp)
% i" E, i% E9 d4 A{
" L0 [8 Y) ]# i+ B4 n        printk("first_drv_open\n");' X- i8 h; B% f9 E$ h* }
        return 0;
6 E5 [0 z! S, Z, b2 c}, @; o1 ?9 {  J& i7 x
static int first_drv_write(struct file * file, const char __user * buffer, size_t count, loff_t * ppos)+ e9 m! {# z7 [1 }+ t* T
{
  a3 y  J9 a" ^* o        printk("first_drv_write\n");
( T  D5 C# W6 X% L( u7 N0 Q        return 0;& B0 a( Y- k3 G/ w0 U' B* J' _# s5 j
}
; a2 J  |4 J5 e0 A/ R( N, X) V+ q4 f4 M, g) s" H8 x+ m" q- X( E& Y0 e! e& R
/* File operations struct for character device */
# x1 m2 A  D# Q% R) @5 {  xstatic const struct file_operations first_drv_fops = {( F0 b( P; j8 T
        .owner                = THIS_MODULE,
+ b% w  a, e8 }, k, M        .open                = first_drv_open,. a7 R% ]. \: n1 E6 m1 h* u
        .write      = first_drv_write,, M1 b( {) S6 t2 K
};
5 f* y, _3 G0 r. W
: ^2 P# O! @! Y+ K8 {$ j) J/* 驱动入口函数 */; p" I, \3 N, R2 ^6 Y& ^
static int first_drv_init(void)
/ `/ c" x+ u" ~. b2 W9 S{6 A/ z: q6 b$ F7 P  R
        /* 主设备号设置为0表示由系统自动分配主设备号 */% O) f. [/ M8 t! f+ a: u8 P  K
        major = register_chrdev(0, "first_drv", &first_drv_fops);
- Z( S/ C! h! c+ ~
6 d% i5 H' r5 V2 y0 C        /* 创建firstdrv类 */
# \7 Z; ^# m9 [# e        firstdrv_class = class_create(THIS_MODULE, "firstdrv");4 Z/ p# ~& J; B8 Y

0 V' I4 `5 s$ K5 a; w6 m        /* 在firstdrv类下创建xxx设备,供应用程序打开设备*/
# f# ^9 I; f: D9 `        firstdrv_device = device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xxx");+ b  x, l3 U" b/ p+ z; G
        return 0;+ p2 e( e% T/ c% o) E
}
6 u" w2 u& y% G7 ~* t9 k7 l
& P$ g2 ^; |- U# l" D, O5 E4 V0 t/* 驱动出口函数 */$ }' L7 q/ w. Y1 I
static void first_drv_exit(void)* r- n& \) t% s9 f; p
{$ P* F8 M4 @) w' I
        unregister_chrdev(major, "first_drv");
' H. I+ U' a1 x. m$ N( G$ |        device_unregister(firstdrv_device);  //卸载类下的设备
/ v* O0 R$ A# ]9 f: ^        class_destroy(firstdrv_class);                //卸载类8 M! J& A8 _" ?( }  s! M2 t
}; }* ~, _. S1 E; C3 R% o: j! D, ?

1 a! _' N- k' W0 fmodule_init(first_drv_init);  //用于修饰入口函数0 s3 x4 d1 b" t& t0 t
module_exit(first_drv_exit);  //用于修饰出口函数        
1 ~! ~" ?, w* b: ]8 A( Y( m% _9 P: @- Q& m* g* v5 n
MODULE_AUTHOR("LWJ");- G4 G& t0 y* @- B" X; x* J
MODULE_DESCRIPTION("Just for Demon");& |; e$ x% J5 [. {; K5 M, F
MODULE_LICENSE("GPL");  //遵循GPL协议
* {, t- d( c/ B
& p& a  I# @- Q7 o7 m8 b
* W. N% @5 f! T) m' a注意事项:
3 m' L6 m, X4 {7 G$ c$ N4 m1.因韦老师使用的linux版本跟我使用的linux版本不一致,头文件路径可能有所变动。2 Z/ K, W' ]6 i% g4 e/ [

1 y" Z6 i, W! Y2.使用的函数名可能也不一样,例如:
6 M, c) o& s" C9 L5 `4 c5 M: x9 _( r- d- }
韦老师是这样子创建类和创建类的设备:3 }- B4 T8 U2 V  }
. |+ c0 G/ `! l$ `
一、定义& R9 O  T' B9 v7 ?
7 s! e8 R' I5 G+ o! z6 K" Y: H2 v
static struct class *firstdrv_class;9 {/ k" ?  z* P0 w& S6 L% h
static struct class_device *firstdrv_class_dev;
$ [, n6 w3 c5 h& g1 e( `
6 r, F  m3 x3 ~# W" I% D/ B  L* i二、入口函数里* _. \7 |3 C: t0 Z. S

6 t# X8 h* D4 q& {firstdrv_class = class_create(THIS_MODULE, "firstdrv");
- M; G2 w! L. o" s! X' S2 F& }* j; Lfirstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz"); /* /dev/xyz */
# ]" E" Y1 x5 J. z
0 Z" O3 v' L- R$ u三、出口函数里
/ C! M- H- V5 L. J* I! r
7 L+ U( z8 D6 n' o: `class_device_unregister(firstdrv_class_dev);0 ], ^# |+ m0 y" c
class_destroy(firstdrv_class);
' r" ]& z: Q: l( c0 B$ G* D0 `5 p5 E. h7 c5 {. k! Y
. I  L, x# P$ l

5 U( i2 v3 q6 n  g9 n而在linux2.6.30.4里,并没有class_device_create和class_device_unregister函数, ^! Z8 }7 z$ [& ^& |

8 G" H4 G, O, W我是这样子创建类和创建类的设备:
9 Q) @, m/ E+ c; Y/ R5 l4 e( L8 i2 F+ G( V0 Z1 P
一、定义
' G+ o' T6 [3 E* D0 x: c; U/ G# N  ?. K; t& o( L& _  Q7 w8 ?8 x/ C
static struct class *firstdrv_class;
! F! h2 A5 x6 F- a* n6 J! Gstatic struct device *firstdrv_device;' S7 s. t3 u* F2 |& F0 Y9 c  Y+ D, ~
2 i+ b  W6 Y' C: z3 ^6 m
二、入口函数里4 f. K2 p, |# C
1 V1 A+ l6 H4 B' D+ h
/* 创建firstdrv类 */  ?3 o: o4 {2 U5 w! w

+ G! f" A! C5 D2 mfirstdrv_class = class_create(THIS_MODULE, "firstdrv");
9 J8 h# ?2 _, Q/ U: I# L( [' ?: s0 F
6 d: V. {9 ^- G+ o
/* 在firstdrv类下创建xxx设备,供应用程序打开设备*/6 z) h2 F: h$ C+ _9 Z! `0 c- Q% \4 S
firstdrv_device = device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xxx");2 y& o1 j& h9 p' }7 Q' h' Q
# |" z0 B% }- ]
三、出口函数里0 U9 h, p5 g4 H# K* S! x9 X% S/ [
# x6 q' t& P& Y* I4 d9 |" v
device_unregister(firstdrv_device);  //卸载类下的设备
$ L8 o! v8 o9 M2 [5 ~class_destroy(firstdrv_class); //卸载类0 S; o5 H1 C4 g

* N  U( o3 X: E( f" E% q, |- D
6 k2 ?: }/ i, x. i% y
7 s2 ^& d8 [% f0 Wlinux2.6.30.4使用device_create函数替代class_device_create函数;
9 r' T1 U1 ?3 S) e: e, E- q. i1 `/ _0 q# H5 R) U4 w
使用device_unregister函数替代class_device_unregister函数。& N' L' ]/ R- d& j7 e9 b( F
3 {7 i9 K( v8 x1 @6 o" H
, h( R4 p) c1 `. I) F( ]( E
  Q* n6 |, `# v; {/ c2 F
测试程序和Makefile没有修改,故再不贴。8 `4 b0 W2 ]' ]8 g$ Y. f  ^
4 C8 p: b9 w& S' m6 R. @
测试步骤:8 Y% r2 M7 [1 U1 `- o

! F% o/ G4 g3 k5 v; `
4 y" Y) _3 D4 \" ][WJ2440]# ls; X6 _8 R0 l2 ^
Qt            driver_test   lib           root          udisk
- X6 b* b5 ~0 P4 n8 |1 LTQLedtest     etc           linuxrc       sbin          usr+ W5 v! `3 q: \/ A
app_test      first_drv.ko  mnt           sddisk        var- Q) z- a+ e: j6 v* d6 l+ L
bin           first_test    opt           sys           web- L. I( h& l! R7 a9 ^
dev           home          proc          tmp
+ X( y, K+ _% o! r  P! J" W[WJ2440]# ls -l /dev/xxx
8 O' @/ x# e) k- p0 n, Qls: /dev/xxx: No such file or directory; @% W. X" R' x
[WJ2440]# insmod first_drv.ko ( I8 q6 Z5 S$ B: n3 U8 U
[WJ2440]# lsmod
3 Z" k/ c! n/ N8 H  Nfirst_drv 1912 0 - Live 0xbf000000
" K4 s( |: F" E) x[WJ2440]# ls -l /dev/xxx
4 s, p) Q  c% A& b  S; tcrw-rw----    1 root     root      252,   0 Jan  1 23:17 /dev/xxx
6 A4 L" |: v0 H) _7 K[WJ2440]# cat proc/devices 2 O( c' v  m# C3 k" V/ z0 z3 _
Character devices:2 h% i5 c) r0 m+ }, P
  1 mem
2 k2 @/ Z' B% b  }) z  4 /dev/vc/0
0 {- a9 ]7 R- ]9 k7 ?' L( q  4 tty
2 r2 Z$ u! o# X* ^& [  5 /dev/tty; I: r/ b% j: M9 }
  5 /dev/console- z' F7 r7 ~' Z3 G+ A0 z* _
  5 /dev/ptmx
! f1 \$ q7 `2 U  7 vcs
( W7 _% L/ u3 v  X) v 10 misc
- @9 h% d; Q+ `# |9 p5 B! n: ^: Z 13 input
) ~1 k3 T* I5 s6 }; A- v 14 sound/ L7 f% K6 \+ t. K  [
29 fb1 J0 e. Q% }4 C. `( l8 Q
81 video4linux. A9 ^- n* r8 d# I% J) t  A
89 i2c
' K2 Q& S  X7 l9 n9 N( D' F 90 mtd1 O3 \) V6 Q' r) }
116 alsa
( ^* k- d3 c, M, k% s4 T128 ptm
" F) M6 C  @/ K# m7 `: M136 pts1 O3 s# v9 R0 m$ L1 B4 m) B' x3 e+ i
180 usb: c5 m0 c5 ^" Q7 K4 Y- O
188 ttyUSB
4 m  a4 g# Y: o5 F1 Y+ h4 }189 usb_device
0 k( D0 ~. L1 x' k) i$ J204 tq2440_serial3 {/ C  q" C2 r, K4 X, \3 A' _
252 first_drv
) p+ ]) [$ R' W253 usb_endpoint+ k' d, ^+ Z' Y: z5 c
254 rtc5 y) [# x! ~" n# p5 G( T& q: l6 Q

& K; l' V6 Q4 o' K' r% Z5 A$ VBlock devices:
% }) a8 z% D' c& V! V; _259 blkext
1 X( H" V# @2 I/ S5 _0 v% L  7 loop
9 D. Y( d1 W6 e. S' n) G. v" q$ {  8 sd
$ o0 r$ w6 f' k 31 mtdblock8 ^9 J( |# f) p- w- J- [) O6 a
65 sd
2 u+ r8 h1 w, I. W 66 sd2 W" q( F* |& U' W
67 sd
4 N  A2 }3 A( X! b5 M6 y' A/ y6 J 68 sd+ k2 N( v# t  o7 e; Z( I* l- J. h
69 sd- K- O4 `9 s0 m6 M7 D
70 sd
! z6 b# H& i1 }$ |- [ 71 sd
" b7 Z* W. `$ |, e% A6 ?! e; O128 sd
' P; Z, v1 Z2 q! P) _129 sd
! n0 d0 F% Q2 `3 Z+ {+ z% f130 sd
7 r( c" B8 D# _; S. N# L/ q1 k' L4 ]131 sd
1 w& H1 |2 y0 L* |1 |) _" I/ i132 sd4 ~/ o' r) P5 S' b( b, p
133 sd
  G  Y6 d% T$ o) Q6 Q  ~7 e0 j134 sd
+ d2 a4 E9 Z0 s" c135 sd
9 U4 o2 k2 e' L6 I9 Z: M4 o- a3 v179 mmc
: ?8 @/ f+ R  `6 p% S# z* Q3 P[WJ2440]# cd /sys/class/
* ~. Z! b9 J3 o1 z0 ^[WJ2440]# ls
& @: ~+ k% I" Z* [/ ibdi           i2c-adapter   misc          scsi_device   usb_endpoint3 h, y: D# Q3 w& q* d+ L
block         i2c-dev       mmc_host      scsi_disk     usb_host( s  o& s+ e$ V
firmware      ieee80211     mtd           scsi_host     vc
. Q' ~0 Y5 v; Ffirstdrv      input         net           sound         video4linux8 j/ y/ e) I- y* H) Z: c- |3 ?" Q
graphics      mem           rtc           tty           vtconsole' c* E+ p1 L$ S" C, Y0 g; F% G8 |1 M8 T
[WJ2440]# cd firstdrv/
/ [7 A+ I9 [6 R2 M# W4 b) [! {[WJ2440]# ls& d$ ^/ Y2 y. J3 w
xxx
* {$ F( Q' u0 X[WJ2440]# cd xxx/) U) ^: M$ p( e( S* ]
[WJ2440]# ls 3 I) ?9 F& a( @! z/ v0 T
dev        subsystem  uevent
0 K1 y: @) Q2 c[WJ2440]# cat dev
5 Z6 ^7 e5 r8 G252:0
8 b; ^; G/ Y+ Z0 F" P[WJ2440]# cat uevent
2 E( [& \' i, DMAJOR=252
# Q$ t; w9 p, H, V. D1 }& ~: H1 jMINOR=0
# K: R5 H7 W: u) b/ d" @[WJ2440]# cd /   $ j5 C, y, F: e
[WJ2440]# ./first_test
$ O7 `6 l7 U: j. cfirst_drv_open
9 h. o! |3 @* \first_drv_write& g$ _! D0 W( ~) t0 Q  {" T
[WJ2440]#
' F) o5 E- K2 Y0 Q" I0 u+ c3 D" T
0 h9 j$ q% v* b9 L3 s- ~: b

# U) }) I- I. H/ ^7 j' L9 p

该用户从未签到

2#
发表于 2020-4-27 13:21 | 只看该作者
linux字符驱动之自动创建设备节点
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-10-26 12:42 , Processed in 0.140625 second(s), 23 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表