嵌入式学习小组
直播中

h1654155275.5916

7年用户 993经验值
私信 关注

如何生成设字符类设备节点?

如何生成设字符类设备节点?

回帖(1)

谢丹丹

2021-12-23 14:51:22
概念




  • 设备类 bus device driver 都是有比较明确定义的,bus 代表总线,device 代表实际的设备和接口,driver 代表驱动
  • class 是设备类,他是一个抽象的概念,没有对应的实体,它是提供给用户借口相似的一类设备的集合,常见的输入子系统input,u*** 串口tty,块设备block 等

生成设字符类设备节点




  • 函数class_create 创建类文件
  • 参数1一般是THIS_MODULE
  • 参数2 设备名称
  • 创建一个设备类用与节点文件的创建
  • 返回一个class 结构体变量
  • class 结构体变量
  • class 是设备驱动模型中的通用设备类结构
  • 在头文件include /linux /device.h 中定义
    -class_destory 释放class

初始化代码中创建设备节点




  • 创建设备节点函数device_create
  • 头文件在include/linux/device.h
  • 参数1设备所属的类
  • 参数2设备的父设备,NULL
  • 参数3设备号
  • 参数4设备数据NULL
  • 参数5设备名称
  • 摧毁设备节点函数device_destory 参数1 所属类,参数2 设备号
  • 释放内存kfree

源码


#include
#include
// 定义module_param module_param_arrary 函数的头文件
#include
// 定义参数函数中perm 参数的枚举量头文件
#include




// MKDEV 转换设备号数据类型的宏定义
#include
// 三个字符设备号函数
#include
// 定义字符设备的结构体
#include
// 分配内存空间的函数
#include


#defind DEVICE_NAME "dcdev";
#defind DEVICE_MINOR_NUM 2;
#defind DEVICE_MAJOR 0;// 主设备号
#defind DEVICE_MINOR 0;
#defind REGDEV_SIZE 3000;


#include ;


static struct class *myClass;


module_init(sdev_init);
module_exit(sdev_exit);


static int module_arg1,module_arg2;
static int int_array[50];
static int int_num;
int numdev_major = DEVICE_MAJOR;
int numdev_minor = DEVICE_MINOR;
/**/


// 输入主设备号
module_param(numdev_major,int,S_IRUSR);
// 输入次设备号
module_param(numdev_minor,int,S_IRUSR);


struct reg_dev{
        char* data;
        unsigned long size;
        struct cdev cdev;
};
struct file_operations my_fops = {
        .owner = THIS_MODULE,
};




static void ret_init_cdev(struct reg_dev * dev,int index){
        int error;
        /*数据初始化*/
        int devno = MKDEV(numdev_major,numdev_minor+index);
        cdev_init(&dev->cdev,&my_fops);
        dev->cdev.owner = THIS_MODULE;
        dev->cdev.ops = &my_fops;


        err = cdev_add(&dev->cdev,devno,1);
        if(err){
                printk(KERN_EMERG,"t cdev_add is fail err is %d n ",err);
        }else{
                printk(KERN_EMERG,"t cdev_add success! n" );
        }
}
struct reg_dev* my_devices;


static int sdev_init(void)
{
        int ret = -1;
        dev_t num_dev;
        if(numdev_major){// 如果0 则动态申请
                num_dev = MKDEV(numdev_major,numdev_minor);
                ret = register_chrdev_region(num_dev,DEVICE_MINOR_NUM,DEVICE_NAME);
               
        }else{
                ret = allo_chrdev_region(&num_dev,numdev_minor,DEVICE_MINOR_NUM,DEVICE_NAME);
                numdev_major = MAJOR(num_dev);
                printk(KERN_EMERG,"t numdev_major %d is failedn ",numdev_major);
        }
        if(!ret){
                printk(KERN_EMERG,"t register_chrdev_region req %d is failedn ",numdev_major);
        }
        myClass = class_create(THIS_MODULE,DEVICE_NAME);
        my_devices = kmalloc(DEVICE_MINOR_NUM*sizeof(struct reg_dev),GPF_KERNEL);
        if(!my_devices){
                ret = -ENOMEM;
                goto fail;
                return 0;
        }
        /*初始化设备*/
        for(int i = 0 ;i < DEVICE_MINOR_NUM;i++){
                my_devices.data = kmalloc(REGDEV_SIZE,GFP_KERNEL);
                memset(my_devices.data,0,REGDEV_SIZE);
                /*设备注册到系统*/
                ret_init_cdev(&my_devices,i);
                /*创建设备节点*/
                device_create(myClass,NULL,MKDEV(numdev_major,numdev_minor+i),NULL,DEVICE_NAME"%d",i);
        }
        memset(my_devices,0,DEVICE_MINOR_NUM * sizeof(struct reg_dev));
        printk(KERN_EMERG,"  dcdev enter!n ");
        return 0;
fail:
        /*注销设备号*/
        unregister_chrdev_region(MKDEV(numdev_major,numdev_minor),DEVICE_MINOR_NUM);                                      
        printk(KERN_EMERG,"kmalloc is fail!n ");
        return 0;
}




static int sdev_exit(void)
{
        int i = 0;
        printk(KERN_EMERG,"t cdev is:%dn ",module_arg2);
        /*除去字符设备*/
        for(i = 0;i < DEVICE_MINOR_NUM;i++){
                cdev_del(&(my_devices->cdev));
                device_destory(myClass,MKDEV(numdev_major,numdev_minor+i));
        }
        class_destory(myClass);
        kfree(my_devices);
        unregister_chrdev_region(MKDEV(numdev_major,numdev_minor),DEVICE_MINOR_NUM);
        return 0;
}
ls /sys/class   能看到新的设备类节点
ls /dev/    看到设备节点
手动创建设备节点

mknod dev/test0 c 249 0mknod dev/test0 c 249 1
举报

更多回帖

×
20
完善资料,
赚取积分