linux設(shè)備驅(qū)動(dòng)歸納總結(jié)(十):1.udev&misc
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
不知不覺(jué)我的總結(jié)已經(jīng)寫得七七八八了,這一章節(jié)只是補(bǔ)充一下兩個(gè)知識(shí)點(diǎn):動(dòng)態(tài)創(chuàng)建設(shè)備節(jié)點(diǎn)和雜設(shè)備類的注冊(cè)。
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
一、動(dòng)態(tài)創(chuàng)建設(shè)備節(jié)點(diǎn)——udev
之前加載字符型設(shè)備后是通過(guò)命令mknod來(lái)創(chuàng)建設(shè)備節(jié)點(diǎn)的。在2.6內(nèi)核中,有一個(gè)名叫udev的后臺(tái)程序,它通過(guò)讀取/sys/class的信息,一旦添加的新的設(shè)備,該后臺(tái)程序就會(huì)自動(dòng)創(chuàng)建設(shè)備節(jié)點(diǎn)。
一、要使用動(dòng)態(tài)創(chuàng)建設(shè)備節(jié)點(diǎn),首先要運(yùn)行udev后臺(tái)程序。
在嵌入式下有兩種方法:
1、移植udev到嵌入式系統(tǒng)中。
2、在編譯busybox時(shí)加入mdev。
mdev可以理解是udev的精簡(jiǎn)版,在這里我就不介紹如何加入mdev,僅僅介紹udev的移植。
首先:進(jìn)入到udev的目錄,我在附件中提供了udev的源文件:
root@xiaobai-laptop:/nfsroot/review_driver/10th_udev_misc/udev/tools/udev-096#
pwd
/nfsroot/review_driver/10th_udev_misc/udev/tools/udev-096
接著修改Makefile的兩處:
line 96 prefix =
/nfsroot //指定udev安裝路徑,安裝到我們的跟文件系統(tǒng)中
linr 114 CROSS_COMPILE =
arm-linux- //指定編譯工具
然后編譯并安裝:
make
make install
最后在跟文件系統(tǒng)的/nfsroot/etc/init.d/rcS加上三句話,讓系統(tǒng)啟動(dòng)后運(yùn)行udev后臺(tái)程序:
mount -t tmpfs tmpfs /dev
/sbin/udevd -d
/sbin/udevstart
移植udev后,系統(tǒng)啟動(dòng)是就會(huì)自己?jiǎn)?dòng)udev程序。
二、接著就是在代碼中使用動(dòng)態(tài)創(chuàng)建函數(shù)了。
udev的動(dòng)態(tài)創(chuàng)建是通過(guò)讀取/sys/class的信息來(lái)實(shí)現(xiàn)的。所以,首先是要?jiǎng)?chuàng)建一個(gè)類:
struct class *class_create(struct
module *owner, const char *name)
owner用于指定該類的所屬,一般填寫THIS_MODULE。
name是指定該類該/sys/class/目錄下的目錄名字。
同樣的,該操作有可能出錯(cuò),需要檢驗(yàn)返回值。
類創(chuàng)建成功后會(huì)在/sys/class創(chuàng)建一個(gè)以name命名的目錄。
類的注銷使用以下函數(shù):
void class_destroy(struct class
*cls)
創(chuàng)建類后,就可以調(diào)用以下函數(shù)注冊(cè)類設(shè)備,將設(shè)備加入到指定的類中,這樣udev就可以才class目錄下讀取信息后動(dòng)態(tài)創(chuàng)建設(shè)備節(jié)點(diǎn)了:
/*drivers/base/core.c*/
1386 struct device
*device_create(struct class *class, struct device *parent,
1387 dev_t devt,
void *drvdata, const char *fmt, ...)
class是用于指定所屬的class。
parent用于指定設(shè)備的父設(shè)備,一般填NULL就可以了。
Devt用于指定該設(shè)備的設(shè)備號(hào)。
drvdata用于指定class下的數(shù)據(jù),一般也不用傳。
fmt就是動(dòng)態(tài)創(chuàng)建的設(shè)備文件的名字,一般格式:"%s",
"test_led"。
設(shè)個(gè)函數(shù)成功調(diào)用會(huì)在/sys/devices/virtual的對(duì)應(yīng)總線下創(chuàng)建一個(gè)test_led的目錄,并且軟連接到/sys/class對(duì)應(yīng)的總線目錄下。
使用以下函數(shù)注銷類設(shè)備:
void device_destroy(struct class
*class, dev_t devt)
注意:上面的兩步并沒(méi)有真正創(chuàng)建設(shè)備文件,只有在udev讀取/sys/class信息后發(fā)現(xiàn)tesl_led,才會(huì)真正創(chuàng)建設(shè)備文件。
先來(lái)來(lái)個(gè)代碼,這是我之前寫的簡(jiǎn)潔版led驅(qū)動(dòng),添加了動(dòng)態(tài)創(chuàng)建設(shè)備文件功能:
/*10th_udev_misc/udev/1st_udev/test.c*/
7 #include
<linux/device.h>
//需要包含該頭文件
10 struct
class *my_class;
。。。。。
62 int test_init(void)
63 {
64 //devmodel class create
65
my_class = class_create(THIS_MODULE, "test_class");
//創(chuàng)建class
66 if(IS_ERR(my_class)){
67 printk("create
cleaa wrong!\n");
68 return -1;
69 }
70
device_create(my_class, NULL, MKDEV(253, 0), NULL, "%s",
"test_led"); //根據(jù)class和設(shè)備號(hào)創(chuàng)建設(shè)備
71
72 register_chrdev(253, "udev
led", &led_fops);
73 led_init();
//ioremap的地址映射
74 led_config();
//gpio_led的配置
75
76 return 0;
77 }
78 void test_exit(void)
79 {
80 iounmap((void *)virt);
//注銷虛擬地址的映射
81 unregister_chrdev(253, "udev
led"); //注銷設(shè)備節(jié)點(diǎn)
82
device_destroy(my_class, MKDEV(253, 0)); //注銷類設(shè)備
83
class_destroy(my_class); //注銷類
84 printk("bye\n");
85 }
接下來(lái)驗(yàn)證一下:
[root: 1st_udev]# insmod test.ko
//加載驅(qū)動(dòng)
[root: 1st_udev]# ./app on
//燈亮
[root: 1st_udev]# ./app off
//燈滅
[root: 1st_udev]# cat /proc/devices
//查看一下
Character devices:
1 mem
。。。。。
136 pts
204 s3c2410_serial
253 udev
led
//設(shè)備被注冊(cè)了
254 rtc
[root: 1st_udev]# cd /
[root: /]# find -name
"*test_led*"
//查找test_led相關(guān)文件
./sys/devices/virtual/test
class/test_led
///device/virtule目錄下有test_led目錄
./sys/class/test
class/test_led
//并且有類test_class
./dev/test_led //動(dòng)態(tài)創(chuàng)建了test_led設(shè)備文件
[root: 1st_udev]# ls -l
/sys/class/test\ class/test_led
lrwxrwxrwx 1 root root
0 Jan 1 08:29 /sys/class/test class/test_led ->
../../devices/virtual/test class/test_led
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
二、雜設(shè)備——misc
簡(jiǎn)單的說(shuō),雜設(shè)備就是內(nèi)核自動(dòng)幫你分配設(shè)備號(hào)并且自動(dòng)創(chuàng)建設(shè)備文件。
1、自動(dòng)分配設(shè)備號(hào),是指所有注冊(cè)為雜設(shè)備的設(shè)備的主設(shè)備號(hào)為10,而次設(shè)備號(hào)內(nèi)核自動(dòng)分配。
2、自動(dòng)創(chuàng)建設(shè)備文件是指,內(nèi)核會(huì)使用udev(前提是你已經(jīng)移植udev),動(dòng)態(tài)創(chuàng)建設(shè)備節(jié)點(diǎn)。
方法很簡(jiǎn)單:需要包含頭文件:linux/miscdevice.h 1、定義雜設(shè)備結(jié)構(gòu)體:
36 struct miscdevice {
37 int minor;
38 const
char *name;
//設(shè)備文件的名字
39 const
struct file_operations *fops;
//指定該設(shè)備的fops結(jié)構(gòu)體
40 struct list_head list;
41 struct device *parent;
42 struct device *this_device;
43 };
紅色標(biāo)記的內(nèi)容是我們必須要自己填寫的,其他部分可以由內(nèi)核自己分配。
2、定義結(jié)構(gòu)體后使用使用一下函數(shù)注冊(cè)和注銷:
int misc_register(struct miscdevice
* misc);
//注冊(cè)
int misc_deregister(struct
miscdevice *misc);
//注銷
注冊(cè)操作會(huì)失敗,建議檢查返回值。
看代碼:
/*10th_udev_misc/misc/1st_misc/test.c*/
58 static struct file_operations
led_fops = {
59 .ioctl = led_ioctl,
60 };
61
62 static
struct miscdevice misc_led = { //雜設(shè)備
63
.name = "test_led",
64
.fops = &led_fops,
65 };
66
67 int test_init(void)
68 {
69
misc_register(&misc_led); //注冊(cè)雜設(shè)備
70
71 led_init();
//ioremap的地址映射
72 led_config();
//gpio_led的配置
73
74 return 0;
75 }
76 void test_exit(void)
77 {
78
misc_deregister(&misc_led); //注銷雜設(shè)備
79 iounmap((void *)virt);
//注銷虛擬地址的映射
80 printk("bye\n");
81 }
再看效果
[root: 1st_misc]# insmod test.ko
[root: 1st_misc]# cat /proc/devices
Character devices:
1 mem
4 /dev/vc/0
4 tty
5 /dev/tty
5 /dev/console
5 /dev/ptmx
7 vcs
10
misc
//創(chuàng)建的設(shè)備在misc中
[root: 1st_misc]# lsmod
test 2212 0 - Live 0xbf000000
[root: 1st_misc]# ls -l
/dev/test_led
crw-rw----
1 root root 10, 0 Jan 1 08:05 /dev/test_led
//自動(dòng)創(chuàng)建的設(shè)備節(jié)點(diǎn)主設(shè)備號(hào)為10
[root: 1st_misc]# ./app on
//亮燈
[root: 1st_misc]# ./app off
//滅燈
[root: 1st_misc]# cd
/
//查看test_led相關(guān)文件
[root: /]# find -name "*test_led*"
./sys/devices/virtual/misc/test_led
./sys/class/misc/test_led
//發(fā)現(xiàn)注冊(cè)到misc類中
./dev/test_led
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
三、總結(jié)
這節(jié)介紹了如何動(dòng)態(tài)創(chuàng)建設(shè)備文件和如果創(chuàng)建雜設(shè)備類驅(qū)動(dòng)。
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
源代碼: 10th_udev_misc.rar
|