Liunx驱动 实现一个misc设备驱动

By | 2019-09-23

================================================================
Linux驱动 编译一个hello模块
Linux驱动 实现一个字符设备驱动
Liunx驱动 实现一个misc设备驱动
================================================================

为什么要学习misc设备的编程

因为,如果我们 每个驱动设备都要像最初那样子去写一个字符设备驱动一样,要分配主设备号,次设备号,实现对应的文件操作函数等等的步骤,未免就有点多了,而且也不好记住它,为此,Linux内核提供了一系列偷懒的技巧,那就是实现了misc设备,其实misc设备,也算是字符设备,只不过对字符设备进行了封装,看看下面的介绍就知道了

打开内核/include/linux/miscdevice.h 找到misc设备的结构体:

struct miscdevice  {
	//次设备号一般赋值为MISC_DYNAMIC_MINOR---->由内核自动去分配次设备号
	int minor;
	//misc设备的名称
	const char *name;
	//文件操作结构体
	const struct file_operations *fops;
	struct list_head list;
	struct device *parent;
	struct device *this_device;
	const struct attribute_group **groups;
	const char *nodename;
	umode_t mode;
};

这里我只实现最简单的misc设备,只需要关注minor(次设备号),name(设备名称),fops(文件操作函数)。

misc设备是对字符设备做了一个再次的封装,而且,在misc设备中,主设备号都是一样的,都是10,只有次设备号不同,当我们不知道内核中应该去分配那个此设备号时,可以直接给minor赋值为MISC_DYNAMIC_MINOR这个宏,意思就是由内核来帮我们分配次设备号。

name就不用说了,如果设备注册成功,在根文件系统/dev/下就会有注册设备后的name。

fops就是一系列的文件操作函数啦,什么open , read ,write , ioctl等等,很多,跟写字符设备是一样的 。

驱动实现源码代码如下:

#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/miscdevice.h>
#include<linux/fs.h>


#define DEVICE_NAME "my_misc_dev"

//实现open函数
int my_misc_dev_open(struct inode *inode, struct file *filp)
{
	printk("minipc misc dev open!\n");
	return 0 ;
}

//实现close函数
int my_misc_dev_close(struct inode *inode, struct file *filp)
{
	printk("minipc misc dev close!\n");
	return 0 ;
}

//初始化文件操作结构体
struct file_operations file_ops = {
	.owner	 = THIS_MODULE,
	.open	 = my_misc_dev_open,
	.release = my_misc_dev_close,
};

//初始化misc设备结构体
struct miscdevice my_misc_dev = {
	//由内核自动分配次设备号
	.minor = MISC_DYNAMIC_MINOR ,
	//初始化设备名称
	.name = DEVICE_NAME ,
	//初始化文件操作结构体
	.fops = &file_ops,	
};


static int __init my_misc_dev_init(void) 
{
	int ret_error ;
	//注册misc设备
	int ret = misc_register(&my_misc_dev);
	if(ret != 0){
	   ret_error = ret ;
	   printk("misc register fair!\n");
	   goto fair ;
	}
	printk("misc init success!\n");	
	return ret ;
fair:
	return ret_error ;
}
 
static void __exit my_misc_dev_exit(void) 
{
	//注销misc设备
	misc_deregister(&my_misc_dev);
}

module_init(my_misc_dev_init);
module_exit(my_misc_dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("LAOHU add misc driver");

Makefile:

TARGET		?= $(shell uname -r)
KERNEL_MODULES	?= /lib/modules/$(TARGET)
KERNEL_BUILD	?= $(KERNEL_MODULES)/build
SYSTEM_MAP	?= $(KERNEL_BUILD)/System.map

DRIVER := my_misc

obj-m	:= $(patsubst %,%.o,$(DRIVER))
obj-ko  := $(patsubst %,%.ko,$(DRIVER))

MAKEFLAGS += --no-print-directory

.PHONY: all modules clean

all: modules

# Targets for running make directly in the external module directory:

modules clean:
	@$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) $@

编译程序,加载驱动,可以看到设备注册成功,主设备号:10,次设备号55

misc device

linux misc设备驱动完成

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注