linux驱动:(11)注册字符类设备

cdev结构体

描述字符设备的一个结构体

struct cdev{
    struct kobject kobj;
    struct module *owner;//属于哪个模块的
    const struct file_operations *ops;//文件操作集
    struct list_head list;//链表的节点
    dev_t dev;//设备号
    unsigned int count;//设备号数量
};

步骤

  • 完成第十章的文章里的步骤
  • 添加头文件
  • 定义一个cdev结构体和文件操作集
  • 在驱动init函数中获取设备号后使用cdev_init函数初始化cdev结构体成员变量
    • void cdev_init(struct cdev* , const struct file_operations *);
    • 参数1:要初始化的cdev
    • 参数2:文件操作集,在函数中会将操作集赋值到cdev -> ops
  • 在驱动init函数中初始化cdev结构体后使用cdev_add函数注册字符设备到内核
    • int cdev_add(struct cdev* ,dev_t,unsigned);
    • 参数1:cdev 的结构体指针
    • 参数2:设备号
    • 参数3:次设备号的数量
  • 在驱动exit函数中释放设备号后使用cdev_del函数注销字符设备
    • void cdev_del(struct cdev *);
    • 参数1:cdev 的结构体指针
  • 如果要测试的话就在文件操作集中定义open函数,在open函数中输出一句话,等后面拿来测试是否成功

例子

  • 在第十章的基础上添加后面几个步骤
  • 编辑驱动.c
    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/miscdevice.h>
    #include <linux/fs.h>
    #include <linux/kdev_t.h>
    #include <linux/uaccess.h>
    #include <linux/cdev.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);
    
    struct cdev cdev;
    
    module_init(misc_init);
    module_exit(misc_exit);
    
    int chrdev_open(struct inode * inode,struct file * file)
    {
        printk("hello misc_open\n");
        return 0;
    }
    
    struct file_operations chrdev_ops={
        .owner = THIS_MODULE,
        .open = chrdev_open
    };
    
    static int misc_init(void)
    {
        dev_t dev_num;
        int ret;
        if(major_num)
        {    
            printk("major_num= %d\n",major_num);
            printk("minor_num= %d\n",minor_num);
            dev_num = MKDEV(major_num,minor_num);
            ret = register_chrdev_region(dev_num,DEVICE_NUMBER ,DEVICE_SNAME );
            if(ret<0)
            {
                printk("register_chrdev_region error\n");
            }
            printk("register_chrdev_region ok\n");
        }
        else 
        {
            ret = alloc_chrdev_region(&dev_num,DEVICE_MINOR_NUMBER,DEVICE_NUMBER,DEVICE_ANAME);
            if(ret<0)
            {
                printk("alloc_chrdev_regionerror\n");
            }
            printk("alloc_chrdev_regionok\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);
        }
    
        cdev.owner = THIS_MODULE;
        cdev_init(&cdev,&chrdev_ops);
        cdev_add(&cdev,dev_num,DEVICE_NUMBER);
    
        return 0;
    }
     
    static void misc_exit(void)
    {
        unregister_chrdev_region(MKDEV(major_num,minor_num),DEVICE_NUMBER);
    
        cdev_del(&cdev);
    
        printk("misc goodbye");
    }
     
     
    MODULE_LICENSE("GPL");
  • 字符设备注册完以后并不会自动生成设备节点,杂项设备可以,我们需要用mknod命令创建一个设备节点,自动生成下一章讲
    • mknod 想要新建设备节点的名称 类型(字符类型是c) 主设备号 次设备号
    • mknod /dev/test c 247 0
  • 然后新建一个测试.c,里面只需要打开/dev/test就可以看到成不成功了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值