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 设备个数

 

 

 

 

 

 

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