申请和注销设备号的方法

一、Linux内核对设备的分类

linux的文件种类:

  1. -:普通文件

  2. d:目录文件

  3. p:管道文件

  4. s:本地socket文件

  5. l:链接文件

  6. c:字符设备

  7. b:块设备

Linux内核按驱动程序实现模型框架的不同,将设备分为三类:

  1. 字符设备:按字节流形式进行数据读写的设备,一般情况下按顺序访问,数据量不大,一般不设缓存

  2. 块设备:按整块进行数据读写的设备,最小的块大小为512字节(一个扇区),块的大小必须是扇区的整数倍,Linux系统的块大小一般为4096字节,随机访问,设缓存以提高效率

  3. 网络设备:针对网络数据收发的设备

总体框架图:

 

二、设备号------内核中同类设备的区分

内核用设备号来区分同类里不同的设备,设备号是一个无符号32位整数,数据类型为dev_t,设备号分为两部分:

  1. 主设备号:占高12位,用来表示驱动程序相同的一类设备

  2. 次设备号:占低20位,用来表示被操作的哪个具体设备

应用程序打开一个设备文件时,通过设备号来查找定位内核中管理的设备。

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

dev_t devno;
int major = 251;//主设备号
int minor = 2;//次设备号
devno = MKDEV(major,minor);//将自定义的主设备号和次设备号结合为内核可以区分的32位的设备号

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

dev_t devno = MKDEV(249,1);
int major = MAJOR(devno);

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

dev_t devno = MKDEV(249,1);
int minor = MINOR(devno);

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

@ cd /dev
@ mknod 设备文件名 设备种类(c为字符设备,b为块设备)  主设备号  次设备号    //ubuntu下需加sudo执行 ,例如在dev目录下要创建的设备文件名为mydev,其为字符设备,主设备号自定义为20,次设备号为1,则使用命令 sudo mknod /dev/mydev c 20 1 来创建对应的设备驱动文件。

在应用程序中如果要创建设备可以调用系统调用函数mknod,其原型如下:

int mknod(const char *pathname,mode_t mode,dev_t dev);
pathname:带路径的设备文件名,无路径默认为当前目录,一般都创建在/dev下
mode:文件权限 位或 S_IFCHR/S_IFBLK
dev:32位设备号
返回值:成功为0,失败-1

三、申请和注销设备号

字符驱动开发的第一步是通过模块的入口函数向内核添加本设备驱动的代码框架,主要完成:

  1. 申请设备号

  2. 定义、初始化、向内核添加代表本设备的结构体元素

int register_chrdev_region(dev_t from, unsigned count, const char *name)
功能:手动分配设备号,先验证设备号是否被占用,如果没有则申请占用该设备号
参数:
    from:自己指定的设备号
    count:申请的设备数量
    name:/proc/devices文件中与该设备对应的名字,方便用户层查询主设备号
返回值:
    成功为0,失败负数,绝对值为错误码

int alloc_chrdev_region(dev_t *dev,unsigned baseminor,unsigned count, const char *name)
功能:动态分配设备号,查询内核里未被占用的设备号,如果找到则占用该设备号
参数:
    dev:分配设备号成功后用来存放分配到的设备号
    baseminior:起始的次设备号,一般为0
    count:申请的设备数量
    name:/proc/devices文件中与该设备对应的名字,方便用户层查询主次设备号
返回值:
    成功为0,失败负数,绝对值为错误码

分配成功后在/proc/devices 可以查看到申请到主设备号和对应的设备名,mknod时参数可以参考查到的此设备信息

void unregister_chrdev_region(dev_t from, unsigned count)
功能:释放设备号
参数:
    from:已成功分配的设备号将被释放
    count:申请成功的设备数量

释放后/proc/devices文件对应的记录消失

注:在申请时若是动态申请,则需要使用MAJOR来重新为主设备号赋值,因为动态申请使用的主设备号是我们所不知道的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Linux中,设备是用于标识设备的唯一标识符。设备由主设备和次设备组成。主设备用于标识设备驱动程序,次设备用于标识同一驱动程序下的不同设备。下面是Linux申请设备的步骤: 1. 定义一个dev_t类型的变量mydev,用于存储申请到的设备。 2. 调用alloc_chrdev_region函数向内核申请一个可以使用的设备,该函数的参数依次为:存储设备的变量、次设备的起始值、设备的数量、设备名称。 3. 判断设备申请是否成功,如果失败则返回错误码。 4. 打印申请到的设备、主设备和次设备。 5. 初始化Linux2.6的核心结构体,包括设置所有者、打开函数和关闭函数。 6. 向内核注册一个Linux2.6的核心结构体,包括核心结构体、设备设备数量。 下面是一个示例代码: ```c #include <linux/fs.h> #include <linux/cdev.h> dev_t mydev; struct cdev mycdev; struct file_operations myfops = { .owner = THIS_MODULE, .open = myopen, .release = myclose, }; int myinit(void) { int ret; // 申请设备 ret = alloc_chrdev_region(&mydev, 0, 1, "beep"); if (ret < 0) { printk("设备申请失败\n"); return -1; } printk("dev:%d\n", mydev); printk("主设备:%d\n", MAJOR(mydev)); printk("次设备:%d\n", MINOR(mydev)); // 初始化核心结构体 cdev_init(&mycdev, &myfops); // 注册核心结构体 cdev_add(&mycdev, mydev, 1); return 0; } void myexit(void) { // 注销设备 unregister_chrdev_region(mydev, 1); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值