天天看點

字元裝置結構體 cdev 初始化

轉自:http://hi.baidu.com/grdd/blog/item/2d799d0adc2b7b1895ca6bde.html

核心中每個字元裝置都對應一個 cdev 結構的變量,下面是它的定義:

linux-2.6.22/include/linux/cdev.h

struct cdev {

   struct kobject kobj;          // 每個 cdev 都是一個 kobject

   struct module *owner;       // 指向實作驅動的子產品

   const struct file_operations *ops;   // 操縱這個字元裝置檔案的方法

   struct list_head list;       // 與 cdev 對應的字元裝置檔案的 inode->i_devices 的連結清單頭

   dev_t dev;                   // 起始裝置編号

   unsigned int count;       // 裝置範圍号大小

};

一個 cdev 一般它有兩種定義初始化方式:靜态的和動态的。

靜态記憶體定義初始化:

struct cdev my_cdev;

cdev_init(&my_cdev, &fops);

my_cdev.owner = THIS_MODULE;

動态記憶體定義初始化:

struct cdev *my_cdev = cdev_alloc();

my_cdev->ops = &fops;

my_cdev->owner = THIS_MODULE;

兩種使用方式的功能是一樣的,隻是使用的記憶體區不一樣,一般視實際的資料結構需求而定。

下面貼出了兩個函數的代碼,以具體看一下它們之間的差異。

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;

}

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;

}

由此可見,兩個函數完成都功能基本一緻,隻是 cdev_init() 還多賦了一個 cdev->ops 的值。

初始化 cdev 後,需要把它添加到系統中去。為此可以調用 cdev_add() 函數。傳入 cdev 結構的指針,起始裝置編号,以及裝置編号範圍。

int cdev_add(struct cdev *p, dev_t dev, unsigned count)

{

   p->dev = dev;

   p->count = count;

   return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);

}

關于 kobj_map() 函數就不展開了,我隻是大緻講一下它的原理。核心中所有都字元裝置都會記錄在一個 kobj_map 結構的 cdev_map 變量中。這個結構的變量中包含一個散清單用來快速存取所有的對象。kobj_map() 函數就是用來把字元裝置編号和 cdev 結構變量一起儲存到 cdev_map 這個散清單裡。當後續要打開一個字元裝置檔案時,通過調用 kobj_lookup() 函數,根據裝置編号就可以找到 cdev 結構變量,進而取出其中的 ops 字段。

當一個字元裝置驅動不再需要的時候(比如子產品解除安裝),就可以用 cdev_del() 函數來釋放 cdev 占用的記憶體。

void cdev_del(struct cdev *p)

{

   cdev_unmap(p->dev, p->count);

   kobject_put(&p->kobj);

}

其中 cdev_unmap() 調用 kobj_unmap() 來釋放 cdev_map 散清單中的對象。kobject_put() 釋放 cdev 結構本身。

繼續閱讀