我希望在初始化摄像机后从内核模块访问/ dev / video0。 为此,我想在ueventd守护程序启动之前创建/ dev / video0节点。
答案 0 :(得分:0)
更深入地了解/ dev / video0节点的内核处理 应用程序尝试打开此文件,它获取一个FILE * fp指针, linux内核虚拟文件系统检查这是否是常规文件或 设备文件,如果是设备文件,则检查它的主要编号 注册它的驱动程序并将次要编号保存在i_rdev字段中 struct inode * inode,它再次嵌入在struct file * fp和 传递给那个司机。
因此,对于应用程序打开的每个FILE * fp,都有struct file * fp in 注册驱动程序,即我们案例中的v4l2驱动程序。传递此文件指针 到内核ioctl API v4l2_ioctl。
现在内部v4l2驱动程序维护一个指向所有指针的数组 注册视频设备 如下所示: static struct video_device * video_device [VIDEO_NUM_DEVICES];
现在,如果我们看到主要的ioctl调用的实现。
static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct video_device *vdev = video_devdata(filp);
...
}
该视频设备结构是从文件指针中提取的,文件指针是我们可以控制视频设备的关键,即我们的相机来自内核,因为它包含指向所有已注册的v4l2 ioctl的函数指针。所以我们的目标是从内核中访问视频设备结构。
现在再次查看内核在收到应用程序请求时如何访问视频设备。
struct video_device *video_devdata(struct file *file)
{
return video_device[iminor(file->f_path.dentry->d_inode)];
}
EXPORT_SYMBOL(video_devdata);
static inline unsigned iminor(const struct inode *inode)
{
return MINOR(inode->i_rdev);
}
如上所示,它使用i_rdev字段获取从struct file * fp传递给VFS的次要编号。
总结一下,如果我们想从内核中访问ioctl,我们需要填写 一个虚拟文件* fp指针,包含次要编号 file-> f_path.dentry-> d_inode.i_rdev字段,v4l2子系统将获得 video_device结构使用此字段并将能够进一步驱动 通过使用video_device-> ioctl_ops从video_device结构进行ioctl操作 字段如下所示。
struct video_device
{
#if defined(CONFIG_MEDIA_CONTROLLER)
struct media_entity entity;
#endif
/* device ops */
const struct v4l2_file_operations *fops;
const struct v4l2_ioctl_ops *ioctl_ops;
...
}
要设置file-> f_path.dentry-> d_inode.i_rdev,我们需要在文件结构中添加对inode和dentry结构的引用,如下面的伪代码:
static int enumerate_camera()
{
inode.i_rdev = cam_minor_number ;// Saved when camera device registered;
dentry.d_inode = inode;
file.f_path.dentry = dentry;
file.f_dentry->d_inode = inode;
....
}