1:register_chrdev_region

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int  register_chrdev_region(dev_t from, unsigned count,  const  char  *name)
{
     struct  char_device_struct *cd;
     dev_t to = from + count;
     dev_t n, next;
 
     for  (n = from; n < to; n = next) {
         next = MKDEV(MAJOR(n)+1, 0);
         if  (next > to)
             next = to;
         cd = __register_chrdev_region(MAJOR(n), MINOR(n),
                    next - n, name);
         if  (IS_ERR(cd))
             goto  fail;
     }
     return  0;
fail:
     to = n;
     for  (n = from; n < to; n = next) {
         next = MKDEV(MAJOR(n)+1, 0);
         kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));
     }
     return  PTR_ERR(cd);
}

  register_chrdev_region函数和register_chrdev函数类似,也是用于字符设备驱动的注册,不同点在于register_chrdev函数在注册字符设备驱动的时候是一步完成的,而register_chrdev_region函数在注册字符设备驱动的时候是分两步完成的:

第一步:注册/分配主次设备号

第二步:注册字符设备驱动

此外有register_chrdev_region函数的源码可以发现,register_chrdev_region可以同时注册多个设备号

2:cdev结构体的定义

1
2
3
4
5
6
7
8
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结构体的定义在linux/cdev.h中,这个结构体的定义是用于描述一个设备驱动

注册函数相关的函数

cdev_alloc:给cdev结构体分配内存(指针实例化)

cdev_init:绑定cdev和file_operations

cdev_add:注册设备

cdev_del:注销设备

3:dev_t类型

    dev_t类型其本质就是一个unsigned int 类型的变量,这个变量用于存放主次设备号,比如高16位存放主设备号,低16位存放次设备号,具体哪些位用来存放主设备号,哪些位用来存放次设备号要看具体的定义。

4:设备号相关的三个宏

MKDEV:由主次设备号换算得到一个设备号

1
2
3
#define MKDEV(ma,mi)    (((ma) << MINORBITS) | (mi))
ma:主设备号
mi:次设备号

MAJOR:从设备号中取出主设备号

1
#define MAJOR(dev)    ((unsigned int) ((dev) >> MINORBITS))

MINOR:从设备号中取出次设备号

1
#define MINOR(dev)    ((unsigned int) ((dev) & MINORMASK))

本文转自 菜鸟养成记 51CTO博客,原文链接:http://blog.51cto.com/11674570/1872435