Yuhang Zheng

第九节、申请字符类设备号

N 人看过

本节用于介绍如何申请字符类设备号

1、字符设备和杂项设备的区别(复习)

杂项设备的主设备号是固定的,固定为10,那么我们要学习的字符类设备就需要自己或者系统来给我们分配了。

杂项设备可以自动生成设备节点,字符设备需要我们自己生成设备节点。

2、注册字符类设备号的俩个方法。

第一种:静态分配一个设备号

需要明确知道我们的系统里面那些设备号没有用

文件位置路径:include/linux/fs.h

实际函数位置路径:fs/char_dev.c

extern int register_chrdev_region(dev_t, unsigned, const char *);
int register_chrdev_region(dev_t from, unsigned count, const char *name)
//参数
//from:设备号的起始值。类型是dev_t类型
//count:次设备号的个数
//name:设备的名称
//返回值
//成功:返回0
//失败:返回非0

可以通过以下命令查看linux系统中已经注册的字符设备以及对应的注册名称

root@localhost:~# cat /proc/devices

dev_t类型:

dev_t是用来保存设备号的,是一个32位数

高12位是用来保存主设备号,低20位是用来保存次设备号的

文件位置路径:include/linux/fs.h

typedef __u32 __kernel_dev_t;
typedef __kernel_dev_t          dev_t;

linux提供了几个宏定义来操作设备号

文件位置路径:include/linux/kdev_t.h

#define MINORBITS       20
//次设备号的位数,一共是20位
#define MINORMASK       ((1U << MINORBITS) - 1)
//次设备号的掩码
//0U 表示 无符号整型 0
//1U 表示 无符号整型 1
//(1U << MINORBITS) 的结果是:         0000 0000 0001 0000 0000 0000 0000 0000
//((1U << MINORBITS) - 1)的结果是:    0000 0000 0000 1111 1111 1111 1111 1111
#define MAJOR(dev)      ((unsigned int) ((dev) >> MINORBITS))
//在dev_t里面获取我们的主设备号
#define MINOR(dev)      ((unsigned int) ((dev) & MINORMASK))
//在dev_t里面获取我们的次设备号
#define MKDEV(ma,mi)    (((ma) << MINORBITS) | (mi))
//将我们的主设备号和次设备号组成一个dev_t类型。ma是主设备号,mi是次设备号。

第二种:动态分配设备号

文件位置路径:include/linux/fs.h

实际函数位置路径:fs/char_dev.c

extern int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *);
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)
//参数
//dev:保存生成的设备号,类型是dev_t *类型
//baseminor:我们请求的第一个次设备号,通常是0
//count:次设备号的个数
//name:设备的名称
//返回值
//成功:返回0
//失败:返回非0

使用动态分配会优先使用255到234

被废弃的函数:

文件位置路径:include/linux/fs.h

extern int __register_chrdev(unsigned int major, unsigned int baseminor,
                             unsigned int count, const char *name,
                             const struct file_operations *fops);
extern void __unregister_chrdev(unsigned int major, unsigned int baseminor,
                                unsigned int count, const char *name);

因为此函数在注册设备的时候,第一个传入的参数是主设备号,它会将主设备号下的所有此设备号全部申请,造成资源浪费。

3、注销设备号

文件位置路径:include/linux/fs.h

实际函数位置路径:fs/char_dev.c

extern void unregister_chrdev_region(dev_t, unsigned);
void unregister_chrdev_region(dev_t from, unsigned count)
//参数
//from:设备号的起始值。类型是dev_t类型
//count:申请的连续的次设备号的个数

建议使用动态申请