注册字符类设备
-
分配内存空间函数 kmalloc 用于分配连续虚拟地址小内存分配,在linux/slab.h 头文件中
- 参数1 申请内存的大小最大128k
- 参数2 GFP_KERNEL 代表优先权,内存不够延迟分配
-
清空内存数据memset 参数1 地址,参数2 起始地址,参数3 长度
-
字符设备初始化函数cdev_init
- 在头文件include/linux/cdev.h
- 参数1cdev 字符设备文件结构体
- 参数2 file_operation 结构体
- 注册设备本质是想linux 设备文件中添加数据,这些数据需要初始化
-
字符设备注册函数cdev_add
- 在头文件include/linux/cdev.h
- 参数1cdev 字符设备结构体
- 参数2设备号
- 参数3 设备范围大小
- 向系统注册设备也是想linux 系统添加数据
源码
#include <linux/init.h>
#include <linux/module.h>
// 定义module_param module_param_arrary 函数的头文件
#include <linux/moduleparam.h>
// 定义参数函数中perm 参数的枚举量头文件
#include <linux/stat.h>
// MKDEV 转换设备号数据类型的宏定义
#include <linux/kdev_t.h>
// 三个字符设备号函数
#include <linux/fs.h>
// 定义字符设备的结构体
#include <linux/cdev.h>
// 分配内存空间的函数
#include <linxu/slab.h>
#defind DEVICE_NAME "dcdev";
#defind DEVICE_MINOR_NUM 2;
#defind DEVICE_MAJOR 0;// 主设备号
#defind DEVICE_MINOR 0;
#defind REGDEV_SIZE 3000;
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 failed\n ",numdev_major);
}
if(!ret){
printk(KERN_EMERG,"\t register_chrdev_region req %d is failed\n ",numdev_major);
}
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[i].data = kmalloc(REGDEV_SIZE,GFP_KERNEL);
memset(my_devices[i].data,0,REGDEV_SIZE);
/*设备注册到系统*/
ret_init_cdev(&my_devices[i],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:%d\n ",module_arg2);
/*除去字符设备*/
for(i = 0;i < DEVICE_MINOR_NUM;i++){
cdev_del(&(my_devices[i]->cdev));
}
unregister_chrdev_region(MKDEV(numdev_major,numdev_minor),DEVICE_MINOR_NUM);
return 0;
}