申请字符类设备号-10

申请字符类设备号

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

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

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

//都在这个头文件下
#include <linux/fs.h>

第一种:静态分配一个设备号,我们使用的是:

register_chrdev_region(dev_t, unsigned, const char *);
  • 需要明确知道我们的系统里面那些设备号没有用。

  • 参数:

  • 第一个:设备号的起始值。类型是dev_t类型

    dev_t类型:

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

  • 第二个:次设备号的个数。

  • 第三个:设备的名称

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

  • 返回值:成功返回0,失败返回负数使用动态分配会优先使用255到234

typedef _u32  kernel_dev_t;
typedef  kernel_dev_t    dev_t;
//Linux提供了几个宏定义来操作设备号
//在这个文件下
#include <linux/kdev_t.h> 
//次设备号的位数,一共是20位
#define MINORBITS 20
//次设备号的掩码
#define MINORMASK((1U<< MINORBITS) - 1)
//在dev_t里面获取我们的主设备号
#define MAJOR(dev) ((unsigned int)((dev) >> MINORBITS))
//在dev_t里面获取我们的次设备号
#define MINOR(dev) ((unsigned int) ((dev)& MINORMASK))
//MKDEV是将主设备号和次设备号转换成dev_t类型的一个内核函数。
#define MKDEV(ma,mi) ("(ma)<<MINORBITS) [ (mi))
  • 将我们的主设备号和次设备号组成一个dev_t类型。第一个参数是主设备号,第二个参数是次设备号

第二种方法:动态分配我们使用的是

alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *);
  • 参数:
  • 第一个:保存生成的设备号
  • 第二个:我们请求的第一个次设备号,通常是0
  • 第三个:连续申请的设备号的个数。
  • 第四个:设备名称
  • 返回值:成功返回0,失败返回负数使用动态分配会优先使用255到234

注销设备号

//在头文件#include <linux/fs.h> 下
extern void unregister_chrdev_region(dev_t, unsigned);
  • 参数
  • 第一个: 分配设备号的起始地址 可用改函数生成 MKDEV(major_num, minor_num)
  • 第二个: 申请的连续设备号的个数
浏览设备里面的驱动的设备号
cat /proc/devices
注意优先使用动态申请

代码

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
//设备的数量
#define DEVICE_NUMBER 1
//静态名称
#define DEVICE_SNAME "schrdev"
//动态名称
#define DEVICE_ANAME "achrdev"
//次设备号的起始地址
#define DEVICE_MINOR_NUMBER 0

//主设备号,次设备号
static int major_num, minor_num;

module_param(major_num,int,S_IRUSR);
module_param(minor_num,int,S_IRUSR);


static int hello_init(void){

    dev_t dev_num;
    int ret;

    if (major_num)
    {
        dev_num = MKDEV(major_num, minor_num);

        printk("major_num = %d \n",major_num);
        printk("minor_num = %d \n",minor_num);

        ret = register_chrdev_region(dev_num,DEVICE_NUMBER,DEVICE_SNAME);

        if (ret <0 )
        {
            printk("register_chrdev_region 注册失败了 \n");
        }

        printk("register_chrdev_region 注册成功了 \n");      

    }else 
    {

        ret = alloc_chrdev_region(&dev_num, DEVICE_MINOR_NUMBER, DEVICE_NUMBER, DEVICE_ANAME);
        if (ret < 0 )
        {
            printk("alloc_chrdev_region 失败了 \n");
        }

        major_num = MAJOR(dev_num);
        minor_num = MINOR(dev_num);

        printk("major_num = %d \n",major_num);
        printk("minor_num = %d \n",minor_num);

        printk("alloc_chrdev_region 成功了 \n");
        
    }
    
    printk(KERN_ALERT "Hello , World\n"); //内核空间里没有printf,用printk
    return 0;

}

static void hello_exit(void){
    unregister_chrdev_region(MKDEV(major_num, minor_num), DEVICE_NUMBER);
    printk(KERN_ALERT "Goodbye 注销成功 , World\n");
}

//模块的注册
module_init(hello_init);
//模块的卸载
module_exit(hello_exit);
MODULE_LICENSE("Dual BSD/GPL");

执行
//注意 静态申请需要看设备中那个主设备号没有注册
insmod chrdev.ko major_num=9
insmod chrdev.ko 
rmmod chrdev.ko 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值