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

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

[cpp]  view plain  copy
  1. static const struct file_operations v4l2_fops = {   
  2.     .owner = THIS_MODULE,   
  3.     .read = v4l2_read,   
  4.     .write = v4l2_write,   
  5.     .open = v4l2_open,   
  6.     .get_unmapped_area = v4l2_get_unmapped_area,   
  7.     .mmap = v4l2_mmap,   
  8.     .unlocked_ioctl = v4l2_ioctl,   
  9. #ifdef CONFIG_COMPAT   
  10.     .compat_ioctl = v4l2_compat_ioctl32,   
  11. #endif   
  12.     .release = v4l2_release,   
  13.     .poll = v4l2_poll,   
  14.     .llseek = no_llseek,   
  15. };  

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

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

[cpp]  view plain  copy
  1. static int v4l2_open(struct inode *inode, struct file *filp)   
  2. {   
  3.     struct video_device *vdev;   
  4.     int ret = 0;   
  5.   
  6.     /* Check if the video device is available */   
  7.     mutex_lock(&videodev_lock);   
  8.     vdev = video_devdata(filp);   
  9.     /* return ENODEV if the video device has already been removed. */   
  10.     if (vdev == NULL || !video_is_registered(vdev)) {   
  11.         mutex_unlock(&videodev_lock);   
  12.         return -ENODEV;   
  13.     }   
  14.     /* and increase the device refcount */   
  15.     video_get(vdev);   
  16.     mutex_unlock(&videodev_lock);   
  17.     if (vdev->fops->open) {   
  18.         if (video_is_registered(vdev))   
  19.             ret = vdev->fops->open(filp);   
  20.         else   
  21.             ret = -ENODEV;   
  22.     }   
  23.   
  24.     if (vdev->debug)   
  25.         printk(KERN_DEBUG "%s: open (%d)\n",   
  26.             video_device_node_name(vdev), ret);   
  27.     /* decrease the refcount in case of an error */   
  28.     if (ret)   
  29.         video_put(vdev);   
  30.     return ret;   
  31. }  

看这个函数,它经过一系列的判断和操作,最终通过我标红那一句,调用到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

扫描二维码关注公众号,回复: 2420703 查看本文章


mxc_v4l_ioctl函数如下所示

[cpp]  view plain  copy
  1. static long mxc_v4l_ioctl(struct file *file, unsigned int cmd,   
  2.              unsigned long arg)   
  3. {   
  4.     pr_debug("In MVC:mxc_v4l_ioctl\n");   
  5.     return video_usercopy(file, cmd, arg, mxc_v4l_do_ioctl);   
  6. }   

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


猜你喜欢

转载自blog.csdn.net/dragon101788/article/details/80660840
3.3