4. 字符设备驱动 — [野火]嵌入式Linux驱动开发实战指南——基于LubanCat

4. 字符设备驱动 — [野火]嵌入式Linux驱动开发实战指南——基于LubanCat

4.4.1.1. 设备号的申请和归还¶

Linux内核提供了两种方式来定义字符设备,如下所示。

定义字符设备¶

1

2

3

4//第一种方式

static struct cdev chrdev;

//第二种方式

struct cdev *cdev_alloc(void);

第一种方式,就是我们常见的变量定义;第二种方式,是内核提供的动态分配方式,调用该函数之

后,会返回一个struct cdev类型的指针,用于描述字符设备。

从内核中移除某个字符设备,则需要调用cdev_del函数,如下所示。

cdev_del函数¶

1void cdev_del(struct cdev *p)

函数参数和返回值如下:

参数:

p: 该函数需要将我们的字符设备结构体的地址作为实参传递进去,就可以从内核中移除该字符设备了。

返回值: 无

register_chrdev_region函数

register_chrdev_region函数用于静态地为一个字符设备申请一个或多个设备编号。函数原型如下所示。

register_chrdev_region函数¶

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

函数参数和返回值如下:

参数:

from:dev_t类型的变量,用于指定字符设备的起始设备号,如果要注册的设备号已经被其他的设备注册了,那么就会导致注册失败。

count:指定要申请的设备号个数,count的值不可以太大,否则会与下一个主设备号重叠。

name:用于指定该设备的名称,我们可以在/proc/devices中看到该设备。

返回值: 返回0表示申请成功,失败则返回错误码

alloc_chrdev_region函数

使用register_chrdev_region函数时,都需要去查阅内核源码的Documentation/devices.txt文件,

这就十分不方便。因此,内核又为我们提供了一种能够动态分配设备编号的方式:alloc_chrdev_region。

调用alloc_chrdev_region函数,内核会自动分配给我们一个尚未使用的主设备号。

我们可以通过命令“cat /proc/devices”查询内核分配的主设备号。

alloc_chrdev_region函数原型¶

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

函数参数和返回值如下:

参数:

dev:指向dev_t类型数据的指针变量,用于存放分配到的设备编号的起始值;

baseminor:次设备号的起始值,通常情况下,设置为0;

count、name:同register_chrdev_region类型,用于指定需要分配的设备编号的个数以及设备的名称。

返回值: 返回0表示申请成功,失败则返回错误码

unregister_chrdev_region函数

当我们删除字符设备时候,我们需要把分配的设备编号交还给内核,对于使用register_chrdev_region函数

以及alloc_chrdev_region函数分配得到的设备编号,可以使用unregister_chrdev_region函数实现该功能。

unregister_chrdev_region函数(内核源码/fs/char_dev.c)¶

1void unregister_chrdev_region(dev_t from, unsigned count)

函数参数和返回值如下:

参数:

from:指定需要注销的字符设备的设备编号起始值,我们一般将定义的dev_t变量作为实参。

count:指定需要注销的字符设备编号的个数,该值应与申请函数的count值相等,通常采用宏定义进行管理。

返回值: 无

register_chrdev函数

除了上述的两种,内核还提供了register_chrdev函数用于分配设备号。该函数是一个内联函数,它不

仅支持静态申请设备号,也支持动态申请设备号,并将主设备号返回,函数原型如下所示。

register_chrdev函数原型(内核源码/include/linux/fs.h文件)¶

1

2

3

4

5static inline int register_chrdev(unsigned int major, const char *name,

const struct file_operations *fops)

{

return __register_chrdev(major, 0, 256, name, fops);

}

函数参数和返回值如下:

参数:

major:用于指定要申请的字符设备的主设备号,等价于register_chrdev_region函数,当设置为0时,内核会自动分配一个未使用的主设备号。

name:用于指定字符设备的名称

fops:用于操作该设备的函数接口指针。

返回值: 主设备号

我们从以上代码中可以看到,使用register_chrdev函数向内核申请设备号,同一类字

符设备(即主设备号相同),会在内核中申请了256个,通常情况下,我们不需要用到这么多个设备,这就造成了极大的资源浪费。

unregister_chrdev函数

使用register函数申请的设备号,则应该使用unregister_chrdev函数进行注销。

unregister_chrdev函数(内核源码/include/linux/fs.h)¶

1

2

3

4static inline void unregister_chrdev(unsigned int major, const char *name)

{

__unregister_chrdev(major, 0, 256, name);

}

函数参数和返回值如下:

参数:

major:指定需要释放的字符设备的主设备号,一般使用register_chrdev函数的返回值作为实参。

name:执行需要释放的字符设备的名称。

返回值: 无

相关推荐

春天在哪里
office365打不开doc文件

春天在哪里

📅 09-29 👁️ 5786
花甲怎么保存?
365bet在线注册

花甲怎么保存?

📅 10-08 👁️ 6626
央行为啥叫“央妈”,和中行有什么区别?
office365打不开doc文件

央行为啥叫“央妈”,和中行有什么区别?

📅 06-29 👁️ 2815