日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

内核驱动中常见的miscdevice、platform_device、platform_driver

發布時間:2025/4/16 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 内核驱动中常见的miscdevice、platform_device、platform_driver 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
最近在看驅動模型,是越看越糊涂,以前接觸比較多的都是一些字符驅動,對字符驅動的框架有一定的了解。后來因為想在驅動中實現設備文件的創建,又了解了一下,sysfs文件系統和udev設備文件系統,必然就涉及到了驅動模型。可是發現驅動模型和以前接觸的字符驅動沒什么聯系。
比如,以前寫字符驅動,主要的內容就是實現file_operations結構體里的函數,然后就是申請設備號,注冊字符設備,根本就沒有涉及到設備驅動模型。而驅動模型里,device_driver根本沒有涉及到設備操作的函數、file_operations等,只有一些電源管理,熱插拔相關的函數。platform_device里也主要是resource的管理,所以感覺兩者根本就沒關系,也很奇怪為什么要弄兩套東西來實現,而且兩者也對應不起來。
后來看了一些內核中的驅動源碼,發現很多都是用miscdevice、platform_device、platform_driver實現的,而且流程很相似:

1、在系統初始化階段注冊platform_device,主要是添加設備對應的resource進鏈表,以便系統對設備占用的資源統一管理;
2、實現platform_driver并注冊,在這部分,需要實現的主要有platform_driver結構體中的probe,還有remove、shutdown等一些關于熱插拔、電源管理方面的函數。
3、然后在模塊初始化函數(xx_init)里注冊platform_driver(platform_driver_register)

其中設備資源的獲取(platform_get_resource),如IO內存、IO端口、中斷號,申請(request),物理地址到虛擬地址的映射(ioremap),misc_device的注冊(misc_register),時鐘的獲取(clk_get)及使能(clk_enable)都是在probe函數里實現的,probe函數是在platform_driver注冊,或者新設備添加時,platform_device和platform_driver匹配(通過名字)成功后執行的,有別于以往接觸的字符驅動里的注冊流程。
對于misc_device對于設備操作函數的實現和字符設備一樣,都是填充file_operations結構體,然后在模塊初始化函數里注冊(misc_register)。
對于platform驅動模型,似乎就是platform_device負責設備資源,platform_driver負責電源管理以及資源的申請,中斷的注冊等設備初始化及啟動有關的操作,然后就是設備操作方法(file_operations)的注冊(misc_register或者cdev_add),cdev或者misc_device就負責file_operations。

但是目前還有不少疑問:
1、設備號的申請在哪里,它是怎么放到驅動模型里的device結構體中的?
2、platform_driver結構體和其中的device_driver結構體中都有probe、remove、shutdown等,為什么要在外層放重復的東西,二者有什么關系和區別嘛?
3、misc_register實現里最終和platform_device_register一樣都會調用device_add,這樣在設備驅動模型里不是有兩個device和device_driver對應,而實際的物理設備只有一個嘛?
4、看起來好像驅動模型是對實際的設備及驅動的抽象,提取它們的信息包裝成內核對象kobject,然后按照它們之間的關系對其進行分類、分層次管理(建立一棵樹),借由這些對象,由系統管理設備資源的注冊申請、釋放以及實際驅動(file_operations)的注冊時機(由此可以實現熱插拔,即插即用)和電源管理(系統可以根據設備樹來決定設備關閉的順序,device->device_driver->shutdown)。
所以設備驅動模型中,device只是用來建立設備樹,最終會根據結構體中的device_driver中的電源管理函數實現合理的電源開關順序?
而對于熱插拔有關的功能,和device與device_driver的匹配過程有關,而與設備樹層次關系無關?
以上是目前想到的不明白的地方,遺漏的地方想起會再添加。改天找老師好好問問,太復雜了!


===============================================
最近研究Linux設備驅動程序遇到混亂,請大俠過來理理頭緒。
Linux設備模型中:bus_type、device、device_driver
《Linux設備驅動程序》的linux設備模型章中說到設備模型中,所有設備都通過總線相連。
添加設備devA,必須指定其device結構體的bus_type域,初始化其他域,然后調用device_register(&devA),將設備devA
注冊到指定總線。
添加該設備驅動driverA,也必須指定其device_driver結構體的bus_type域,初始化其他域,然后調用driver_register(&driverA),
將該驅動注冊到總線上。
如果驅動driverA和設備devA匹配成功,即調用probe函數成功,則建立他們之間的符號鏈接,即將設備與驅動捆綁起來。
而實際我看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;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???
};
從結構體可以看出,platform_device是device派生出,platform_driver是device_driver派生出
同樣添加設備PlatformDevA,初始化platform_device結構體的dev域時,沒有初始化其bus_type域,而實際將該設備添加在sys\bus\platform\devices目錄下,
在源代碼中哪里可以看到這部分代碼。
同樣添加驅動PlatformDrvA,初始化platform_driver結構體的driver域時,沒有初始化其bus_type域,而實際將該驅動添加在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;? ?? ???
};?
與字符型設備
struct cdev {
struct kobject kobj;
struct module *owner;
const struct file_operations *ops;
struct list_head list;
dev_t dev;
unsigned int count;
};
從結構體可以看出,miscdevice是device派生出,它與platform_device區別:
1、platform_device中有設備使用的資源的信息resource。
2、miscdevice中有該設備的使用方法file_operations。
從設備驅動源代碼中:
第一步
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,
},
};
//向系統添加此設備,注冊設備的資源
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,
};
//向系統添加此設備,注冊設備的使用方法
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,
},
};
//注冊此設備驅動
platform_driver_register(&at91_i2c_driver);

這三個結構體關系:
(基類)
kobject --------------------
/? ???\? ?? ?? ?? ?? ?? ?? ? \
/? ?? ? \? ?? ?? ?? ?? ?? ?? ? \
device? ???cdev? ?? ?? ?? ?? ?? ? driver
/? ???\ (設備驅動操作方法)? ?? ?? ???\
/? ?? ? \? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?\
miscdevice? ?? ?? ?platform_device? ?? ?? ?? ?? ?platform_driver
(設備驅動操作方法)? ? (設備的資源)? ?? ?? ?? ?? ?? ? (設備驅動)?
我的疑問:
1、當寫字符型設備驅動時,我一般只使用cdev結構體,使用此種方式,好像無法在sysfs中顯示出該設備。
2、miscdevice是否支持字符設備和塊設備,如果使用它怎么辨別塊設備或字符設備。
3、miscdevice、platform_device、platform_driver是否可以作為通用的設備驅動方法,由platform_device注冊設備資源
platform_driver注冊設備驅動、miscdevice注冊設備使用方法。

===============================================
以上是網上搜到的一個帖子,和我的疑問有些相似,而且有些地方我也沒搞清楚。
這個帖子轉載不少,可是少有人回復,回復的也沒什么實質性內容。
不過這個同學整理的部分還是比較清晰的,值得看看!

總結

以上是生活随笔為你收集整理的内核驱动中常见的miscdevice、platform_device、platform_driver的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。