内核驱动中常见的miscdevice、platform_device、platform_driver
生活随笔
收集整理的這篇文章主要介紹了
内核驱动中常见的miscdevice、platform_device、platform_driver
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
最近在看驅(qū)動(dòng)模型,是越看越糊涂,以前接觸比較多的都是一些字符驅(qū)動(dòng),對(duì)字符驅(qū)動(dòng)的框架有一定的了解。后來(lái)因?yàn)橄朐隍?qū)動(dòng)中實(shí)現(xiàn)設(shè)備文件的創(chuàng)建,又了解了一下,sysfs文件系統(tǒng)和udev設(shè)備文件系統(tǒng),必然就涉及到了驅(qū)動(dòng)模型。可是發(fā)現(xiàn)驅(qū)動(dòng)模型和以前接觸的字符驅(qū)動(dòng)沒(méi)什么聯(lián)系。
比如,以前寫(xiě)字符驅(qū)動(dòng),主要的內(nèi)容就是實(shí)現(xiàn)file_operations結(jié)構(gòu)體里的函數(shù),然后就是申請(qǐng)?jiān)O(shè)備號(hào),注冊(cè)字符設(shè)備,根本就沒(méi)有涉及到設(shè)備驅(qū)動(dòng)模型。而驅(qū)動(dòng)模型里,device_driver根本沒(méi)有涉及到設(shè)備操作的函數(shù)、file_operations等,只有一些電源管理,熱插拔相關(guān)的函數(shù)。platform_device里也主要是resource的管理,所以感覺(jué)兩者根本就沒(méi)關(guān)系,也很奇怪為什么要弄兩套東西來(lái)實(shí)現(xiàn),而且兩者也對(duì)應(yīng)不起來(lái)。
后來(lái)看了一些內(nèi)核中的驅(qū)動(dòng)源碼,發(fā)現(xiàn)很多都是用miscdevice、platform_device、platform_driver實(shí)現(xiàn)的,而且流程很相似:
1、在系統(tǒng)初始化階段注冊(cè)platform_device,主要是添加設(shè)備對(duì)應(yīng)的resource進(jìn)鏈表,以便系統(tǒng)對(duì)設(shè)備占用的資源統(tǒng)一管理;
2、實(shí)現(xiàn)platform_driver并注冊(cè),在這部分,需要實(shí)現(xiàn)的主要有platform_driver結(jié)構(gòu)體中的probe,還有remove、shutdown等一些關(guān)于熱插拔、電源管理方面的函數(shù)。
3、然后在模塊初始化函數(shù)(xx_init)里注冊(cè)platform_driver(platform_driver_register)
其中設(shè)備資源的獲取(platform_get_resource),如IO內(nèi)存、IO端口、中斷號(hào),申請(qǐng)(request),物理地址到虛擬地址的映射(ioremap),misc_device的注冊(cè)(misc_register),時(shí)鐘的獲取(clk_get)及使能(clk_enable)都是在probe函數(shù)里實(shí)現(xiàn)的,probe函數(shù)是在platform_driver注冊(cè),或者新設(shè)備添加時(shí),platform_device和platform_driver匹配(通過(guò)名字)成功后執(zhí)行的,有別于以往接觸的字符驅(qū)動(dòng)里的注冊(cè)流程。
對(duì)于misc_device對(duì)于設(shè)備操作函數(shù)的實(shí)現(xiàn)和字符設(shè)備一樣,都是填充file_operations結(jié)構(gòu)體,然后在模塊初始化函數(shù)里注冊(cè)(misc_register)。
對(duì)于platform驅(qū)動(dòng)模型,似乎就是platform_device負(fù)責(zé)設(shè)備資源,platform_driver負(fù)責(zé)電源管理以及資源的申請(qǐng),中斷的注冊(cè)等設(shè)備初始化及啟動(dòng)有關(guān)的操作,然后就是設(shè)備操作方法(file_operations)的注冊(cè)(misc_register或者cdev_add),cdev或者misc_device就負(fù)責(zé)file_operations。
但是目前還有不少疑問(wèn):
1、設(shè)備號(hào)的申請(qǐng)?jiān)谀睦?#xff0c;它是怎么放到驅(qū)動(dòng)模型里的device結(jié)構(gòu)體中的?
2、platform_driver結(jié)構(gòu)體和其中的device_driver結(jié)構(gòu)體中都有probe、remove、shutdown等,為什么要在外層放重復(fù)的東西,二者有什么關(guān)系和區(qū)別嘛?
3、misc_register實(shí)現(xiàn)里最終和platform_device_register一樣都會(huì)調(diào)用device_add,這樣在設(shè)備驅(qū)動(dòng)模型里不是有兩個(gè)device和device_driver對(duì)應(yīng),而實(shí)際的物理設(shè)備只有一個(gè)嘛?
4、看起來(lái)好像驅(qū)動(dòng)模型是對(duì)實(shí)際的設(shè)備及驅(qū)動(dòng)的抽象,提取它們的信息包裝成內(nèi)核對(duì)象kobject,然后按照它們之間的關(guān)系對(duì)其進(jìn)行分類、分層次管理(建立一棵樹(shù)),借由這些對(duì)象,由系統(tǒng)管理設(shè)備資源的注冊(cè)申請(qǐng)、釋放以及實(shí)際驅(qū)動(dòng)(file_operations)的注冊(cè)時(shí)機(jī)(由此可以實(shí)現(xiàn)熱插拔,即插即用)和電源管理(系統(tǒng)可以根據(jù)設(shè)備樹(shù)來(lái)決定設(shè)備關(guān)閉的順序,device->device_driver->shutdown)。
所以設(shè)備驅(qū)動(dòng)模型中,device只是用來(lái)建立設(shè)備樹(shù),最終會(huì)根據(jù)結(jié)構(gòu)體中的device_driver中的電源管理函數(shù)實(shí)現(xiàn)合理的電源開(kāi)關(guān)順序?
而對(duì)于熱插拔有關(guān)的功能,和device與device_driver的匹配過(guò)程有關(guān),而與設(shè)備樹(shù)層次關(guān)系無(wú)關(guān)?
( 以上是目前想到的不明白的地方,遺漏的地方想起會(huì)再添加。改天找老師好好問(wèn)問(wèn),太復(fù)雜了! )
===============================================
最近研究Linux設(shè)備驅(qū)動(dòng)程序遇到混亂,請(qǐng)大俠過(guò)來(lái)理理頭緒。
Linux設(shè)備模型中:bus_type、device、device_driver
《Linux設(shè)備驅(qū)動(dòng)程序》的linux設(shè)備模型章中說(shuō)到設(shè)備模型中,所有設(shè)備都通過(guò)總線相連。
添加設(shè)備devA,必須指定其device結(jié)構(gòu)體的bus_type域,初始化其他域,然后調(diào)用device_register(&devA),將設(shè)備devA
注冊(cè)到指定總線。
添加該設(shè)備驅(qū)動(dòng)driverA,也必須指定其device_driver結(jié)構(gòu)體的bus_type域,初始化其他域,然后調(diào)用driver_register(&driverA),
將該驅(qū)動(dòng)注冊(cè)到總線上。
如果驅(qū)動(dòng)driverA和設(shè)備devA匹配成功,即調(diào)用probe函數(shù)成功,則建立他們之間的符號(hào)鏈接,即將設(shè)備與驅(qū)動(dòng)捆綁起來(lái)。
而實(shí)際我看Linux源代碼中卻大量使用platform_device,
struct platform_device {? ?? ??
const char? ? ? ? * name;? ?? ???
u32? ? ? ? ? ? ? ? id;? ?? ?? ?? ?? ??
struct device? ? ? ? dev;? ?? ??
u32? ? ? ? ? ? ? ? num_resources;? ???
struct resource? ? ? ? * resource;
};
和
struct platform_driver {? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?
int (*probe)(struct platform_device *);? ?? ?? ?? ?? ?? ?? ?? ?? ?
int (*remove)(struct platform_device *);? ?? ?? ?? ?? ?? ?? ?? ???
void (*shutdown)(struct platform_device *);? ?? ?? ?? ?? ?? ?? ???
int (*suspend)(struct platform_device *, pm_message_t state);? ???
int (*suspend_late)(struct platform_device *, pm_message_t state);
int (*resume_early)(struct platform_device *);? ?? ?? ?? ?? ?? ???
int (*resume)(struct platform_device *);? ?? ?? ?? ?? ?? ?? ?? ???
struct device_driver driver;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???
};
從結(jié)構(gòu)體可以看出,platform_device是device派生出,platform_driver是device_driver派生出
同樣添加設(shè)備PlatformDevA,初始化platform_device結(jié)構(gòu)體的dev域時(shí),沒(méi)有初始化其bus_type域,而實(shí)際將該設(shè)備添加在sys\bus\platform\devices目錄下,
在源代碼中哪里可以看到這部分代碼。
同樣添加驅(qū)動(dòng)PlatformDrvA,初始化platform_driver結(jié)構(gòu)體的driver域時(shí),沒(méi)有初始化其bus_type域,而實(shí)際將該驅(qū)動(dòng)添加在sys\bus\platform\drivers目錄下,
在源代碼中哪里可以看到這部分代碼。
還有
struct miscdevice??{? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??
int minor;? ?? ?? ?? ?? ?? ?? ?? ??
const char *name;? ?? ?? ?? ?? ?? ?
const struct file_operations *fops;
struct list_head list;? ?? ?? ?? ??
struct device *parent;? ?? ?? ?? ??
struct device *this_device;? ?? ???
};?
與字符型設(shè)備
struct cdev {
struct kobject kobj;
struct module *owner;
const struct file_operations *ops;
struct list_head list;
dev_t dev;
unsigned int count;
};
從結(jié)構(gòu)體可以看出,miscdevice是device派生出,它與platform_device區(qū)別:
1、platform_device中有設(shè)備使用的資源的信息resource。
2、miscdevice中有該設(shè)備的使用方法file_operations。
從設(shè)備驅(qū)動(dòng)源代碼中:
第一步
static struct platform_device at91sam9260_adc_device = {
.name? ?? ? = "at91_adc",
.id? ???= -1,
.dev? ?? ???= {
.platform_data??= &adc_data,
},??
.resource? ?= adc_resources,
.num_resources??= ARRAY_SIZE(adc_resources),
};
static struct resource spi0_resources[] = {
[0] = {
.start??= AT91SAM9260_BASE_SPI0,
.end? ? = AT91SAM9260_BASE_SPI0 + SZ_16K - 1,
.flags??= IORESOURCE_MEM,
},
[1] = {
.start??= AT91SAM9260_ID_SPI0,
.end? ? = AT91SAM9260_ID_SPI0,
.flags??= IORESOURCE_IRQ,
},
};
//向系統(tǒng)添加此設(shè)備,注冊(cè)設(shè)備的資源
platform_device_register(&at91sam9260_adc_device);
第二步:
static struct file_operations at91_adc_fops = {
.owner =? ? ? ? THIS_MODULE,
.ioctl =? ? ? ? at91_adc_ioctl,
.read =? ? ? ? at91_adc_readdata,? ?? ??
.open =? ? ? ? ? ? ? ? at91_adc_open,? ?? ???
.release =? ? ? ? at91_adc_release,? ?? ???
};
static struct miscdevice at91_adc_dev = {? ?? ???
.minor =? ? ? ? MISC_DYNAMIC_MINOR,
.name =? ? ? ? ? ? ? ? "adc",
.fops =? ? ? ? ? ? ? ? &at91_adc_fops,
};
//向系統(tǒng)添加此設(shè)備,注冊(cè)設(shè)備的使用方法
misc_register(&at91_adc_dev);
第三步:
static struct platform_driver at91_i2c_driver = {
.probe? ? ? ? ? ? ? ? = at91_adc_probe,
.remove? ? ? ? ? ? ? ? = __devexit_p(at91_adc_remove),
.suspend? ? ? ? = at91_adc_suspend,
.resume? ? ? ? ? ? ? ? = at91_adc_resume,
.driver? ? ? ? ? ? ? ? = {
.name? ? ? ? = "at91_adc",
.owner? ? ? ? = THIS_MODULE,
},
};
//注冊(cè)此設(shè)備驅(qū)動(dòng)
platform_driver_register(&at91_i2c_driver);
這三個(gè)結(jié)構(gòu)體關(guān)系:
(基類)
kobject --------------------
/? ???\? ?? ?? ?? ?? ?? ?? ? \
/? ?? ? \? ?? ?? ?? ?? ?? ?? ? \
device? ???cdev? ?? ?? ?? ?? ?? ? driver
/? ???\ (設(shè)備驅(qū)動(dòng)操作方法)? ?? ?? ???\
/? ?? ? \? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?\
miscdevice? ?? ?? ?platform_device? ?? ?? ?? ?? ?platform_driver
(設(shè)備驅(qū)動(dòng)操作方法)? ? (設(shè)備的資源)? ?? ?? ?? ?? ?? ? (設(shè)備驅(qū)動(dòng))?
我的疑問(wèn):
1、當(dāng)寫(xiě)字符型設(shè)備驅(qū)動(dòng)時(shí),我一般只使用cdev結(jié)構(gòu)體,使用此種方式,好像無(wú)法在sysfs中顯示出該設(shè)備。
2、miscdevice是否支持字符設(shè)備和塊設(shè)備,如果使用它怎么辨別塊設(shè)備或字符設(shè)備。
3、miscdevice、platform_device、platform_driver是否可以作為通用的設(shè)備驅(qū)動(dòng)方法,由platform_device注冊(cè)設(shè)備資源
platform_driver注冊(cè)設(shè)備驅(qū)動(dòng)、miscdevice注冊(cè)設(shè)備使用方法。
===============================================
以上是網(wǎng)上搜到的一個(gè)帖子,和我的疑問(wèn)有些相似,而且有些地方我也沒(méi)搞清楚。
這個(gè)帖子轉(zhuǎn)載不少,可是少有人回復(fù),回復(fù)的也沒(méi)什么實(shí)質(zhì)性內(nèi)容。
不過(guò)這個(gè)同學(xué)整理的部分還是比較清晰的,值得看看!
比如,以前寫(xiě)字符驅(qū)動(dòng),主要的內(nèi)容就是實(shí)現(xiàn)file_operations結(jié)構(gòu)體里的函數(shù),然后就是申請(qǐng)?jiān)O(shè)備號(hào),注冊(cè)字符設(shè)備,根本就沒(méi)有涉及到設(shè)備驅(qū)動(dòng)模型。而驅(qū)動(dòng)模型里,device_driver根本沒(méi)有涉及到設(shè)備操作的函數(shù)、file_operations等,只有一些電源管理,熱插拔相關(guān)的函數(shù)。platform_device里也主要是resource的管理,所以感覺(jué)兩者根本就沒(méi)關(guān)系,也很奇怪為什么要弄兩套東西來(lái)實(shí)現(xiàn),而且兩者也對(duì)應(yīng)不起來(lái)。
后來(lái)看了一些內(nèi)核中的驅(qū)動(dòng)源碼,發(fā)現(xiàn)很多都是用miscdevice、platform_device、platform_driver實(shí)現(xiàn)的,而且流程很相似:
1、在系統(tǒng)初始化階段注冊(cè)platform_device,主要是添加設(shè)備對(duì)應(yīng)的resource進(jìn)鏈表,以便系統(tǒng)對(duì)設(shè)備占用的資源統(tǒng)一管理;
2、實(shí)現(xiàn)platform_driver并注冊(cè),在這部分,需要實(shí)現(xiàn)的主要有platform_driver結(jié)構(gòu)體中的probe,還有remove、shutdown等一些關(guān)于熱插拔、電源管理方面的函數(shù)。
3、然后在模塊初始化函數(shù)(xx_init)里注冊(cè)platform_driver(platform_driver_register)
其中設(shè)備資源的獲取(platform_get_resource),如IO內(nèi)存、IO端口、中斷號(hào),申請(qǐng)(request),物理地址到虛擬地址的映射(ioremap),misc_device的注冊(cè)(misc_register),時(shí)鐘的獲取(clk_get)及使能(clk_enable)都是在probe函數(shù)里實(shí)現(xiàn)的,probe函數(shù)是在platform_driver注冊(cè),或者新設(shè)備添加時(shí),platform_device和platform_driver匹配(通過(guò)名字)成功后執(zhí)行的,有別于以往接觸的字符驅(qū)動(dòng)里的注冊(cè)流程。
對(duì)于misc_device對(duì)于設(shè)備操作函數(shù)的實(shí)現(xiàn)和字符設(shè)備一樣,都是填充file_operations結(jié)構(gòu)體,然后在模塊初始化函數(shù)里注冊(cè)(misc_register)。
對(duì)于platform驅(qū)動(dòng)模型,似乎就是platform_device負(fù)責(zé)設(shè)備資源,platform_driver負(fù)責(zé)電源管理以及資源的申請(qǐng),中斷的注冊(cè)等設(shè)備初始化及啟動(dòng)有關(guān)的操作,然后就是設(shè)備操作方法(file_operations)的注冊(cè)(misc_register或者cdev_add),cdev或者misc_device就負(fù)責(zé)file_operations。
但是目前還有不少疑問(wèn):
1、設(shè)備號(hào)的申請(qǐng)?jiān)谀睦?#xff0c;它是怎么放到驅(qū)動(dòng)模型里的device結(jié)構(gòu)體中的?
2、platform_driver結(jié)構(gòu)體和其中的device_driver結(jié)構(gòu)體中都有probe、remove、shutdown等,為什么要在外層放重復(fù)的東西,二者有什么關(guān)系和區(qū)別嘛?
3、misc_register實(shí)現(xiàn)里最終和platform_device_register一樣都會(huì)調(diào)用device_add,這樣在設(shè)備驅(qū)動(dòng)模型里不是有兩個(gè)device和device_driver對(duì)應(yīng),而實(shí)際的物理設(shè)備只有一個(gè)嘛?
4、看起來(lái)好像驅(qū)動(dòng)模型是對(duì)實(shí)際的設(shè)備及驅(qū)動(dòng)的抽象,提取它們的信息包裝成內(nèi)核對(duì)象kobject,然后按照它們之間的關(guān)系對(duì)其進(jìn)行分類、分層次管理(建立一棵樹(shù)),借由這些對(duì)象,由系統(tǒng)管理設(shè)備資源的注冊(cè)申請(qǐng)、釋放以及實(shí)際驅(qū)動(dòng)(file_operations)的注冊(cè)時(shí)機(jī)(由此可以實(shí)現(xiàn)熱插拔,即插即用)和電源管理(系統(tǒng)可以根據(jù)設(shè)備樹(shù)來(lái)決定設(shè)備關(guān)閉的順序,device->device_driver->shutdown)。
所以設(shè)備驅(qū)動(dòng)模型中,device只是用來(lái)建立設(shè)備樹(shù),最終會(huì)根據(jù)結(jié)構(gòu)體中的device_driver中的電源管理函數(shù)實(shí)現(xiàn)合理的電源開(kāi)關(guān)順序?
而對(duì)于熱插拔有關(guān)的功能,和device與device_driver的匹配過(guò)程有關(guān),而與設(shè)備樹(shù)層次關(guān)系無(wú)關(guān)?
( 以上是目前想到的不明白的地方,遺漏的地方想起會(huì)再添加。改天找老師好好問(wèn)問(wèn),太復(fù)雜了! )
===============================================
最近研究Linux設(shè)備驅(qū)動(dòng)程序遇到混亂,請(qǐng)大俠過(guò)來(lái)理理頭緒。
Linux設(shè)備模型中:bus_type、device、device_driver
《Linux設(shè)備驅(qū)動(dòng)程序》的linux設(shè)備模型章中說(shuō)到設(shè)備模型中,所有設(shè)備都通過(guò)總線相連。
添加設(shè)備devA,必須指定其device結(jié)構(gòu)體的bus_type域,初始化其他域,然后調(diào)用device_register(&devA),將設(shè)備devA
注冊(cè)到指定總線。
添加該設(shè)備驅(qū)動(dòng)driverA,也必須指定其device_driver結(jié)構(gòu)體的bus_type域,初始化其他域,然后調(diào)用driver_register(&driverA),
將該驅(qū)動(dòng)注冊(cè)到總線上。
如果驅(qū)動(dòng)driverA和設(shè)備devA匹配成功,即調(diào)用probe函數(shù)成功,則建立他們之間的符號(hào)鏈接,即將設(shè)備與驅(qū)動(dòng)捆綁起來(lái)。
而實(shí)際我看Linux源代碼中卻大量使用platform_device,
struct platform_device {? ?? ??
const char? ? ? ? * name;? ?? ???
u32? ? ? ? ? ? ? ? id;? ?? ?? ?? ?? ??
struct device? ? ? ? dev;? ?? ??
u32? ? ? ? ? ? ? ? num_resources;? ???
struct resource? ? ? ? * resource;
};
和
struct platform_driver {? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?
int (*probe)(struct platform_device *);? ?? ?? ?? ?? ?? ?? ?? ?? ?
int (*remove)(struct platform_device *);? ?? ?? ?? ?? ?? ?? ?? ???
void (*shutdown)(struct platform_device *);? ?? ?? ?? ?? ?? ?? ???
int (*suspend)(struct platform_device *, pm_message_t state);? ???
int (*suspend_late)(struct platform_device *, pm_message_t state);
int (*resume_early)(struct platform_device *);? ?? ?? ?? ?? ?? ???
int (*resume)(struct platform_device *);? ?? ?? ?? ?? ?? ?? ?? ???
struct device_driver driver;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???
};
從結(jié)構(gòu)體可以看出,platform_device是device派生出,platform_driver是device_driver派生出
同樣添加設(shè)備PlatformDevA,初始化platform_device結(jié)構(gòu)體的dev域時(shí),沒(méi)有初始化其bus_type域,而實(shí)際將該設(shè)備添加在sys\bus\platform\devices目錄下,
在源代碼中哪里可以看到這部分代碼。
同樣添加驅(qū)動(dòng)PlatformDrvA,初始化platform_driver結(jié)構(gòu)體的driver域時(shí),沒(méi)有初始化其bus_type域,而實(shí)際將該驅(qū)動(dòng)添加在sys\bus\platform\drivers目錄下,
在源代碼中哪里可以看到這部分代碼。
還有
struct miscdevice??{? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??
int minor;? ?? ?? ?? ?? ?? ?? ?? ??
const char *name;? ?? ?? ?? ?? ?? ?
const struct file_operations *fops;
struct list_head list;? ?? ?? ?? ??
struct device *parent;? ?? ?? ?? ??
struct device *this_device;? ?? ???
};?
與字符型設(shè)備
struct cdev {
struct kobject kobj;
struct module *owner;
const struct file_operations *ops;
struct list_head list;
dev_t dev;
unsigned int count;
};
從結(jié)構(gòu)體可以看出,miscdevice是device派生出,它與platform_device區(qū)別:
1、platform_device中有設(shè)備使用的資源的信息resource。
2、miscdevice中有該設(shè)備的使用方法file_operations。
從設(shè)備驅(qū)動(dòng)源代碼中:
第一步
static struct platform_device at91sam9260_adc_device = {
.name? ?? ? = "at91_adc",
.id? ???= -1,
.dev? ?? ???= {
.platform_data??= &adc_data,
},??
.resource? ?= adc_resources,
.num_resources??= ARRAY_SIZE(adc_resources),
};
static struct resource spi0_resources[] = {
[0] = {
.start??= AT91SAM9260_BASE_SPI0,
.end? ? = AT91SAM9260_BASE_SPI0 + SZ_16K - 1,
.flags??= IORESOURCE_MEM,
},
[1] = {
.start??= AT91SAM9260_ID_SPI0,
.end? ? = AT91SAM9260_ID_SPI0,
.flags??= IORESOURCE_IRQ,
},
};
//向系統(tǒng)添加此設(shè)備,注冊(cè)設(shè)備的資源
platform_device_register(&at91sam9260_adc_device);
第二步:
static struct file_operations at91_adc_fops = {
.owner =? ? ? ? THIS_MODULE,
.ioctl =? ? ? ? at91_adc_ioctl,
.read =? ? ? ? at91_adc_readdata,? ?? ??
.open =? ? ? ? ? ? ? ? at91_adc_open,? ?? ???
.release =? ? ? ? at91_adc_release,? ?? ???
};
static struct miscdevice at91_adc_dev = {? ?? ???
.minor =? ? ? ? MISC_DYNAMIC_MINOR,
.name =? ? ? ? ? ? ? ? "adc",
.fops =? ? ? ? ? ? ? ? &at91_adc_fops,
};
//向系統(tǒng)添加此設(shè)備,注冊(cè)設(shè)備的使用方法
misc_register(&at91_adc_dev);
第三步:
static struct platform_driver at91_i2c_driver = {
.probe? ? ? ? ? ? ? ? = at91_adc_probe,
.remove? ? ? ? ? ? ? ? = __devexit_p(at91_adc_remove),
.suspend? ? ? ? = at91_adc_suspend,
.resume? ? ? ? ? ? ? ? = at91_adc_resume,
.driver? ? ? ? ? ? ? ? = {
.name? ? ? ? = "at91_adc",
.owner? ? ? ? = THIS_MODULE,
},
};
//注冊(cè)此設(shè)備驅(qū)動(dòng)
platform_driver_register(&at91_i2c_driver);
這三個(gè)結(jié)構(gòu)體關(guān)系:
(基類)
kobject --------------------
/? ???\? ?? ?? ?? ?? ?? ?? ? \
/? ?? ? \? ?? ?? ?? ?? ?? ?? ? \
device? ???cdev? ?? ?? ?? ?? ?? ? driver
/? ???\ (設(shè)備驅(qū)動(dòng)操作方法)? ?? ?? ???\
/? ?? ? \? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?\
miscdevice? ?? ?? ?platform_device? ?? ?? ?? ?? ?platform_driver
(設(shè)備驅(qū)動(dòng)操作方法)? ? (設(shè)備的資源)? ?? ?? ?? ?? ?? ? (設(shè)備驅(qū)動(dòng))?
我的疑問(wèn):
1、當(dāng)寫(xiě)字符型設(shè)備驅(qū)動(dòng)時(shí),我一般只使用cdev結(jié)構(gòu)體,使用此種方式,好像無(wú)法在sysfs中顯示出該設(shè)備。
2、miscdevice是否支持字符設(shè)備和塊設(shè)備,如果使用它怎么辨別塊設(shè)備或字符設(shè)備。
3、miscdevice、platform_device、platform_driver是否可以作為通用的設(shè)備驅(qū)動(dòng)方法,由platform_device注冊(cè)設(shè)備資源
platform_driver注冊(cè)設(shè)備驅(qū)動(dòng)、miscdevice注冊(cè)設(shè)備使用方法。
===============================================
以上是網(wǎng)上搜到的一個(gè)帖子,和我的疑問(wèn)有些相似,而且有些地方我也沒(méi)搞清楚。
這個(gè)帖子轉(zhuǎn)載不少,可是少有人回復(fù),回復(fù)的也沒(méi)什么實(shí)質(zhì)性內(nèi)容。
不過(guò)這個(gè)同學(xué)整理的部分還是比較清晰的,值得看看!
總結(jié)
以上是生活随笔為你收集整理的内核驱动中常见的miscdevice、platform_device、platform_driver的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: DEVICE_ATTR实例分析
- 下一篇: DEVICE_ATTR