Linux中字符设备的注册过程是比较简单的。我们通常可以调用misc_register()函数来注册一个字符设备。Misc设备是一种字符设备,通过该设备可以将fops请求转发给注册的misc设备,从而实现字符设备的功能。用户调用该接口注册Misc字符设备时,可以动态分配设备Minor号,当获取Minor号之后调用class_simple_device_add()或者device_create()函数完成字符设备的创建。Misc字符设备注册函数如下所示:
int misc_register(struct miscdevice * misc) { struct miscdevice *c; dev_t dev; int err = 0; INIT_LIST_HEAD(&misc->list); mutex_lock(&misc_mtx); //获取misc设备信号量 list_for_each_entry(c, &misc_list, list) { //检查设备是否已经存在 if (c->minor == misc->minor) { mutex_unlock(&misc_mtx); return -EBUSY; //如果设备存在,直接返回 } } if (misc->minor == MISC_DYNAMIC_MINOR) { //动态分配分配minor号 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); misc->this_device = device_create(misc_class, misc->parent, dev, "%s", misc->name); //创建字符设备(Misc设备) 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设备链中,设备访问时需要操作该链表 out: mutex_unlock(&misc_mtx); return err; }
需要注意的是2.6.12内核中创建系统设备时需要调用simple_device的接口class_simple_device_add()。在2.6.23中需要调用device_create()函数完成设备注册。在3.2内核中,simple_device的接口已经不存在了,所以必须调用device_create函数,另外,3.2内核不支持具有相同minor号的字符设备,在2.6.x内核中是支持的。
系统是如何完成fops函数调用的呢?回答这个问题需要分析Misc设备打开过程。在打开Misc设备驱动的时候,Misc设备驱动会根据访问设备的Minor号重定向fops函数集,该程序说明如下:
static int misc_open(struct inode * inode, struct file * file) { int minor = iminor(inode); struct miscdevice *c; int err = -ENODEV; const struct file_operations *old_fops, *new_fops = NULL; mutex_lock(&misc_mtx); list_for_each_entry(c, &misc_list, list) { //通过minor号来匹配对应的fops函数集 if (c->minor == minor) { new_fops = fops_get(c->fops); break; } } if (!new_fops) { mutex_unlock(&misc_mtx); request_module("char-major-%d-%d", MISC_MAJOR, minor); mutex_lock(&misc_mtx); list_for_each_entry(c, &misc_list, list) { if (c->minor == minor) { new_fops = fops_get(c->fops); break; } } if (!new_fops) goto fail; } err = 0; old_fops = file->f_op; file->f_op = new_fops; //重定向fops函数 if (file->f_op->open) { //打开设备 err=file->f_op->open(inode,file); if (err) { fops_put(file->f_op); file->f_op = fops_get(old_fops); } } fops_put(old_fops); fail: mutex_unlock(&misc_mtx); return err; }
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索file
, 函数
, is_err
, i2c设备驱动字符设备
, 字符
, 注册
, xenbus设备注册
, 字符设备
, minor
, 设备
, 字符设备驱动
major.minor
linux 注册字符设备、linux字符设备驱动、linux 字符设备、linux 字符设备文件、linux 字符设备读写,以便于您获取更多的相关知识。