Linux misc设备(一)misc驱动框架

Linux misc设备驱动

Linux misc设备(一)misc驱动框架

Linux misc设备(二)蜂鸣器驱动

Linux misc设备(一)misc驱动框架

一、misc简介

Linux的驱动设计是趋向于分层的,大多数设备都有自己归属的类型,例如按键、触摸屏属于输入设备,Linux有一个input子系统框架。但是对于adc、蜂鸣器等设备,无法明确其属于什么类型,对于这种设备一般推荐使用misc驱动框架编写驱动程序

misc设备也是一个字符设备,在misc的初始化函数中注册了一个字符设备,主设备号为MISC_MAJOR (10)

这个字符设备并不是具体的misc设备实例的实现,只是misc核心层用来将应用层的操作转发到具体的misc实例中

在编写misc设备驱动实例时,通过misc_register()向misc核心层注册一个字符设备,在此函数中完成了生成设备节点、动态获取次设备号的动作

二、misc驱动框架

misc设备实例表明一个具体的驱动程序(例如adc、蜂鸣器),每一个misc设备实例都有对应得次设备号和相应驱动程序实现的文件操作集

misc设备实例驱动通过misc_register向misc核心层注册misc设备,所有的misc的主设备号都是(MISC_MAJOR),misc核心为注册的misc设备维护一个双向链表,如下图所示

在这里插入图片描述

当应用层通过open打开设备节点时,内核会为打开的设备文件创建一个struct file对象

然后调用到misc核心层的cdev的open函数,在cdev的open函数中,从misc维护的misc设备链表中,根据次设备号找到对应的misc设备实例,将struct file对象中的文件操作集合更改为misc设备实例的文件操作集合,然后调用misc设备实例的open函数,如下图所示

在这里插入图片描述

之后应用层通过read、ioctl等来操作设备文件,都会调用对应的struct file对象中的文件操作集合,进而操作具体的misc实例,如下图所示

在这里插入图片描述

以上就是misc设备的驱动框架

三、misc源码剖析

在内核文件drivers\char\misc.c中时misc驱动核心的实现,下面详细剖析这个源码

首先看驱动的入口

static struct class *misc_class;
static const struct file_operations misc_fops = {
	.owner		= THIS_MODULE,
	.open		= misc_open,
};


static int __init misc_init(void)
{
    /* 创建misc类 */
    misc_class = class_create(THIS_MODULE, "misc"); 
    
    /* 注册字符设备 */
    register_chrdev(MISC_MAJOR,"misc",&misc_fops); //MISC_MAJOR主设备号(10)
}

首先创建misc类,这将给misc设备实例生成设备节点时使用

然后注册字符设备,可以看到misc_fops中只实现了open函数,此函数是用于转发系统调用到具体的misc设备实例中,是misc驱动框架的核心

再来看注册函数misc_register

int misc_register(struct miscdevice * misc)
{
    /* 找到空闲的次设备号 */
    int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS);

    /* 设备号 */
	dev = MKDEV(MISC_MAJOR, misc->minor);

    /* 生成设备节点 */
	misc->this_device = device_create(misc_class, misc->parent, dev,
					  misc, "%s", misc->name);
    
	list_add(&misc->list, &misc_list); //将设备添加到链表中
}

可以看到注册函数会分配一个次设备号,然后生成设备节点,再将misc设备添加到链表中

接下来分析misc_open

static int misc_open(struct inode * inode, struct file * file)
{
    /* 遍历misc设备链表,根据次设备号找到对应misc设备实例的fops */
	list_for_each_entry(c, &misc_list, list) {
		if (c->minor == minor) {
			new_fops = fops_get(c->fops);		
			break;
		}
	}
    
    /* 将file对象的fops设置为misc实例的fops */
    file->f_op = new_fops;
}

从上面代码中可以看到,首先从misc设备链表中找到misc设备实例,然后将file对应得fops设置为misc设备实例对应的fops,其中file是内核为每个打开文件创建的一个对象

之后应用层再进行系统调用,都会调用到misc设备实例

四、misc设备实例驱动编写模板

如何基于misc写一个设备驱动非常简单,下面给出一个模板

static int buzzer_open(struct inode *inode, struct file *file)
{
    return 0;
}


static int buzzer_close(struct inode *inode, struct file *file)
{
	return 0;
}

static int buzzer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
    return 0;
}


static struct file_operations buzzer_fops = {
    .owner   =   THIS_MODULE,
    .open    =   buzzer_open,
    .release =   buzzer_close, 
    .ioctl   =   buzzer_ioctl,
};

static struct miscdevice buzzer_dev = {
	.minor  = MISC_DYNAMIC_MINOR, //动态分配次设备号
	.name   = "buzzer",
	.fops   = &buzzer_fops, //文件操作集
};

static int __init buzzer_init(void)
{
    /* 注册杂项设备 */
	misc_register(&buzzer_dev);

	return 0;
}

static void __exit buzzer_exit(void)
{
    /* 注销杂项设备 */
	misc_deregister(&buzzer_dev);
}

module_init(buzzer_init);
module_exit(buzzer_exit);
MODULE_LICENSE("GPL");
  • 10
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux 中的 misc 是一种杂项设备类型,它可以用来创建一些没有特定驱动程序的设备文件,例如 /dev/null 和 /dev/random。 要创建一个 misc 设备,可以使用 misc_register() 函数,该函数需要一个 miscdevice 结构体作为参数,其中包含设备的名称、设备号等信息。然后,可以使用 misc_deregister() 函数来注销设备。 下面是一个简单的示例程序,用于创建一个名为 mymiscmisc 设备: ```c #include <linux/module.h> #include <linux/miscdevice.h> static int mymisc_open(struct inode *inode, struct file *file) { printk(KERN_INFO "mymisc: device opened\n"); return 0; } static int mymisc_release(struct inode *inode, struct file *file) { printk(KERN_INFO "mymisc: device closed\n"); return 0; } static const struct file_operations mymisc_fops = { .owner = THIS_MODULE, .open = mymisc_open, .release = mymisc_release, }; static struct miscdevice mymisc_device = { .minor = MISC_DYNAMIC_MINOR, .name = "mymisc", .fops = &mymisc_fops, }; static int __init mymisc_init(void) { int ret; ret = misc_register(&mymisc_device); if (ret) { printk(KERN_ERR "mymisc: unable to register device\n"); return ret; } printk(KERN_INFO "mymisc: device registered\n"); return 0; } static void __exit mymisc_exit(void) { misc_deregister(&mymisc_device); printk(KERN_INFO "mymisc: device unregistered\n"); } module_init(mymisc_init); module_exit(mymisc_exit); MODULE_LICENSE("GPL"); ``` 编译并安装模块后,可以使用以下命令来查看设备文件: ``` $ ls -l /dev/mymisc crw------- 1 root root 10, 58 May 22 15:08 /dev/mymisc ``` 可以使用 cat 命令来测试设备: ``` $ cat /dev/mymisc mymisc: device opened mymisc: device closed ``` 这里的输出是由 mymisc_open() 和 mymisc_release() 函数生成的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值