chrdev_open的详细分析

来源:互联网 发布:编程工具 编辑:程序博客网 时间:2024/06/06 03:46

此函数主要完成的工作就是填充并调用用户给出的 struct file->f_op 结构中的函数集。它首先尝试得到正确的字符设备结构,判断如果注册了相应的函数集则调用。

int chrdev_open(struct inode * inode, struct file * filp)
{
 struct cdev *p;
 struct cdev *new = NULL;
 int ret = 0;

 spin_lock(&cdev_lock);
        
        //
        // 得到相应的字符设备结构
        //
 p = inode->i_cdev;
 if (!p) {
  struct kobject *kobj;
  int idx;
  spin_unlock(&cdev_lock);

                //
                // 如果此字符设备结构无效,则从设备对象管理中查找
                //
  kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx);
  if (!kobj)
   return -ENXIO;
  new = container_of(kobj, struct cdev, kobj);
  spin_lock(&cdev_lock);

                //
                // 再次尝试获得正确的字符设备结构
                //
  p = inode->i_cdev;
  if (!p) {
   inode->i_cdev = p = new;
   inode->i_cindex = idx;
   list_add(&inode->i_devices, &p->list);
   new = NULL;
                //
                // 使用 cdev_get() 函数判断相应设备结构的内核设备对象是否
                // 有效
                //
  } else if (!cdev_get(p))
   ret = -ENXIO;

        //
        // 如果有效,则调用 cdev_get() 函数继续判断相应设备结构的内核
        // 设备对象是否有效,如果无效则表明此设备仍不可用。
        //
 } else if (!cdev_get(p))
  ret = -ENXIO;
 spin_unlock(&cdev_lock);
 cdev_put(new);

        //
        // 如果到此字符设备还无效的话,则返回错误。
        //
 if (ret)
  return ret;

        //
        // 注意:这里使用 cdev->file_operations 函数操作集来
        // 填充的 struct file->f_op 这也是我们注册字符设备驱动
        // 时所给出的函数集。
        //
 filp->f_op = fops_get(p->ops);

        //
        // 如果 struct file->f_op 无效,那么它所指向的函数集
        // 肯定也无效,这样的话直接返回错误。注意:这里有一
        // 种可能,那就是调用者虽注册了一个字符设备驱动,但是
        // 并没有提供相应的操作集,或许调用者认为没有必要。
        //
 if (!filp->f_op) {
  cdev_put(p);
  return -ENXIO;
 }

        //
        // 如果 open 函数有效那么则先锁定内核,调用此方法后
        // 再解锁内核
        //
 if (filp->f_op->open) {
  lock_kernel();
  ret = filp->f_op->open(inode,filp);
  unlock_kernel();
 }
 if (ret)
  cdev_put(p);
 return ret;
}

原创粉丝点击