| 試著總結一下,學習一下,至少現(xiàn)在的我對于設備模型這個概念,幾乎完全不懂。 
 Linux設備模型中三個很重要的概念就是總線、設備和驅動,即bus、device、driver,而實際上內核中也定義了這么一些數(shù)據(jù)結構,分別為struct bus_type,struct device,struct device_driver,
 
 原型定義均在include/linux/device.h中。而struct bus_type結構中兩個非常重要的成員就是kset和kobject這兩個結構體。
 
 于是乎,Linux設備模型概念中重要的5個概念都引出來了,即設備模型
 
 在具體實現(xiàn)方面分兩個層次:
 
 一是底層數(shù)據(jù)結構來實現(xiàn)基本對象及其層次關系:kobjects和ksets。
 
 二是基于這兩個底層數(shù)據(jù)結構上實現(xiàn)的設備模型:總線,設備,驅動。
 
 一、底層數(shù)據(jù)結構:kobject,kset
 
 kobject
 
 結合面向對象的思維。這個kobject屬于最基礎的結構,也就是最高抽象層(有點像java中的Cobject類)。任何一個設備模型如總線,設備,驅動都屬于一個kobject 。在實現(xiàn)上這種派生關系就是在結構體中包含一個kobject的變量。
 
 這個在層次上處理最頂層的kobject結構提供了所有模型需要的最基本的功能:
 
 1 引用計數(shù) 用于內核維護其存在與消亡
 
 2 sys水利模型fs表示 每個sys/下的對象對應著一個kobject。
 
 3 熱拔插事件處理 處理設備的熱拔插事件。
 
 Kobjects 在內核中對應有一套申請,初始化,添加,注冊,計數(shù)操縱,開釋等函數(shù) //2.6.10 struct kobject { char * k_name; //名稱 char name[KOBJ_NAME_LEN]; struct kref kref; //計數(shù) struct list_head entry;//用于連接到同類kobjects的鏈表 struct kobjectn * parent;//用于實現(xiàn)層次,指向其父對象 struct kset * kset; //用于實現(xiàn)層次,所屬的集合 struct kobj_typen * ktype;//指向對象的類型 struct dentry * dentry; //指示在sysfs中的目錄項 }; Kset和kobj_type
 
 Kset在概念上是一個集合或者叫容器。實現(xiàn)了對象的層鍋爐模型次鍋爐模型。所有屬于一個ksets的對象(kobject)的parent都指向該ksets的kobj.同時這個對象都連接到kset 的list表上。同時位于ksets層次之上的是subsys,在最新的內核中已經(jīng)取消subsys,由于它本質上也就是一個ksets。Kset有一套類似kobject的操縱,實現(xiàn)上只是進一步調用其自身kobj的相應操縱,究竟ksets本質上也是一個kobject。 //2.6.10 struct kset { struct subsystem * subsys; //在新內核中已經(jīng)沒有subsys概念了,同一用kests struct kobj_type * ktype; //類型 struct list_head list; //同一kset的鏈表 struct kobject kobj; //自身的kobjects struct kset_hotplug_ops * hotplu鍋爐模型g_ops; }; 最后 屬于同一個集合的對象可以擁有共同的屬性:ktype 。
 
 struct kobj_type { void (*release)(struct kobject *); struct sysfs_ops * sysfs_ops; struct attribute ** default_attrs; }; 所謂的屬性更具體一點說就是一些鍵值對。并且在sysfs_ops中的show函數(shù)被文件系統(tǒng)調用來顯示sys/下面對應進口各屬性的值。
 
 如此 ,kobjects與ksets實現(xiàn)層次樹的底層骨架。
 
 進一步地,通過封裝這些底層結構來實現(xiàn)上層的設備驅動模型。
 
 二、總線 設備 驅動
 
 關于bus,關于device,關于driver,他們是如何建立聯(lián)系的呢?
 
 基本關系扼要的概括如下:
 
 驅動核心可以注冊多種類型的總線。
 
 每種總線下面可以掛載很多設備。(通過kset devices)
 
 每種總線下可以用很多設備驅動。(通過包含一個kset drivers)}
 
 每個驅動可以處理一組設備。
 
 這種基本關系的建立源于實際系統(tǒng)中各種總線,設備,驅動結構的抽象。
 
 具體到usb設備就是usb core的代碼會進行整個usb系統(tǒng)的初始化,比如申請struct bus_type usb_bus_type,然后掃描usb總線,看線上連接了哪些usb設備,或者說root hub上連了哪些usb設備
 
 ,比如說連了一個usb鍵盤,那么就為它預備一個struct device,根據(jù)它的實際情況,為這個struct device賦值,并插進devices鏈表中來。又比沙盤模型如root hub上連了一個普通的hub,那么除了要為這個hub本身預備一個struct device以外,還得繼續(xù)掃描這個hub上是否又連了別的設備,有的話繼續(xù)重復之前的事情,這樣一直進行下往,直到完成整個掃描,終極就把usb_bus_type中的devices鏈表給建立了起來。
 
 那么drivers鏈表呢?這個就不用bus方面主動了,而該由每一個driver本身往bus上面登記,或者說掛牌。具體到usb系統(tǒng),每一個usb設備的驅動程序都會有一個struct usb_driver結構體,其代
 
 碼如下,來自include/linux/usb.h //2.6.10 struct usb_driver { struct module *owner; const char *name; int (*probe) (struct usb_inte***ce *intf, const struct usb_device_id *id); void (*disconnect) (struct usb_inte***ce *intf); int (*ioctl) (struct usb_inte***ce *intf, unsigned int code, void *buf); int (*suspend) (struct usb_inte***ce *intf, u32 state); int (*resume) (struct usb_inte***ce *intf); const str沙盤模型//" title="沙盤模型" target="_blank ">沙盤模型uct usb_device_id *id_table; struct device_driver driver; }; bus和device之間是如何建立聯(lián)系的?
 
 看似很長一段,實際上也就是注釋為主.而此刻我們只需留意到其中的struct device_driver driver這個成員,usb core為每一個設備驅動預備了一個函數(shù),讓它把自己的這個
 
 struct device_driver driver插進到usb_bus_type中的drivers鏈表中往.而這個函數(shù)正是我們此前看到的usb_register.而與之對應的 usb_deregister所從事的正是與之相反的工作,把這個結構
 
 體從drivers鏈表中刪除.可以說,usb core的確是專心良苦,為每一個usb設備驅動做足了作業(yè),正由于如此,作為一個實際的usb設備驅動,它在初始化階段所要做的事情就很少,很簡單了, 直接調用
 
 usb_register即可.事實上,沒有人是理所當然應該為你做什么的,但usb core這么做了.所以每一個寫usb設備驅動的人應該銘記,usb device driver盡不是一個人在工作,在他身后,是usb core所提
 
 供的默默無聞又不可或缺的支持。
 
 device和driver之間是如何建立聯(lián)系的呢?
 
 由于有了熱插拔,device可以在計算機啟動以后在插進或者拔出計算機了.因此,很難再說是先有device還是先有driver了.由于都有可能.device可以在任何時刻出現(xiàn),而driver也可以在任何時刻被加載,所以,出現(xiàn)的情況就是,每當一個struct device誕生,它就會往bus的drivers鏈表中尋找自己的另一半,反之,每當一個一個struct device_driver誕生,它就往bus的devices鏈表中尋找它的那些設備.假如找到了合適的,那么ok,調用 device_bind_driver綁定好.假如找不到,沒有關系,等待吧。
 
 還記得初始化的那幾行代碼嗎?回到usb_register中來,看一下傳給他的參數(shù)是什么?
 
 我們留意到,那句調用是這樣子的, /* register the driver, return usb_register return code if error */ retval = usb_register(&usb_storage_driver); 是的,傳遞了一個叫做usb_storage_driver的家伙,這是什么?同一文件中,drivers/usb/storage/usb.c:
 
 struct usb_driver usb_storage_driver = { .owner = THIS_MODULE, .name = "usb-storage", .probe = storage_probe, .disconnect = storage_disconnect, .id_table = storage_usb_ids, }; 可以看到這里定義了一個struct usb_driver的結構體變量,usb_storage_driver,關于usb_driver我們上節(jié)已經(jīng)說過了,當時主要說的是其中的成員driver,而眼下要講的則是另外幾個成員.首先,.owner
 
 和.name這兩個沒啥好多說的,owner這玩藝是用來給模塊計數(shù)的,每個模塊都這么用,賦值總是THIS_MODULE,而name就是這個模塊的名字,usb core會處理它,所以假如這個模塊正常被加載了的話,使用lsmod命令能看到一個叫做usb-storage的模塊名。
 |