Linux驅動複習_字符設備的註冊

1. 字符設備相關結構體
 

include/linux/cdev.h

struct cdev {
    struct kobject kobj;
    struct module *owner;
    const struct file_operations *ops;
    struct list_head list;
    dev_t dev;
    unsigned int count;
};

f

s/char_dev.c

static struct char_device_struct {
    struct char_device_struct *next;
    unsigned int major;
    unsigned int baseminor;
    int minorct;
    char name[64];
    struct cdev *cdev;        /* will die */
} *chrdevs[CHRDEV_MAJOR_HASH_SIZE];


include/linux/fs.h

#define CHRDEV_MAJOR_HASH_SIZE    255

2.字符設備的註冊

(1)相關的接口函數
 

int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops)

      major:主設備號(int類型的一個數字,可以爲0,表示內核自動分配【多希望房子也可以由國家自動分配😏】)

     name:設備的名字

     fops:文件操作函數實現的‘類’

register_chrdev 是一個早期的字符註冊函數,隨着linux 的使用越來越廣,需要管理的字符設備越來越多,有了新的註冊函數,以提供更多的設備號

int register_chrdev_region(dev_t from, unsigned count, const char *name)

      from:設備號起始號,等同於上述的主設備號

      count:本次需要註冊的設備的個數

      name:設備名字

int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,	const char *name)
       dev: 輸出一個註冊了的設備號
       baseminor:起始的次設備號
       count:次設備個數
       name:設備名字

 

(2)調用關係:

 

static struct char_device_struct *
__register_chrdev_region(unsigned int major, unsigned int baseminor, int minorct, const char *name)

根據主次設備號註冊一個字符設備。(1)中的三個註冊函數都可以註冊一個字符設備,區別是:

 register_chrdev  封裝比較全,傳入設備號、名字和fops就可以創建了一個字符設備

alloc_chrdev_region    主要是用於設備號確定或者一個主設備號對應多個次設備號的情況,即多個設備可以通過該函數共享  fops函數。適用於同類設備的情況,如多個led的情況,那麼他們的主設備號相同,次設備號不同,一個設備的設備號是由主次設備號共同組成;註冊後還需要添調用cdev_init() and cdev_add(),才能完成真正的註冊。

alloc_chrdev_region  用法和 register_chrdev_region類似,唯一不同的是這裏的 dev 參數是 “output parameter for first assigned number” 這是什麼意思呢?就是說該參數是在alloc_chrdev_region  內部賦一個整數值,作爲輸出參數;即動態分配一個設備號。

(3) cdev 的完善

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結構體變量,所作的操作是:

清空cdev變量

初始化cdev鏈表(頭尾指針相互指向對方0)

初始化kobject(這是內核設備模型,稍後的博客中會講述)

fops的掛接

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);
}

字符設備添加到系統中,xxx_chrdev_region()申請了設備號並在字符設備數組中做了標記,cdev_init()初始化了cdev變量;但是他們都是獨立的兩個個體,彼此間沒有絲毫的關係。這裏cdev_add將兩者掛接起來,使得兩者彼此知道了對方的存在,並相互依靠直到該設備的消亡。

p  cdev變量指針

dev 設備號

count 設備個數

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章