1、简介
Linux杂项驱动出现的意义在于:有很多简单的外围字符设备,它们功能相对简单,一个设备占用一个主设备号对于内核资源来说太浪费。
所有这些设备都统一采用主设备号为10,次设备动态分配的方式注册到内核
杂项设备描述结构体
linux/miscdevice.h
struct miscdevice {
int minor;//次设备号
const char *name;//设备的名字
const struct file_operations *fops;//设备的操作函数集
struct list_head list;//将miscdevice串成链表使用
struct device *parent;//父设备(设备模型有关)
struct device *this_device;//代表自己的设备(设备模型有关)
const char *nodename;
mode_t mode;
};
2、使用
2.1 填充file_operations
2.2 填充miscdevice
2.3 misc_register(&miscdevice); //注册并生成节点
3、代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
//杂项设备需要的头文件
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#define DEMO_DEBUG
#ifdef DEMO_DEBUG
#define dem_dbg(fmt, arg...) printk(KERN_WARNING fmt, ##arg)
#else
#define dem_dbg(fmt, arg...) printk(KERN_DEBUG fmt, ##arg)
#endif
static int demo_open (struct inode *pnode, struct file *filp)
{
dem_dbg("==>%s major: %d minor: %d\n",
__FUNCTION__, imajor(pnode), iminor(pnode));
return 0;
}
static ssize_t demo_read (struct file *filp, char __user *buf, size_t count, loff_t *offp)
{
unsigned char ary[100] = "read successfully\n";
unsigned long len = min(count, sizeof(ary));
int retval;
printk("==>%s major: %d minor: %d\n",
__FUNCTION__, imajor(filp->f_dentry->d_inode),
iminor(filp->f_dentry->d_inode));
if(copy_to_user(buf, ary, len) != 0){
retval = -EFAULT;
goto cp_err;
}
return len; //成功返回实际传输的字节数
cp_err:
return retval;
}
static int demo_release (struct inode *pnode, struct file *filp)
{
dem_dbg("==>%s major: %d minor: %d\n",
__FUNCTION__, imajor(pnode), iminor(pnode));
return 0;
}
static struct file_operations fops = {
.owner = THIS_MODULE,
.read = demo_read,
.open = demo_open,
.release = demo_release,
};
//1 定义miscdevice结构体
static struct miscdevice misc = {
//动态获取次设备号
.minor = MISC_DYNAMIC_MINOR,
//填充file_operations结构体
.fops = &fops,
//设备名称
.name = "demo0",
};
static int __init demo_init(void)
{
int res;
dem_dbg("==>demo_init\n");
//2 注册杂项设备 将在/dev/目录下自动创建设备文件节点
res = misc_register(&misc);
if(res < 0){
dem_dbg("register misc device failed!\n");
return -EFAULT;
}
return 0;
}
static void __exit demo_exit(void)
{
dem_dbg("==>demo_exit\n");
//3 注销杂项设备
misc_deregister(&misc);
}
module_init(demo_init);
module_exit(demo_exit);
MODULE_LICENSE("Dual BSD/GPL");
Makefile
ifneq ($(KERNELRELEASE),)
obj-m +=misc.o
#此时由内核构造系统调用
else
#定义并记录内核源码路径
KERNELDIR = /home/ms/iTop4412_Kernel_3.0
#记录当前工程目录
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
@rm -rf *.o .t* .m* .*.cmd *.mod.c *.order *.symvers
endif
clean:
rm -rf *.ko *.o .t* .m* .*.cmd *.mod.c *.order *.symvers