本文共 5467 字,大约阅读时间需要 18 分钟。
杂项设备的原理就是注册一个主设备号,将各种杂类设备都归属于该主设备号之下。
杂项设备本质上就是字符设备。
static int __init misc_init(void)
{
#ifdef CONFIG_PROC_FS
//在proc文件系统下创建一个"misc"目录。
#endif//创建一个杂项设备类名为"misc"
//注册一个主设备号为MISC_MAJOR(10)的字符设备,设备操作函数集为misc_fops。
fail_printk:
fail_remove:
}
subsys_initcall(misc_init);//作为子系统添加到内核
//注册字符设备的具体实现如下
int register_chrdev(unsigned int major, const char *name,
{
//注册一个主设备号(major)和在该主设备号下的256个次设备号。
out:
out2:
}
现在我们已经将主设备号为10的字符设备添加到了内核,并注册了该主设备号下的256个次设备号。
那么是如何将这些次设备号分配给各杂项设备并为它们创建设备节点的呢?让我们来看一个看门狗驱动的例子。
每一个杂项设备都对应一个杂项设备结构体:
struct miscdevice
};
在看门狗驱动中申明并初始化了一个杂项设备结构体(在文件linux/drivers/char/watchdog/s3c2410_wdt.c中)
static struct miscdevice s3c2410wdt_miscdev = {
操作函数集
static const struct file_operations s3c2410wdt_fops = {
该看门狗设备不仅作为杂项设备还作为平台设备而存在。
以下是平台设备驱动探测函数:
static int s3c2410wdt_probe(struct platform_device *pdev)
{
//看门狗作为杂项设备被添加到内核并创建设备节点
}
int misc_register(struct miscdevice * misc)
{
//如果杂项设备的设备号被置为MISC_DYNAMIC_MINOR,则表明该设备的设备号要从新自动分配。
//计算设备号主设备号为MISC_MAJOR(10),即是我们先前注册的字符设备的主设备号
}
到此一个杂项设备就被添加到了内核,并为之创建了设备节点。
所有的杂项设备都共用一个主设备号,但各有各的操作函数集,各杂项设备被是如何找到自己的操作函数集的呢?
先前我们注册了一个字符设备,设备名为"misc",主设备号为MISC_MAJOR,操作函数集为misc_fops。
该字符设备管理着主设备号MISC_MAJOR下的所有杂项设备。
操作函数集misc_fops在文件linux/drivers/char/misc.c中申明并初始化。
static const struct file_operations misc_fops = {
//该操作函数集只有一个打开函数,让我们看看在设备打开时做了哪些工作。
//用户空间的文件操作函数直接调用的是主设备号对应的那个设备的操作函数集中的函数。
//所以用户空间打开一个杂项设备时直接调用的打开函数必是此处的misc_open()而不是
//各杂项设备自己的打开函数。
static int misc_open(struct inode * inode, struct file * file)
{
//并重新遍历链表misc_list找出杂项设备结构体并获取它的操作函数集。
fail:
}
//杂项设备文件打开的主要工作就是寻找次设备号对应杂项设备,并获取该杂项设备操作函数集,用新的操作函数集中的
//打开函数实现设备的真正打开。
本文来源于在此表示感谢!
转载地址:http://masci.baihongyu.com/