3.3 应用程序中函数调用的底层执行流程

3.1节分析的probe函数中,它的核心函数video_register_devicepart3中(v4l2-core/v4l2-dev.c文件),通过vdev->cdev->ops= &v4l2_fops;将字符设备的结构体cdevfile_operations函数集指向了v4l2_fops,如下所示:

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, 
};

open函数和ioctl函数为例来分析这个底层的调用过程:

当应用程序调用open函数的时候,就会调用这个v4l2_open函数,如下所示:

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); 
	/* 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) { 
		if (video_is_registered(vdev)) 
			ret = vdev->fops->open(filp); 
		else 
			ret = -ENODEV; 
	} 

	if (vdev->debug) 
		printk(KERN_DEBUG "%s: open (%d)\n", 
			video_device_node_name(vdev), ret); 
	/* decrease the refcount in case of an error */ 
	if (ret) 
		video_put(vdev); 
	return ret; 
}

看这个函数,它经过一系列的判断和操作,最终通过我标红那一句,调用到video_device结构体里面fops函数集的open函数。(以上这些分析是v4l2-dev.c中的)

体现在mxc_v4l2_capture.c中就是:在init_camera_struct函数中,通过*(cam->video_dev)= mxc_v4l_template;这一句话,将video_device指向了mxc_v4l_template,所以应用程序调用open函数,最终就会依次调用mxc_v4l_template->fops->open,即

mxc_v4l_template--->mxc_v4l_fops--->mxc_v4l_open

上面分析的是应用程序如果调用open函数的话,底层函数的执行流程,最终就会执行到我们mxc_v4l2_capture.c中的mxc_v4l_open函数。


同样对于ioctl函数来说,比如应用程序调用了一个ioctl函数,作为一个字符设备,肯定会调用到v4l2_fops结构体中的v4l2_ioctl函数,ret= vdev->fops->ioctl(filp, cmd, arg);

最终在mxc_v4l2_capture.c中会依次调用mxc_v4l_template--->mxc_v4l_fops--->mxc_v4l_ioctl


mxc_v4l_ioctl函数如下所示

static long mxc_v4l_ioctl(struct file *file, unsigned int cmd, 
			 unsigned long arg) 
{ 
	pr_debug("In MVC:mxc_v4l_ioctl\n"); 
	return video_usercopy(file, cmd, arg, mxc_v4l_do_ioctl); 
} 

它通过video_usercopy函数,这个video_usercopy函数会进行一些检查及错误分析,最终会调用到mxc_v4l_do_ioctl函数,在mxc_v4l_do_ioctl函数中会根据不同的宏,通过一个switch语句来分别执行不同的过程。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值