亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 3225 | 回復(fù): 0
打印 上一主題 下一主題

linux設(shè)備驅(qū)動歸納總結(jié)(八):2.match.probe.remove [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報(bào)告]
發(fā)表于 2011-02-02 23:13 |只看該作者 |倒序?yàn)g覽
linux設(shè)備驅(qū)動歸納總結(jié)(八):2.總線、設(shè)備和驅(qū)動的關(guān)系


xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

上一節(jié)介紹了總線、設(shè)備和驅(qū)動函數(shù)的注冊,這節(jié)著重介紹它們?nèi)叩年P(guān)系,和上一節(jié)一樣,我模擬一條usb總線,一個usb鼠標(biāo)設(shè)備和一個usb鼠標(biāo)驅(qū)動函數(shù),當(dāng)然,只是名字是usb,里面并沒有實(shí)質(zhì)的操作,只是通過這樣來介紹一下三者之間的關(guān)系。。

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


一、總線、設(shè)備和驅(qū)動函數(shù)在/sys/中的框架


首先要寫三個函數(shù),bus.c、device.cdriver.c。這幾個函數(shù)其實(shí)就是上一節(jié)函數(shù)的精簡版,去掉屬性文件的創(chuàng)建,僅僅保留創(chuàng)建和注銷操作。

第一個函數(shù)是bus.c,加載模塊會創(chuàng)建了一條名叫usb的總線,總線目錄放在/sys/bus/目錄下:

/*8th_devModule_2/1st/bus.c*/

6 struct bus_type usb_bus = {

7 .name = "usb",         //注冊成功后將在/sys/bus目錄下看到目錄usb

8 };

9

10 static int __init usb_bus_init(void)

11 {

12 int ret;

13 /*總線注冊,必須檢測返回值*/

14 ret = bus_register(&usb_bus);

15 if(ret){

16 printk("bus register failed!\n");

17 return ret;

18 }

19

20 printk("usb bus init\n");

21 return 0;

22 }

23

24 static void __exit usb_bus_exit(void)

25 {

26 bus_unregister(&usb_bus);

27 printk("usb bus bye!\n");

28 }

第二個函數(shù)是device.c,加載模塊會創(chuàng)建目錄/sys/device/usb_device來管理這個usb設(shè)備。

由于該設(shè)備指定了所屬的總線是usb_bus,所有會在/sys/bus/usb/device目錄下創(chuàng)建一了指向usb_device的軟連接。

同時,在卸載模塊時,usb_deivce被刪除,內(nèi)核自動調(diào)用release函數(shù),現(xiàn)實(shí)當(dāng)中release函數(shù)應(yīng)該做一些卸載設(shè)備的相關(guān)操作,但是我的usb設(shè)備是我虛擬出來的,所以release函數(shù)只是打印了一句話。

/*8th_devModule_2/1st/device.c*/

5 extern struct bus_type usb_bus;

6

7 void usb_dev_release(struct device *dev) //卸載函數(shù)沒有干具體的事情

8 {

9 printk("<kernel> release\n");

10 }

11

12 struct device usb_device = {

13 .bus_id = "usb_device",

14 .bus = &usb_bus,                   //指定該設(shè)備的總線,/sys/bus/usb

15 .release = usb_dev_release, //必須要都有release函數(shù),不然卸載時會出錯

16 };

17

18 static int __init usb_device_init(void)

19 {

20 int ret;

21 /*設(shè)備注冊,注冊成功后在/sys/device目錄下創(chuàng)建目錄usb_device并在指定總線

22 * usb_bus的目錄/sys/bus/usb/device創(chuàng)建/sys/device/usb_device的軟連接*/

23 ret = device_register(&usb_device);

24 if(ret){

25 printk("device register failed!\n");

26 return ret;

27 }

28

29 printk("usb device init\n");

30 return 0;

31 }

32

33 static void __exit usb_device_exit(void)

34 {

35 device_unregister(&usb_device);

36 printk("usb device bye!\n");

37 }

第三個函數(shù)是driver.c,加載模塊后會在指定的總線目錄的driver目錄,即/sys/bus/usb/driver目錄下創(chuàng)建一個名叫usb_driver的目錄來管理這個驅(qū)動函數(shù)。

/*8th_devModule_2/1st/driver.c*/

6 extern struct bus_type usb_bus;

7

8 struct device_driver usb_driver = {

9 .name = "usb_driver", ///sys/中的驅(qū)動目錄名字

10 .bus = &usb_bus,      //必須指定驅(qū)動函數(shù)所屬總線,不然不能注冊。

11 };

12

13 static int __init usb_driver_init(void)

14 {

15 int ret;

16 /*驅(qū)動注冊,注冊成功后在/sys/bus/usb/driver目錄下創(chuàng)建目錄usb_driver*/

17 ret = driver_register(&usb_driver);

18 if(ret){

19 printk("driver register failed!\n");

20 return ret;

21 }

22 printk("usb driver init\n");

23 return 0;

24 }

25

26 static void __exit usb_driver_exit(void)

27 {

28 driver_unregister(&usb_driver);

29 printk("usb driver bye!\n");

30 }

接下來看看效果,因?yàn)樵O(shè)備和驅(qū)動的都指定了所屬總線,所以必須先加載總線的模塊。同樣的,在卸載總線的模塊前,必須先把設(shè)備和驅(qū)動的模塊先卸載。

[root: 1st]# insmod bus.ko //先加載bus.ko

usb bus init

[root: 1st]# ls /sys/bus/ //sys/bus目錄下多了一個usb目錄

platform scsi usb

[root: 1st]# insmod device.ko //再加載device.ko

usb device init

[root: 1st]# ls /sys/devices/ //sys/device目錄下多了一個usb_device目錄

platform system usb_device virtual

[root: 1st]# ls -l /sys/bus/usb/devices/ //同時將該目錄軟連接到指定的總線目錄下

lrwxrwxrwx 1 root root 0 Oct 27 13:28 usb_device -> ../../../devices/usb_device

[root: 1st]# insmod driver.ko //加載driver.ko

usb driver init

[root: 1st]# ls /sys/bus/usb/drivers //在指定總線的driver目錄下多了一個usb_driver目錄

usb_driver //但它和設(shè)備的目錄不一樣,它并不是軟連接。

[root: 1st]# lsmod //查看一下當(dāng)前加載的模塊

driver 1256 0 - Live 0xbf00c000

device 1560 0 - Live 0xbf006000

bus 1336 2 driver,device, Live 0xbf000000 //模塊的引用計(jì)數(shù),bus模塊被devicedriver引用

[root: 1st]# rmmod bus //如果你要卸載bus模塊,它會提示出錯,要先卸載driverdevice

rmmod: remove 'bus': Resource temporarily unavailable

[root: 1st]# rmmod driver

usb driver bye!

[root: 1st]# rmmod device //卸載device時,內(nèi)核自動調(diào)用device結(jié)構(gòu)體中指定的release函數(shù)

<kernel> release

usb device bye!

[root: 1st]# lsmod //bus的引用計(jì)數(shù)為0,可以卸載bus

bus 1336 0 - Live 0xbf012000

[root: 1st]# rmmod bus

usb bus bye!

最后來個圖:


xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


二、配對函數(shù)(match)、探測函數(shù)(probe)和卸載函數(shù)(remove)


現(xiàn)在講一下三個函數(shù):


第一個是配對函數(shù)(match),它是總線結(jié)構(gòu)體bus_type的其中一個成員:

57 int (*match)(struct device *dev, struct device_driver *drv);

當(dāng)總線上添加了新設(shè)備或者新驅(qū)動函數(shù)的時候,內(nèi)核會調(diào)用一次或者多次這個函數(shù)。

舉例,如果我現(xiàn)在添加了一個新的驅(qū)動函數(shù),內(nèi)核就會調(diào)用所屬總線的match函數(shù),配對總線上所有的設(shè)備,如果驅(qū)動能夠處理其中一個設(shè)備,函數(shù)返回0,告訴內(nèi)核配對成功。

一般的,match函數(shù)是判斷設(shè)備的結(jié)構(gòu)體成員device->bus_id和驅(qū)動函數(shù)的結(jié)構(gòu)體成員device_driver->name是否一致,如果一致,那就表明配對成功。

所以,bus.c修改如下,貼上修改的代碼:

/*8th_devModule_2/2nd/bus.c*/

6 int usb_bus_match(struct device *dev, struct device_driver *drv)

7 {

8 if(!strcmp(dev->bus_id, drv->name)){

9 printk("match success\n"); //為了配對成功,設(shè)備的bus_id和驅(qū)動的name我都更改為

10 return 1;                             //usb_mouse,詳細(xì)的可以查看device.cdriver.c

11 }else{

12 printk("match failed\n");

13 return 0;

14 }

15 }

16

17 struct bus_type usb_bus = {

18 .name = "usb",                    //注冊成功后將在/sys/bus目錄下看到目錄usb

19 .match = usb_bus_match,

20 };


第二個是探測函數(shù)(probe),它是驅(qū)動函數(shù)結(jié)構(gòu)體中的一個成員:

129 int (*probe) (struct device *dev);

當(dāng)配對(match)成功后,內(nèi)核就會調(diào)用指定驅(qū)動中的probe函數(shù)來查詢設(shè)備能否被該驅(qū)動操作,如果可以,驅(qū)動就會對該設(shè)備進(jìn)行相應(yīng)的操作,如初始化。所以說,真正的驅(qū)動函數(shù)入口是在probe函數(shù)中。

所以,driver.c修改如下:

/*8th_devModule_2/2nd/driver.c*/

8 void init_mouse(void)

9 {

10 printk("init usb mouse\n");

11 }

12

13 int usb_driver_probe(struct device *dev)

14 {//查詢特定設(shè)備是否存在,以及是否能夠才操作該設(shè)備,然后再進(jìn)行設(shè)備操作。

15 //check_mouse(); //自己假設(shè)一下檢查設(shè)備

16 init_mouse(); //usb鼠標(biāo)驅(qū)動的真正入口

17 return 0;

18 }

。。。。。

26 struct device_driver usb_driver = {

27 .name = "usb_mouse", ///sys/中的驅(qū)動目錄名字,為了配對成功,修改為usb_mouse

28 .bus = &usb_bus, //必須指定驅(qū)動函數(shù)所屬總線,不然不能注冊。

29 .probe = usb_driver_probe,

30 。。。。。

31 };


第三個是卸載函數(shù)(remove),它是驅(qū)動函數(shù)結(jié)構(gòu)體中的一個成員:

130 int (*remove) (struct device *dev);

當(dāng)該驅(qū)動函數(shù)或者驅(qū)動函數(shù)正在操作的設(shè)備被移除時,內(nèi)核會調(diào)用驅(qū)動函數(shù)中的remove函數(shù)調(diào)用,進(jìn)行一些設(shè)備卸載相應(yīng)的操作。

所以,driver.c修改如下:

/*8th_devModule_2/2nd/driver.c*/

20 int usb_driver_remove(struct device *dev)

21 {

22 printk("remove mouse driver\n");

23 return 0;

24 }

25

26 struct device_driver usb_driver = {

27 .name = "usb_mouse", ///sys/中的驅(qū)動目錄名字

28 .bus = &usb_bus, //必須指定驅(qū)動函數(shù)所屬總線,不然不能注冊。

29 .probe = usb_driver_probe,

30 .remove = usb_driver_remove,

31 };

接下來就要驗(yàn)證一下了。當(dāng)然,我的函數(shù)里面并沒有真正的硬件操作,僅僅是打印出一句話:

[root: 2nd]# insmod bus.ko //必須先加載總線模塊

usb bus init

[root: 2nd]# insmod device.ko

usb device init

[root: 2nd]# insmod driver.ko

match success //當(dāng)加載了設(shè)備和驅(qū)動的模塊后,內(nèi)核調(diào)用總線的配對函數(shù)

match success //并且配對成功。

init usb mouse //配對成功后內(nèi)核調(diào)用探測函數(shù)probe

usb driver init

[root: 2nd]# rmmod device

remove mouse driver //當(dāng)設(shè)備卸載時,內(nèi)核調(diào)用驅(qū)動函數(shù)中的remove

<kernel> release //同時也會調(diào)用設(shè)備中的release函數(shù)調(diào)用

usb device bye!

[root: 2nd]# rmmod driver

usb driver bye!

又到了舉例時間,程序員最喜歡就是男女關(guān)系,那就以男女關(guān)系舉例:


xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


三、多個設(shè)備和驅(qū)動之間的配對


上面講的內(nèi)容都是一對一的配對,但是如果系統(tǒng)中有多個配對成功,內(nèi)核會如何處理呢?


1、多個設(shè)備對應(yīng)一個驅(qū)動:


下面要講的情況是,如果多個設(shè)備與內(nèi)核中的一個驅(qū)動函數(shù)配對成功時,內(nèi)核會進(jìn)行怎么樣的操作,先看實(shí)例。

為了能夠讓多個設(shè)備配對成功,我將bus.c的配對條件修改了一下:

/*8th_devModule_2/3th/bus.c */

6 int usb_bus_match(struct device *dev, struct device_driver *drv)

7 { //僅僅配對名字的前9個字母是否相同

8 if(!strncmp(dev->bus_id, drv->name, 9)){

9 printk("match success\n");

10 return 1;

11 }else{

12 printk("match failed\n");

13 return 0;

14 }

15 }

同時在device.c的基礎(chǔ)上拷貝了device1.cdevice2.c,三個程序都差不多,可以自己看看。接下來直接看效果:

[root: /]# cd /review_driver/8th_devModule/8th_devModule_2/3th

[root: 3th]# insmod bus.ko //先加載總線

usb bus init

[root: 3th]# insmod driver.ko //再加載驅(qū)動

usb driver init

[root: 3th]# insmod device.ko //當(dāng)加載device.ko時,配對成功

match success

init usb mouse //內(nèi)核調(diào)用驅(qū)動中的probe

usb device init

[root: 3th]# insmod device1.ko //再加載device1.ko,也配對成功

match success

init usb mouse //內(nèi)核有調(diào)用驅(qū)動中的probe

usb device1 init

[root: 3th]# insmod device2.ko //加載device2.ko,配對不成功

match failed

usb device2 init

上面的驗(yàn)證表明,一個驅(qū)動可以對應(yīng)多個設(shè)備。在聯(lián)想起我舉得男人女人——一個男人可以配對多個女人,哈哈。


2、一個設(shè)備對應(yīng)多個驅(qū)動


這個例子中我將driver.c拷貝多了一個driver1.c,兩個程序基本相同,都能配對成功,但看看效果:

[root: 3th]# insmod bus.ko //先加載總線

usb bus init

[root: 3th]# insmod device.ko //再加載設(shè)備

usb device init

[root: 3th]# insmod driver.ko //加載driver.ko

match success //配對成功

match success

init usb mouse //并且調(diào)用了probe

usb driver init

[root: 3th]# insmod driver1.ko //再加載driver1.ko

match success //因?yàn)槊值那?font face="DejaVu Serif, serif">9個字母一樣,所以也會配對成功

usb driver1 init //但不會調(diào)用probe,因?yàn)橐呀?jīng)有一個驅(qū)動跟該設(shè)備配對了。

上面的驗(yàn)證表明,一個設(shè)備只能對應(yīng)一個驅(qū)動


xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


四、總結(jié)


這節(jié)內(nèi)容主要介紹了總線和驅(qū)動中的幾個方法和總線、設(shè)備和驅(qū)動函數(shù)三者之間的關(guān)系。


xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

源代碼: 8th_devModule_2.rar  

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

寫到現(xiàn)在,都差不多踏入新年了,不知道還有沒有人在看博客,預(yù)祝一下新年快樂。總結(jié)還沒寫完,年前任務(wù)沒完成。過年期間繼續(xù)復(fù)習(xí)。

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報(bào)專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP