您的位置:首页 > 运维架构 > Linux

Linux设备驱动(2)字符设备

2016-05-08 11:52 639 查看

设备号

设备号由主设备号和次设备号组成。linux下,一切设备皆文件,所有的设备都能在/dev目录下找到相应的文件。这些文件除了名字不一样以外,还每个设备文件都有不一样的设备号;

一般地,主设备号对应一个类型的驱动设备,之所以有次设备号,它是用来驱动同类型的设备。如串口,所有的串口共用一个主设备号,每个串口有不同的次设备号。

dev_t类型用来保存设备编号(包含主设备号和次设备号),实际上是一个32位整数,12位用来表示主设备号,后20位表示次设备号。

#define MINORBITS   20
#define MINORMASK   ((1U << MINORBITS) - 1)

//提取主设备号
#define MAJOR(dev)  ((unsigned int) ((dev) >> MINORBITS))
//提取次设备号
#define MINOR(dev)  ((unsigned int) ((dev) & MINORMASK))
//生成设备号
#define MKDEV(ma,mi)    (((ma) << MINORBITS) | (mi))


设备号的分配和释放

静态分配

/**
* register_chrdev_region() - register a range of device numbers
* @from: the first in the desired range of device numbers; must include
*        the major number.
* @count: the number of consecutive device numbers required
* @name: the name of the device or driver.
*
* Return value is zero on success, a negative error code on failure.
*/
int register_chrdev_region(dev_t from, unsigned count, const char *name)


指定从设备号from开始,申请count个设备号,在/proc/devices中的名字为name

动态分配

int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)


动态申请从次设备号baseminor开始的count个设备号,在/proc/devices中的名字为name,并通过dev指针把分配到的设备号返回给调用函数者。

释放

void unregister_chrdev_region(dev_t from, unsigned count)


设备注册

字符设备struct cdev

struct cdev {
struct kobject kobj;
struct module *owner;//一般初始化为THIS_MODULE
const struct file_operations *ops;//文件操作结构体
struct list_head list;
dev_t dev;//设备号
unsigned int count;//添加的设备个数
};


注册的三个步骤:

1)分配cdev;

2)初始化cdev;

3)添加cdev;

分配

直接定义struct cdev test_cdev;

或者动态分配

truct cdev* test_cdev;

test_cdev = cdev_alloc();

初始化

/**
* cdev_init() - initialize a cdev structure
* @cdev: the structure to initialize
* @fops: the file_operations for this device
*
* Initializes @cdev, remembering @fops, making it ready to add to the
* system with cdev_add().
*/
void cdev_init(struct cdev *cdev, const struct file_operations *fops)


这个函数干了两件事情:

1)内核自己填充了结构体中list和kobj的内容

2)把传入的文件操作结构体也填充进去

一般的,还要手工定义结构体成员owner。

添加

将cdev结构体与设备号关联起来:

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


参数:

cdev:指定要被添加的cdev结构体;

dev:对应的设备号

count:从设备号dev开始添加count个设备.

函数干了也两件事:

1)把cdev结构体中还没填充的两个成员dev和count按照传入参数赋值。

2)把cdev结构体中传入内核,这样内核就知道对应设备号和具体的文件操作结构体了。

删除

void cdev_del(struct cdev *p)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: