#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>//cdev结构体的头文件
#include <linux/device.h>//class、create函数
/*注意:以下代码是申请了设备号 + 注册到内核中,但是并没有创建设备节点,因此需要完成这两部后需要
执行命令 mknod /dev/test c 247 0 来创建一个设备节点test c的意思是test的文件类型 247是主设备号
0 是次设备号*/
static int major_num,minor_num;//定义主/次设备号,传参的时候只传递主设备号,次设备号默认是0
//dev_t就是int类型,高12位是主设备号,低20位是次设备号
dev_t dev_num;
//向模块传参的函数
module_param(major_num,int,S_IRUSR);
module_param(minor_num,int,S_IRUSR);
struct cdev cdev;
struct class *class;
struct device *device;
int chrdev_open(struct inode *inode,struct file *file)
{
printk("chrdev_open ok\n");
return 0;
}
struct file_operations chrdev_ops = {
.owner = THIS_MODULE,
.open = chrdev_open
};
static int hello_init(void)
{
int ret;
//如果传入了主设备号(大于0),那么使用静态申请的方式申请设备号,否则使用动态申请
if(major_num > 0)
{
//将主次设备号合并成一个 dev_t类型的变量
dev_num = MKDEV(major_num,minor_num);
//静态申请一个字符设备号,参数:①设备号②次设备号的个数③设备名称(/proc/devices文件中有 如10 misc)
ret = register_chrdev_region(dev_num,1,"s_name");
if(ret == 0)
{
printk("静态申请成功\n");
}else{
printk("静态申请失败\n");
}
}else
{
//动态分配设备号,参数①dev_t设备号②次设备号的起始值③次设备号的个数④设备号名称
ret = alloc_chrdev_region(&dev_num,0,1,"d_name");
if(ret < 0)
{
printk("动态申请失败\n");
}else
{
printk("动态申请成功\n");
}
major_num = MAJOR(dev_num);//取出动态分配的主设备号
minor_num = MINOR(dev_num);//取出次设备号
}
//cdev成员初始化,cdev_init函数就是添加一个文件操作集
cdev.owner = THIS_MODULE;
cdev_init(&cdev,&chrdev_ops);
//将cdev结构体添加到内核中
cdev_add(&cdev,dev_num,1);
//创建一个class类
class = class_create(THIS_MODULE,"dev_class");
device = device_create(class,NULL,dev_num,NULL,"/dev/dev_name");
return 0;
}
static void hello_exit(void)
{
//注销设备号,参数①dev_t设备号,②申请的次设备号的个数
unregister_chrdev_region(MKDEV(major_num,minor_num),1);
//注销cdev结构体
cdev_del(&cdev);
//注销设备节点
device_destroy(class,dev_num);
//注销class类
class_destroy(class);
printk("bye bye\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
步骤:
1、申请设备号。在/proc/devices文件中可以看到,如 10 misc
2、创建cdev结构体 + 编写文件操作集fops。cdev_add(&cdev,dev_num,1) ---> 将结构体和设备号绑定并注册到内核中。
3、创建 class类。class_create函数,在 sys/class目录下可以看到,同一种类型驱动。
4、在class下创建设备节点。device_create函数,在/dev目录下就有了设备节点。