第九节、申请字符类设备号
本节用于介绍如何申请字符类设备号
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:申请的连续的次设备号的个数
建议使用动态申请