================================================================
《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
linux misc设备驱动完成