从vivi学习V4L2架构(二):open流程分析

6 篇文章 0 订阅
5 篇文章 0 订阅

 应用open调用流程

使用open函数将/dev/videoX其打开

fd = open("/dev/video0", O_RDWR);

对应会调用到video_device->cdev->ops->open函数也就是v4l2_open函数

static const struct file_operations v4l2_fops = {
	.owner = THIS_MODULE,
	.read = v4l2_read,
	.write = v4l2_write,
	.open = v4l2_open,
	.get_unmapped_area = v4l2_get_unmapped_area,
	.mmap = v4l2_mmap,
	.unlocked_ioctl = v4l2_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl = v4l2_compat_ioctl32,
#endif
	.release = v4l2_release,
	.poll = v4l2_poll,
	.llseek = no_llseek,
};

/* Override for the open function */
static int v4l2_open(struct inode *inode, struct file *filp)
{
	struct video_device *vdev;
	int ret = 0;

	/* Check if the video device is available */
	mutex_lock(&videodev_lock);
	vdev = video_devdata(filp); //返回对应次设备号的video_device video_device[minor]
	/* return ENODEV if the video device has already been removed. */
	if (vdev == NULL || !video_is_registered(vdev)) {
		mutex_unlock(&videodev_lock);
		return -ENODEV;
	}
	/* and increase the device refcount */
	video_get(vdev);
	mutex_unlock(&videodev_lock);
	if (vdev->fops->open) { //这里再vivi.c中赋值了fops= vivi_fops
		if (vdev->lock && mutex_lock_interruptible(vdev->lock)) {
			ret = -ERESTARTSYS;
			goto err;
		}
		if (video_is_registered(vdev))
//这里就回调video_device->fops->open函数,也就是v4l2_fh_open
			ret = vdev->fops->open(filp); 
		else
			ret = -ENODEV;
		if (vdev->lock)
			mutex_unlock(vdev->lock);
	}

err:
	/* decrease the refcount in case of an error */
	if (ret)
		video_put(vdev);
	return ret;
}

那么看一下v4l2_fh_open()函数干了什么

int v4l2_fh_open(struct file *filp)
{
	struct video_device *vdev = video_devdata(filp);
    //定义fh并分配空间
	struct v4l2_fh *fh = kzalloc(sizeof(*fh), GFP_KERNEL);
    
    //将fh赋值给filp->private_data
	filp->private_data = fh;
	if (fh == NULL)
		return -ENOMEM;

    /*    主要就是初始化fh,  1.将fh->vdev指向vdev 
     *    2.设置fh->vdev->flags V4L2_FL_USES_V4L2_FH
     *    3.fh->prio = V4L2_PRIORITY_UNSET;
     */
	v4l2_fh_init(fh, vdev);

	v4l2_fh_add(fh);
	return 0;
}
EXPORT_SYMBOL_GPL(v4l2_fh_open);

void v4l2_fh_add(struct v4l2_fh *fh)
{
	unsigned long flags;

    //在vivi驱动里面设置了,条件成立
	if (test_bit(V4L2_FL_USE_FH_PRIO, &fh->vdev->flags)) 
		v4l2_prio_open(fh->vdev->prio, &fh->prio); 
        //v4l2_prio_open在这里有条件不满足所以v4l2_prio_change(global, local, 
        //V4L2_PRIORITY_DEFAULT);直接返回,否则会做下面几件事
        //将V4L2_PRIORITY_DEFAULT赋值给fh->prio, 
        //增加fh->vdev->prio->prios[new]的计数
        //并将fh->vdev->prio->prios[*local]计数减1

	spin_lock_irqsave(&fh->vdev->fh_lock, flags);
    //将fh加入到video_device->fh_list链表中
	list_add(&fh->list, &fh->vdev->fh_list);
	spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
}
EXPORT_SYMBOL_GPL(v4l2_fh_add);

open调用过程还是简单,大概就如下图

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值