a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 356|回复: 3

[综合辅导] Linux自动创建设备节点

[复制链接]
发表于 2012-8-4 12:07:07 | 显示全部楼层 |阅读模式
在驱动用加入对udev的支持主要做的就是:在驱动初始化的代码里调用class_create(…)为该设备创建一个class,再为每个设备调用device_create(…)( 在2.6较早的内核中用class_device_create)创建对应的设备。- x3 V9 v- t  M7 \) }) s7 f1 |
    & x8 b7 @' H5 L7 {  B
    内核中定义的struct class结构体,顾名思义,一个struct class结构体类型变量对应一个类,内核同时提供了class_create(…)函数,可以用它来创建一个类,这个类存放于sysfs下面,一旦创建好了这个类,再调用 device_create(…)函数来在/dev目录下创建相应的设备节点。这样,加载模块的时候,用户空间中的udev会自动响应 device_create(…)函数,去/sysfs下寻找对应的类从而创建设备节点。
$ A$ c/ h. m. v7 Q* ]    1 l! z6 v! b- f9 r
    struct class定义在头文件include/linux/device.h中class_create(…)在/drivers/base/class.c中实现device_create(…)函数在/drivers/base/core.c中实现class_destroy(…),device_destroy(…)也在/drivers/base/core.c中实现调用过程类似如下:& A* r$ O" |* n) m
    7 L/ N" f, B. R% Q( Y
    static struct class *spidev_class;) y9 Z; E4 v4 M2 l) I" y
   
- W% g+ N& }- c. Q5 m& U" Q- d    /*-------------------------------------------------------------------------*/( C0 I% B+ Z. F" E/ y, t! w
   
( U7 w0 S7 V! B0 I8 A# Y    static int spidev_probe(struct spi_device *spi)+ G# {, @7 E6 X! z" E3 d; h  T% r8 b
    ; D! S- G( h3 P8 k+ I$ i
    {
6 n1 p  f: w$ F   
1 ~6 [4 D4 i2 `3 k% I- E    …2 C3 S, `% q3 n1 N2 L" A7 Z
    7 I6 W. K( k1 e' q
    dev = device_create(spidev_class, &spi->dev, spidev->devt,
5 D  T( Q: T6 z7 N+ E    9 H" m! `/ t8 K" B6 S  \
    spidev, "spidev%d.%d",
, K$ U& J; S; z5 [& L   
' m' n$ z4 t/ k6 [2 p    spi->master->bus_num, spi->chip_select);
) @& H! Y7 \0 S    & c- J$ l) T, [0 j6 Z9 M% }8 j
    …2 ~5 q+ z0 m- A, l/ G+ i- M& ?
    . B! x: a5 g) J; K
    }
" B/ t" h+ K0 S7 @/ n   
5 i7 N6 B+ K* G% h" _) O2 O    static int spidev_remove(struct spi_device *spi)/ i' h' r2 ~* O( d0 Q
    # e# n* O- o( W- ?8 q
    {
* B7 Y/ Z* ?& p& |7 p- i    , q: p0 Z) R1 |
    ……
( M1 @1 P8 J3 X4 _; L9 S   
, L! x9 v2 {: s    device_destroy(spidev_class, spidev->devt);
9 u. l: Q* ]% [0 S4 U   
1 w5 _; c9 p! x! b$ ?% M1 P    ……7 ?* X4 I6 \5 P7 A5 o
    7 {' p# q. K% h0 z0 _
    return 0;
: P  m) q6 N! w: y+ q- C. ?    3 U2 n' \+ _( w3 j
    }" g& U3 G2 }+ M6 Z7 z2 O
    1 [+ M2 ]2 o( Y% q1 m' t
    static struct spi_driver spidev_spi = {) b" g# y- r0 r5 B1 D4 F" p. z8 V
    , x8 \& [  n' t7 q- o2 ?7 V
    .driver = {  y, X: j( s: ^
   
/ h/ s' F8 `$ l0 T- A/ b    .name =        "spidev",  X( ^8 k* t# [3 c  f
    : h8 n+ L% e6 U! l
    .owner =    THIS_MODULE,
7 e% \$ W+ ~/ t! d7 T   
3 y' O! s9 X$ p7 G4 y- m* |% `    },8 q3 G" W3 ?/ q! t; O
   
9 J) k1 j* x+ S    .probe =    spidev_probe,$ t0 j2 }5 }; w& Q8 C
   
2 d' n8 D. {  q+ ^( z    .remove =    __devexit_p(spidev_remove),
+ E/ W7 Z. O$ `$ M+ c9 S4 f- D   
% v: e' ^- ]( s; S5 o3 V+ U" f% b    };
) z4 f1 l: J7 H3 u1 o/ E4 w2 N    3 v2 n: v3 n  m. |8 D
    /*-------------------------------------------------------------------------*/
7 w9 u; B( K" w9 j: a    ' Q9 Q3 E9 K$ R" z
    static int __init spidev_init(void)
" b- O8 X$ y: V% R    6 z  X  s2 u: {/ ?+ D# l
    {
回复

使用道具 举报

 楼主| 发表于 2012-8-4 12:07:08 | 显示全部楼层

Linux自动创建设备节点


- @0 Y* B$ G# c2 Y0 f   
, ?7 G$ L0 y* D6 ]' k    spidev_class = class_create(THIS_MODULE, "spidev");
7 E: Z/ D. T# H  X* O   
2 M$ V: g; p6 y+ ^; K# m8 V* ~' M    if (IS_ERR(spidev_class)) {+ \) U1 H- _2 f9 Y/ @1 q
    8 |5 m  X6 ]3 P
    unregister_chrdev(SPIDEV_MAJOR, spidev_spi.driver.name);' V- K  j% }# K/ k
    7 O9 K# t' K# B$ l8 U4 v+ r9 h
    return PTR_ERR(spidev_class);
9 C8 F. M8 ^8 P    2 @& K  p3 }; V" [/ v% P
    }
! ~* ~9 N( I3 h+ D2 n/ e0 u    . R3 H' e" [, G7 w7 H' J
    …
% I2 t3 t% g3 k/ q6 ~- W+ F# j2 v3 x   
# [$ X) y1 C0 X1 L+ g    }, R$ M$ [$ E6 [8 i- s0 z8 z0 h
    , Z: e' u( Y0 w- R- c: \
    module_init(spidev_init);
2 z9 H2 M2 z! [  O  R1 `! [    , X; p0 ~" J( @$ x$ P
    static void __exit spidev_exit(void)# w2 N, i4 X' h
    5 G- u# g, G, P  V8 Q8 S/ s
    {
! |8 T( a* c; T/ ?5 Y: @) `7 W, n. c    % V" E1 i7 O' `* F
    ……
! p2 p0 |5 v0 u/ u! ?    3 j+ I8 Y1 f5 M8 R+ h
    class_destroy(spidev_class);* @' G- r7 c) s' k' H
   
, C& ]6 q- C5 F; c# A# V    ……
3 G" A/ B+ ]. T5 i" _- s# c. h   
2 M/ G. R. z" r5 L* G* L* I: q% u    }3 M- R/ I; ?/ w1 E6 n+ s8 ~9 N* r
   
2 Y6 Z* F9 k! Q2 b4 A    module_exit(spidev_exit);1 I6 @/ g& d9 p8 u0 _
    ! [# e4 V& P+ Y
    MODULE_DESCRIPTION("User mode SPI device interface");, D9 d8 r% |. @6 o& v8 i) e( f
   
9 @+ b' j0 J5 S7 w  Z6 ?    MODULE_LICENSE("GPL");2 J- Q; k0 S* P4 B- T
   
& P4 K4 F! n6 A; ?. n; R    下面以一个简单字符设备驱动来展示如何使用这几个函数
) ^  m' C* W4 Q- Z5 j' K   
$ x2 B: E) ]  b6 {' S, x+ y    #include
" n% A; z% e' N# f; k5 `    ; @% @' d8 x6 i  }- ?) f* A
    #include
; k( ~9 n+ F2 z2 z, C$ g( u" @6 m   
/ ^# R  ]1 @  M/ D3 N    #include % \6 y9 }4 t" u/ g! P8 {$ o
    0 Q$ R* v6 k* W9 c. [* }
    #include + X; x' s- ^; \* V2 }
    , [8 A0 V, c5 H( s- p" _7 E" F1 J
    #include ' |& N: V$ y+ ]
   
( p. R6 @8 K6 q    #include
* i% E6 P& u& r8 S* p0 W! N    / ?0 A. O' [- R( d# u! D* C
    int HELLO_MAJOR = 0;
: S( L; a( o  o( Q/ G4 x$ ~    . T. v7 M6 s- }% {# h; `
    int HELLO_MINOR = 0;
7 F0 n1 G* n9 b   
8 l0 {3 p% E! [) K1 l, E    int NUMBER_OF_DEVICES = 2;
8 B( x/ T; H0 d- Q% M; ?    & p% U" v; T. l7 q) c3 d7 r
    struct class *my_class;
0 l+ J; n- }/ _% a. d( @    ( ]7 C- s" R: [' v
    struct cdev cdev;
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-8-4 12:07:09 | 显示全部楼层

Linux自动创建设备节点

dev_t devno;
- o! b# D7 J# f7 P" B. Y+ x& ~    ' s1 o* b, n# P2 C0 Y; r
    struct file_operations hello_fops = {7 N8 |# E( t% L; `( @$ {; E
   
, Y- c' ?! B5 k, s1 R5 o7 y+ ~! C    .owner = THIS_MODULE
5 H2 G1 d, t/ a  M) u" Q; r9 l   
7 X! A% N) B& p    };/ M, j% h& F$ v' F. @
   
* l0 _8 U- {# c& x& P% i6 ~* Z    static int __init hello_init (void)
0 s/ R: ^9 x! b6 ]9 ]8 }% z6 M   
1 O1 O8 X- B- ]5 }9 W6 C4 [2 Q% _    {
' r$ p  j5 [* P: _' V2 {- o$ b   
+ M- c0 B7 Q' H# w4 ~    int result;7 }' V( ~- p. i- R
    3 ?6 f- J. g9 M4 j" Z
    devno = MKDEV(HELLO_MAJOR, HELLO_MINOR);, d; S3 e9 z+ w
   
4 Y% m4 a' @8 I/ D    if (HELLO_MAJOR)
* o$ \, r2 q! c' Z; k  I    2 a/ n9 k7 M: T4 i' s5 Y
    result = register_chrdev_region(devno, 2, "memdev");; I1 H8 T# a$ ~! U2 V2 c+ n2 d
   
8 s" S( k. ?0 V# O5 l' O' N5 j    else
8 ?1 n& R, J6 s. w" Z   
( m: F- x9 e; ?% Z4 r' W; M0 P    {
: e" {' E, i2 Q# g9 w4 {: z/ w, ^& G   
* s* _) R+ M: a+ z    result = alloc_chrdev_region(&devno, 0, 2, "memdev");
5 c) Y* [3 `. p' l5 E1 ~! M# o% K3 v    ' i& g* F( x: [0 F
    HELLO_MAJOR = MAJOR(devno);9 u  y9 n4 X! M8 n9 y
   
- y% f) A4 [" C6 e    }
* q- j, Q( x2 l! I( I. f   
7 Y% j& r& S6 z# D. e: ?    printk("MAJOR IS %d\n",HELLO_MAJOR);
) V$ E. r0 h- }/ @$ L' `    + F; o& T- s0 g* g7 V3 ?; Z
    my_class = class_create(THIS_MODULE,"hello_char_class");  //类名为hello_char_class
. l4 r+ O) x0 R% J0 o( F- w" k0 N    ' \+ A  \  l$ d; k" r; C+ S
    if(IS_ERR(my_class))
& E6 }- i4 |: k" @: O   
0 Y3 V! \; Q8 y* |; g    {8 O: [3 z' j, r, o* H8 H* p2 m
   
& ?" K, L9 V1 J! b    printk("Err: failed in creating class.\n");
3 i& s) P5 R2 r( ^, y, y8 @    4 G: ^* a% l0 N: ?) g
    return -1;
( l' ]% ], l+ W& o6 H8 H8 I* B    ) G2 u/ ~0 j! a8 V! N
    }
8 j" L: Y4 [# \  L8 a  m5 n   
8 {8 q( ^! h! M" C7 x    device_create(my_class,NULL,devno,NULL,"memdev");      //设备名为memdev0 J6 b$ j- N2 q
    ; p* a9 t3 q; C% p! J4 b* E
    if (result
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-8-4 12:07:10 | 显示全部楼层

Linux自动创建设备节点

}
; a# s( Y/ n- x' K    * i, a- p7 z: K& c  \
    static void __exit hello_exit (void)" p' Z" P1 F$ P+ a7 N7 c# U3 j6 A
   
! w  h: y' `4 q3 M; Y+ y    {# p) Y& M( C, Y) l+ ^" o' l" u
   
6 X! o0 \: ?0 [- I    cdev_del (&cdev);
+ c8 R" n* U! f4 a3 {7 C   
9 I7 f1 x) j) z0 a- d% [. P    device_destroy(my_class, devno);         //delete device node under /dev//必须先删除设备,再删除class类; l! P, \7 ]" S6 b# F. b3 U. u
    5 ^7 u, q0 N* b$ d
    class_destroy(my_class);                 //delete class created by us+ D  b) \* w+ I' Y
    . w& u+ c; w' a1 K( i- A
    unregister_chrdev_region (devno,NUMBER_OF_DEVICES);
- F3 {! k* }) d' Y3 N6 S+ F3 U   
) T% k) Z" A! F/ f: I+ \    printk (KERN_INFO "char driver cleaned up\n");
4 D& x  q& C! _4 e   
  C4 V5 d7 k! }: V+ Z- _( g; Z    }
2 ?, O. K# b/ }6 E* p    / v1 D8 ^$ Z* I: w
    module_init (hello_init);
( S' ^$ M- S; Y4 A+ v6 t2 F3 q8 S    8 \$ x, ]  y. [$ _8 U0 k
    module_exit (hello_exit);
4 i$ a2 Y: @5 U! n9 ]+ E. q   
! J/ C7 s7 _" n# m    MODULE_LICENSE ("GPL");: j8 m) v, e0 F
    7 p! x) F7 t' T. q$ D8 ~
    这样,模块加载后,就能在/dev目录下找到memdev这个设备节点了。5 z; W3 Y0 h/ ~/ l; b3 x1 l# c9 x
   
. S" y8 `: y0 s8 P* G3 r0 H% E    例2:内核中的drivers/i2c/i2c-dev.c
5 R" q7 q8 H! ?    2 J; y1 {- w! a) z9 m
    在i2cdev_attach_adapter中调用device_create(i2c_dev_class, &adap->dev,
5 ~+ a- `3 G( G& A$ O  a  G   
- [7 R# u% S5 ^$ s1 S! g    MKDEV(I2C_MAJOR, adap->nr), NULL,
  a) S- Z+ f$ ?  ?4 Q6 |   
% c! R7 W- l! }* T    "i2c-%d", adap->nr);  g% J) @1 q' \
   
( W" ?, w$ j  T; G; i0 j1 d. S    这样在dev目录就产生i2c-0  或i2c-1节点( K7 T0 }* c! S1 |1 _
      f# N# ]0 ]4 F  F9 B: z
    接下来就是udev应用,udev是应用层的东西,udev需要内核sysfs和tmpfa的支持,sysfs为udev提供设备入口和uevent通道,tmpfs为udev设备文件提供存放空间! ]. m3 Z! o* M5 r3 y2 y# s
   
# \1 K. G. Q+ w0 z) H    udev的源码可以在去相关网站下载,然后就是对其在运行环境下的移植,指定交叉编译环境,修改Makefile下的CROSS_COMPILE,如为mipsel-linux-,DESTDIR=xxx,或直接make CROSS_COMPILE=mipsel-linux-,DESTDIR=xxx 并install把主要生成的udevd、udevstart拷贝rootfs下的/sbin/目录内,udev的配置文件udev.conf和rules.d下的rules文件拷贝到rootfs下的/etc/目录内,并在rootfs/etc/init.d/rcS中添加以下几行:
4 r( l7 i$ [* Z1 v) r2 @  B    * J. G8 ]5 S. C3 N
    echo "Starting udevd…"  o7 c& b/ r* u* U; z7 e* Y
    9 m/ t! H/ Y: s) z+ l5 ^# |
    /sbin/udevd --daemon" ~& A. {# P- h5 S# m  K1 V1 |* n
    0 j4 h* s7 X7 P1 j" a
    /sbin/udevstart6 m3 y. [$ o1 A! Q: i3 \" ^
    7 ^7 I/ h! z8 d6 a
    (原rcS内容如下:* ]5 r  K: v5 w! s! R
   
* J, D* ~2 K( J3 R+ [    # mount filesystems
, q. U+ ]- F: e# b. T   
& k( S* s6 x2 S& Q( c! q+ g    /bin/mount -t proc /proc /proc
9 Y9 C# j' v% e& K3 Z4 D   
4 R7 C8 r7 {0 k: E& r    /bin/mount -t sysfs sysfs /sys
5 I9 f0 S7 ^8 a* ~, r9 S/ s   
4 ^- ?/ V' _6 r9 d* W    /bin/mount -t tmpfs tmpfs /dev
5 g  x  R: \) ]: N   
9 d( p6 L' a$ i, Q: h6 X    # create necessary devices
' c- K* v/ A; X6 q( l1 H   
$ ]2 i- i, @1 R! p4 X- e& ]    /bin/mknod /dev/null c 1 35 w! s" J2 s9 E% s
   
$ j( J2 w& t# k3 z3 M  K( a    /bin/mkdir /dev/pts
! i- S8 h4 ]0 ?5 Z7 e: j    / o/ l1 v4 G: s
    /bin/mount -t devpts devpts /dev/pts
5 a4 W" _! M' L   
' M4 g' r3 o; L! w1 k( {    /bin/mknod /dev/audio c 14 40 {4 f6 X9 c  i. ]* P4 ?- T' f
   
- {  e; K- l( j( S    /bin/mknod /dev/ts c 10 16- {! D1 e; j% u1 C2 Y
   
9 |9 h# a8 A% f( U, }0 q$ E  n1 b    )
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Woexam.Com ( 湘ICP备18023104号 )

GMT+8, 2024-5-21 08:24 , Processed in 0.350251 second(s), 27 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

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