打印
[嵌入式linux]

知其然知其所以然:源码分析misc设备

[复制链接]
1834|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
yyplc|  楼主 | 2012-4-23 15:08 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 yyplc 于 2012-4-23 21:17 编辑

前面分析了字符设备,接下来分析misc混杂设备。如果不对请扔砖头
混杂设备是字符设备的一种,算是字符设备的一种附加品吧。
混杂驱动程序是那些简单的字符驱动程序,它们拥有一些相同的特性。内核将这些性抽象至一个API中,这个API能简化驱动程序初始化的方式。所有的混杂设备的主设备号为10,每个设备可选择一个单独的次设备号。
混杂设备定义以下参数:
#define DYNAMIC_MINORS 64 /* like dynamic majors */
static unsigned char misc_minors[DYNAMIC_MINORS / 8];
说明可以动态分配64个次设备号(0~63)对应8组misc_minors[]。每组的位对应表示64个次设备号.
misc_minors[7]对应63,62,61,60,59,58,57,56 并且用misc_minors[7]的8位来标记:1表示已分配,0表是未分配
misc_minors[6]对应55,54,53,52,51,50,49,48 并且用misc_minors[6]的8位来标记:1表示已分配,0表是未分配
...
misc_minors[0]对应 7, 6, 5, 4, 3, 2, 1, 0 并且用misc_minors[0]的8位来标记:1表示已分配,0表示未分配
//内核初始化时,通过调用subsys_init()调用misc_init()形成misc子系统
static int __init misc_init(void)
{

int err;



#ifdef CONFIG_PROC_FS

proc_create("misc", 0, NULL, &misc_proc_fops);

#endif

misc_class = class_create(THIS_MODULE, "misc");  //在/sys/class下生成misc目录

err = PTR_ERR(misc_class);

if (IS_ERR(misc_class))

goto fail_remove;



err = -EIO;

if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) //根据主设备号10,注册字符设备

goto fail_printk;

return 0;


fail_printk:

printk("unable to get major %d for misc devices\n", MISC_MAJOR);

class_destroy(misc_class);
fail_remove:

remove_proc_entry("misc", NULL);

return err;
}
subsys_initcall(misc_init);   //系统在do_basic_setup()-->do_initcalls调用

分析一下miscdevice结构
struct miscdevice  {

int minor;

const char *name; //设备名

const struct file_operations *fops; //操作函数

struct list_head list;   //链表

struct device *parent;   //指向父设备

struct device *this_device;  //指向设备本身
};
//misc设备的注册API
int misc_register(struct miscdevice * misc)
{

struct miscdevice *c;

dev_t dev;

int err = 0;



INIT_LIST_HEAD(&misc->list);



mutex_lock(&misc_mtx);

list_for_each_entry(c, &misc_list, list) { //遍历misc设备list

if (c->minor == misc->minor) { //如果minor已被分配,则退出

mutex_unlock(&misc_mtx);

return -EBUSY;

}
}



if (misc->minor == MISC_DYNAMIC_MINOR) { //如果是动态分配minor则找出minor为相应位为0的次设备号

int i = DYNAMIC_MINORS;   

while (--i >= 0)

if ( (misc_minors[i>>3] & (1 << (i&7))) == 0)

break;

if (i<0) {

mutex_unlock(&misc_mtx);

return -EBUSY;

}

misc->minor = i;

}



if (misc->minor < DYNAMIC_MINORS)

misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7);  //相应位置位

dev = MKDEV(MISC_MAJOR, misc->minor);  //获取设备号(32位)



misc->this_device = device_create(misc_class, misc->parent, dev, NULL,

"%s", misc->name);  //在/dev下生成设备节点

if (IS_ERR(misc->this_device)) {

err = PTR_ERR(misc->this_device);

goto out;

}


/*
* Add it to the front, so that later devices can "override"
* earlier defaults
*/

list_add(&misc->list, &misc_list); //将当前设备添加到misc_list设备链表表头之后
out:

mutex_unlock(&misc_mtx);

return err;
}
//misc设备的注销API
int misc_deregister(struct miscdevice *misc)
{

int i = misc->minor;



if (list_empty(&misc->list))

return -EINVAL;



mutex_lock(&misc_mtx);

list_del(&misc->list);

device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));

if (i < DYNAMIC_MINORS && i>0) {

misc_minors[i>>3] &= ~(1 << (misc->minor & 7)); //相应位复位

}

mutex_unlock(&misc_mtx);

return 0;}

编写misc设备驱动很简单,主要调用misc 的API:
misc_regiseter(&);
misc_deregister(&);

相关下载

相关帖子

沙发
青山电子| | 2012-5-11 20:07 | 只看该作者
不错的资料

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

15

主题

262

帖子

1

粉丝