注册字符设备完整流程代码详解

 设备节点

 在Linux中,设备节点(也称为设备文件)是文件系统中的一种特殊文件,它提供了一个接口来访问硬件设备。设备节点允许用户空间程序通过标准的文件操作(如openreadwriteclose等)来与硬件设备交互,而无需了解硬件的具体细节。

设备节点通常位于/dev目录下,这是专门用于存放设备文件的目录。在/dev目录中,每个设备节点都代表了一个硬件设备或设备的一个特定部分(如磁盘的一个分区)。

设备节点根据其代表的设备类型被分为两类:字符设备(character device)和块设备(block device)。

  • 字符设备:字符设备以字符为单位进行数据的读写操作。这种设备通常不支持随机访问,即每次读写操作都是从设备的当前位置开始的。字符设备通常用于那些需要按字节或按行进行输入输出的设备,如串口、键盘、鼠标、打印机等。

  • 块设备:块设备以数据块为单位进行数据的读写操作。这种设备支持随机访问,即可以跳过设备上的某些部分直接访问其他部分。块设备通常用于存储大量数据,如硬盘、U盘、SD卡等。

 设备号的申请

在Linux中,每个字符设备都需要一个唯一的设备号来标识。设备号由主设备号和次设备号组成,其中主设备号用于区分不同类型的设备,而次设备号则用于区分同一类型下的不同设备。

设备号是一个无符号32位整数,数据类型为dev_t,设备号分为两部分:

主设备号:占高12位,用来表示驱动程序相同的一类设备
次设备号:占低20位,用来表示被操作的哪个具体设备
应用程序打开一个设备文件时,通过设备号来查找定位内核中管理的设备。

MKDEV宏用来将主设备号和次设备号组合成32位完整的设备号,用法:

 dev_t devno;
int major = 11;//主设备号
int minor = 0;//次设备号
devno = MKDEV(major,minor);

MAJOR宏用来从32位设备号中分离出主设备号,用法:

dev_t devno = MKDEV(11,0);
int major = MAJOR(devno);

MINOR宏用来从32位设备号中分离出次设备号,用法:

dev_t devno = MKDEV(11,0);
int minor = MINOR(devno);

1. 静态指定设备号

如果开发者知道想要使用的设备号,可以使用register_chrdev_region函数来静态指定设备号。

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

  • from:指定的起始设备号(主设备号和次设备号的组合)。
  • count:要申请的设备号的数量。
  • name:设备驱动的名称。

 

2.动态申请设备号

如果开发者不确定使用哪个设备号,可以使用alloc_chrdev_region函数来动态申请一定范围内的设备号。

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

  • dev:用于存储申请到的设备号的指针。
  • baseminor:次设备号的起始值。
  • count:要申请的设备号的数量。
  • name:设备驱动的名称。

         如果已知一个设备的主次设备号,应用层指定好设备文件名,那么可以用mknod命令在/dev目录创建代表这个设备的文件,即此后应用程序对此文件的操作就是对其代表的设备操作。

下面是在Linux上面操作的命令: 

在include/linux 查询指定函数:

grep 名称 ./ -r -n 

查看当前设备号: 

cat /proc/devices | grep mychar

创建一个字符设备:

sudo mknod /dev/mydev c 11 0

  • mknod:是创建特殊文件的命令。
  • /dev/mydev:是你要创建的设备文件的路径和名称。
  • c:指定要创建的文件是一个字符设备(character device)。与之相对的是块设备(block device),用 b 表示。
  • 11:是主设备号(major number),用于区分不同类型的设备。在这个例子中,选择了11作为主设备号。请注意,选择一个已经在使用中的主设备号可能会导致冲突。
  • 0:是次设备号(minor number),用于在同一种类型的设备中区分不同的设备实例。在这个例子中,选择了0作为次设备号。

若在应用程序中要创建设备可以调用系统调用函数mknod: 

int mknod(const char *pathname,mode_t mode,dev_t dev);

  • pathname:带路径的设备文件名,无路径默认为当前目录,一般都创建在/dev下
  • mode:文件权限 位或 S_IFCHR/S_IFBLK
  • dev:32位设备号

返回值:成功为0,失败-1

 3.释放设备号:

void unregister_chrdev_region(dev_t from, unsigned count);
功能:释放设备号

  •     from:已成功分配的设备号将被释放
  •     count:申请成功的设备数量
 基本模板示例(mychar.c):
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>

int major = 11;					//主设备号
int minor = 0;					//次设备号
int char_num = 1;				//设备号数量

int __init mychar_init(void) 
{
	int ret = 0;
    //将主次设备号合成一个完整设备号
	dev_t devno = MKDEV(major, minor);

	/* 手动申请设备号 若返回值不为0,则自动设置*/
	ret = register_chrdev_region(major, char_num, "mychar");
	if (ret) {
		/* 动态申请设备号 */
		ret = alloc_chrdev_region(&devno, minor, char_num, "mychar");
		if(ret){
			printk("get devno failed\n");
			return -1;
		}
		/*申请成功 更新设备号*/
		major = MAJOR(devno);//自动分配的设备号不一定是11,所以需要分离出其主设备号
							 //因为次设备号都是从0开始.
	}
	
	return 0;
}

void __exit mychar_e
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值