4、驱动设备号

什么是设备号:

Linux 规定 每个字符设备或者块设备必须有一个专属的设备号;一个设备号由主设备号 和次设备号组成;

主设备号和次设备号是什么?

主设备号 在Linux是唯一的,次设备号不一定;

设备号是计算机识别设备的一种方式,主设备相同就被视为同一类的设备;

查看主设备号命令:

cat /proc/devices

设备号类型

        Linux使用dev_tde数据类型表示设备号,定义在 include/linux/types.h 头文件里面;

其中 dev_t 是一个u32类型,其中高12bit是主设备号,低20bit是次设备号;

设备号操作宏

  • MINORBITS:表示次设备号的位数,通常为20位。这个宏定义了次设备号在dev_t类型中所占的位数。
  • MINORMASK:用于计算次设备号使用的掩码,其值为(1U << MINORBITS) - 1
  • MAJOR(dev):从dev_t类型的设备号中提取主设备号。其实现通常是将设备号右移MINORBITS位。
  • MINOR(dev):从dev_t类型的设备号中提取次设备号。其实现通常是取设备号与MINORMASK进行位与操作。
  • MKDEV(ma, mi):由主设备号(ma)和次设备号(mi)合成一个dev_t类型的设备号。其实现通常是将主设备号左移MINORBITS位后与次设备号进行位或操作。

设备号相关函数

设备号申请

编写字符设备驱动代码时候,可以静态分配设备号也可以动态分配设备号

有两个函数实现这两种功能

/* 静态申请 */
int register_chrdev_region(dev_t from, unsigned count, const char *name);

//from:要申请的起始设备号,通常是通过MKDEV(major, 0)宏计算得到的,其中major是已知的主设备号。
//count:要申请的设备号数量。
//name:设备名,这个名称将出现在/proc/devices文件中。
//成功时返回0,失败时返回负数错误码。



/* 动态申请 */

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

//dev:用于接收分配到的起始设备号的指针。
//baseminor:起始次设备号,如果不需要特别指定,可以设为0。
//count:要申请的设备号数量。
//name:设备名,这个名称将出现在/proc/devices文件中。

//成功时返回0,并将分配到的起始设备号存储在*dev中;失败时返回负数错误码。

释放设备号

/* 释放设备号 */
void unregister_chrdev_region(dev_t first, unsigned int count);

//first:要注销的起始设备号。对于unregister_chrdev_region函数来说,这个参数是设备号范围的起始
//值,通常是通过MKDEV(major, 0)宏计算得到的,其中major是之前申请到的主设备号。
//count:要注销的设备号数量。这个参数指定了要注销的设备号范围中的设备号数量。

例程

#include<linux/module.h>
#include<linux/init.h>

#include<linux/fs.h>
#include<linux/modulepram.h>
#include<linux/kdev_t.h>


static int major;
static int minor; 

 
module_param(major,int,S_IRUGO);
MODULE_PARAM_DESC(major,"e.g:major=1");
 
module_param(minor,int,S_IRUGO);
MODULE_PARAM_DESC(minor,"e.g:minor=1");
 

 
 
static int hello_init(void)
{
    dev_t dev_num;
    int ret;
    printk("input major=%d minor=%d \n",major,minor);


    if(major == 0)
    {
        //静态申请
        dev_num=MKDEV(major,minor);
        ret=register_chrdev_region(dev_num,1,"chrdev_num");
        if(0 != ret)
        {
            printk("register_chrdev_region err %d\n",ret);
            return ret;
        }
    }
    else
    {
       //动态申请
        ret=alloc_chrdev_region(&dev_num,0,1,"chrdev_num");
        if(0 != ret)
        {
            printk("alloc_chrdev_regionerr %d\n",ret);
            return ret;
        }
       printk("dev_num=%d \n",dev_num);
       major = MAJOR(dev_num);
       minor = MINOR(dev_num);
       printk("input major=%d minor=%d \n",major,minor);

    }

    
    printk("hello word init\n");
    return 0;
}
 
static void hello_exit(void)
{
    //释放设备号
    unregister_chrdev_region(dev_num,1);

    printk("hello word exit\n");
    return 0;
}

 
module_init(hello_init);
module_exit(hello_exit);
 
MODULE_LICENSE("GPL");
MODULE_AUTHOR("SONG");
MODULE_VERSION("v1.0");

编译生成.ko文件 加载到目标板

查看打印是否正确,也可以通过命令查看

cat  /proc/devices 

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值