字元裝置的核心抽象

broadviewbj發表於2012-02-29

字元裝置的核心抽象

顧名思義,字元裝置驅動程式管理的核心物件是字元裝置。從字元裝置驅動程式的設計框架角度出發,核心為字元裝置抽象出了一個具體的資料結構struct cdev,其定義如下:

struct cdev {

       struct kobject kobj;

       struct module *owner;

       const struct file_operations *ops;

       struct list_head list;

       dev_t dev;

       unsigned int count;

};

在本章後續的內容中將陸續看到它們的實際用法,這裡只把這些成員的作用簡單描述如下:

struct kobject kobj

內嵌的核心物件,其用途將在“Linux裝置驅動模型一章中討論。

struct module *owner

字元裝置驅動程式所在的核心模組物件指標。

const struct file_operations *ops

字元裝置驅動程式中一個極其關鍵的資料結構,在應用程式透過檔案系統介面呼叫到裝置驅動程式中實現的檔案操作類函式的過程中,ops指標起著橋樑紐帶的作用。

struct list_head list

用來將系統中的字元裝置形成連結串列。

dev_t dev

字元裝置的裝置號,由主裝置號和次裝置號構成。

unsigned int count

隸屬於同一主裝置號的次裝置號的個數,用於表示由當前裝置驅動程式控制的實際同類裝置的數量。

裝置驅動程式中可以用兩種方式來產生struct cdev物件。一是靜態定義的方式,比如在前面的那個示例程式中,透過下列程式碼靜態定義了一個struct cdev物件:

static struct cdev chr_dev;

另一種是在程式的執行期透過動態分配的方式產生,比如:

static struct cdev *p = kmalloc(sizeof(struct cdev), GFP_KERNEL);

其實Linux核心原始碼中提供了一個函式cdev_alloc,專門用於動態分配struct cdev物件。cdev_alloc不僅會為struct cdev物件分配記憶體空間,還會對該物件進行必要的初始化:

struct cdev *cdev_alloc(void)

{

       struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL);

       if (p) {

              INIT_LIST_HEAD(&p->list);

              kobject_init(&p->kobj, &ktype_cdev_dynamic);

       }

       return p;

}

需要注意的是,核心引入struct cdev資料結構作為字元裝置的抽象,僅僅是為了滿足系統對字元裝置驅動程式框架結構設計的需要,現實中一個具體的字元硬體裝置的資料結構的抽象往往要複雜得多,在這種情況下struct cdev常常作為一種內嵌的成員變數出現在實際裝置的資料機構中,比如:

struct my_keypad_dev{

       //硬體相關的成員變數

       int a;

       int b;

       int c;

      

       //內嵌的struct cdev資料結構

       struct cdev cdev;

}

在這樣的情況下,如果要動態分配一個struct real_char_dev物件,cdev_alloc函式顯然就無能為力了,此時只能使用下面的方法:

static struct real_char_dev *p = kzalloc(sizeof(struct real_char_dev), GFP_KERNEL);

前面討論瞭如何分配一個struct cdev物件,接下來的一個話題是如何初始化一個cdev物件,核心為此提供的函式是cdev_init

void cdev_init(struct cdev *cdev, const struct file_operations *fops)

{

       memset(cdev, 0, sizeof *cdev);

       INIT_LIST_HEAD(&cdev->list);

       kobject_init(&cdev->kobj, &ktype_cdev_default);

       cdev->ops = fops;

}

函式的程式碼非常直白,不再贅述。一個struct cdev物件在被最終加入系統前,都應該被初始化,無論是直接透過cdev_init或者是其他途徑。理由很簡單,這是Linux系統中字元裝置驅動程式框架設計的需要。

照理在談完cdev物件的分配和初始化之後,下面應該討論如何將一個cdev物件加入到系統了,但是由於這個過程需要用到裝置號相關的技術點,所以暫且先來探討裝置號的問題。

 字元裝置的核心抽象

——本段文位元組選自《深入Linux裝置驅動程式核心機制》

圖書詳細資訊:http://space.itpub.net/?uid-13164110-action-viewspace-itemid-716897

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/13164110/viewspace-717398/,如需轉載,請註明出處,否則將追究法律責任。

相關文章