linux 下面對 driver 的定義:
struct device_driver {
const char * name;
struct bus_type * bus;
struct completion unloaded;
struct kobject kobj;
struct klist klist_devices;
struct klist_node knode_bus;
struct module * owner;
const char * mod_name; /* used for built-in modules */
struct module_kobject * mkobj;
int (*probe) (struct device * dev);
int (*remove) (struct device * dev);
void (*shutdown) (struct device * dev);
int (*suspend) (struct device * dev, pm_message_t state);
int (*resume) (struct device * dev);
unsigned int multithread_probe:1;
};
我們一個個來看,
Name :就是這個 driver 的名字;
Bus :就是這個 driver 是掛在上面 bus 上面的;
Unloaded :這個以後再討論;
Kobj :這個可以理解為 driver 結構的父親,如果從面向對象的角度來看的話;
Klist_devices: 這個就是由此 driver 驅動的設備列表;
Knode_bus: 這個就是用來掛在它說屬的 bus 鏈表上的節點,順著這個鏈表就可以找到所有的掛在這個 bus 上的所有的 driver ;
Owner :這個 driver 所屬的模塊;
Mod_name: 模塊名字;
mkobj: 模塊的頂層描述;
probe :這個是很關鍵的函數,用來初始化此 driver 驅動的硬件,還有其它能夠正常為應用層提供服務說需要提前做的事都需要在這裡做;
remove :這個就是移除的時候做的事情;
suspend :這個應該是睡眠的時候做的事情,也就是說上層通過這個函數實現對硬件的電源策略控制;
resume :這個就是從睡眠中醒來需要對硬件所做的事都需要在這裡做;
multithread_probe :是否啟用多線程 probe ;
分析完了 driver 的結構,我們看看為什麼需要這樣的設計,也就是說,如果我們自己需要實現一套架構用來實現同樣的功能,我們需要做什麼呢?
Driver 應該提供的功能
driver 應該提供哪些功能呢?
1, 為應用層使用 driver 提供接口;
這個應該是很好理解的,不可能讓每個上層軟件的作者自己寫驅動來訪問硬件;所以必須要抽象出一套接口,但是需要哪些接口呢?
Linux 的 driver 實現很有意思,把任何東西都抽象成文件,包括硬件,這樣對硬件的操作也就只需提供 vfs 所需的一套接口,當然其實這些接口的類型在很大程度上劃分了 driver 的類型,而這些接口也可以提供其它的形式,比如網卡就不提供這些接口;
Open :打開,也就是打開這個設備,這只是抽象的概念,很多硬件設備不存在這樣的物理動作,比如門,我們才說打開,當然如果理解所謂“打開心扉”也就很好理解這裡的 driver 所抽象出的打開了;先前所說硬件的初始化可以在 probe 函數裡面做,當然我想有些動作放在 open 裡面做也可以的,但是必須要考慮的是, open 是可能出現許多個進程來訪問的,或者你自己要上鎖或者你就要考慮可重入性,也就是說如果一些動作只能做一次,那麼顯然放在 open 裡面來做就不合適了。
Close :這個和 open 相反的動作,但是這個 close 是上層才有的一個概念,在驅動裡面用來一個叫 release 的接口實現,至於 close 到 release 之間的轉換就需要去看看文件系統這層的實現了。
Read :這就是讀取數據了,沒什麼好說,比如串口,比如 touch panel ;
Write :這就是寫了,也就是往設備裡面寫數據;
其它的一些對上的接口 …. 就不討論了;
而 driver 還必須要提供其它的接口:那就是做為 linux driver 本身說必須要提供的接口,這些接口通常是內核自身所調用的;
那就是
Probe :這個函數很關鍵,12下一頁