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 設備個數