xnu中的vnode和文件描述符,文件操作向量存储在哪里 [英] vnode and file descriptor in xnu, where does the file operation vector is stored

查看:154
本文介绍了xnu中的vnode和文件描述符,文件操作向量存储在哪里的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在xnu中,我们有 vnode_t 实体,该实体全局表示文件。

In xnu we have the vnode_t entity which represent the file globally.

每个进程都可以访问文件(假设它具有正确的权限),方法是设置新的文件描述符并在vg_data下设置vnode

Each process can access the file (assuming it has right permissions) by setting new file descriptor and set the vnode under fg_data

fp->f_fglob->fg_data = vp;

vnode包含所有相关操作的基本操作列表,并根据文件的FS进行设置。即HFS +驱动程序实现此向量并相应地设置其vnode。

the vnode contain a list of basic actions for all relevant operations and is set in according to the file's FS. i.e. HFS+ driver implement such vector and set its vnode accordingly.

int     (**v_op)(void *);       /* vnode operations vector */

这是用于所有可能在其上进行操作的函数指针的向量vnode。

this is a vector for function pointers for all actions that may operate on the vnode.

此外,我们有fileops结构,它是文件描述符(fg_global)的一部分,描述了这些功能的最小子集:

In addition, we have the fileops struct that is part of the file descriptor (fg_global) which describe a minimal subset of these functions:

这是一个典型的定义:

const struct fileops vnops = {
 .fo_type = DTYPE_VNODE,
 .fo_read = vn_read,
 .fo_write = vn_write,
 .fo_ioctl = vn_ioctl,
 .fo_select = vn_select,
 .fo_close = vn_closefile,
 .fo_kqfilter = vn_kqfilt_add,
 .fo_drain = NULL,
};

,然后在此处设置:

fp->f_fglob->fg_ops = &vnops;

我看到当读取本地文件系统(HFS +)下的常规文件时,它通过file_descriptor而不是vnode ...

I saw that when reading regular file under local filesystem (HFS+), it works through the file_descriptor and not the vnode ...

 * frame #0: 0xffffff801313c67c kernel`vn_read(fp=0xffffff801f004d98, uio=0xffffff807240be70, flags=0, ctx=0xffffff807240bf10) at vfs_vnops.c:978 [opt]
frame #1: 0xffffff801339cc1a kernel`dofileread [inlined] fo_read(fp=0xffffff801f004d98, uio=0xffffff807240be70, flags=0, ctx=0xffffff807240bf10) at kern_descrip.c:5832 [opt]
frame #2: 0xffffff801339cbff kernel`dofileread(ctx=0xffffff807240bf10, fp=0xffffff801f004d98, bufp=140222138463456, nbyte=282, offset=<unavailable>, flags=<unavailable>, retval=<unavailable>) at sys_generic.c:365 [opt]
frame #3: 0xffffff801339c983 kernel`read_nocancel(p=0xffffff801a597658, uap=0xffffff801a553cc0, retval=<unavailable>) at sys_generic.c:215 [opt]
frame #4: 0xffffff8013425695 kernel`unix_syscall64(state=<unavailable>) at systemcalls.c:376 [opt]
frame #5: 0xffffff8012e9dd46 kernel`hndl_unix_scall64 + 22

我的问题是为什么需要这种双重性,在哪种情况下该操作通过file_descriptor向量(fg_ops)工作,在哪种情况下该操作通过vnode向量(vp-> v_op)。

My question is why does this duality needed, and in which cases the operation works through the file_descriptor vector (fg_ops) and which cases the operation works through the vnode vector (vp->v_op).

谢谢

推荐答案


[…]在这种情况下,
操作通过file_descriptor向量(fg_ops)工作,在
种情况下,该操作通过vnode向量(vp-> v_op)工作。

[…] in which cases the operation works through the file_descriptor vector (fg_ops) and which cases the operation works through the vnode vector (vp->v_op).

我将首先回答问题的第二部分:如果您进一步跟踪调用堆栈,并查看 vn_read 函数的内部,您会发现它包含以下行:

I'm going to start by answering this second part of the question first: if you trace through your call stack further, and look inside the vn_read function, you'll find that it contains this line:

    error = VNOP_READ(vp, uio, ioflag, ctx);

VNOP_READ 函数(kpi_vfs.c)依次具有:

The VNOP_READ function (kpi_vfs.c) in turn has this:

_err = (*vp->v_op[vnop_read_desc.vdesc_offset])(&a);

因此,您的问题的答案是对于您的典型文件,两者表用于调度操作。

So the answer to your question is that for your typical file, both tables are used for dispatching operations.

用这样的方式,


我的问题是,为什么需要这种双重性[…]

My question is why does this duality needed […]

并非所有进程都可以保存文件描述符的内容都表示在文件系统。例如,不必一定要命名管道。在这种情况下,vnode没有任何意义。因此,在sys_pipe.c中,您将看到一个不同的fileops表:

Not everything to which a process can hold a file descriptor is also represented in the file system. For example, pipes don't necessarily have to be named. A vnode doesn't make any sense in that context. So in sys_pipe.c, you'll see a different fileops table:

static const struct fileops pipeops = {
    .fo_type = DTYPE_PIPE,
    .fo_read = pipe_read,
    .fo_write = pipe_write,
    .fo_ioctl = pipe_ioctl,
    .fo_select = pipe_select,
    .fo_close = pipe_close,
    .fo_kqfilter = pipe_kqfilter,
    .fo_drain = pipe_drain,
};

套接字的类似处理。

文件描述符跟踪文件或对象的进程视图状态,以允许进行类似文件的操作。像文件中的位置之类的东西-不同的进程可以打开相同的文件,而且每个进程都必须具有自己的读/写位置-因此vnode:fileglob是1:1的关系。

File descriptors track the state of a process's view of a file or object that allows file-like operations. Things like position in the file, etc. - different processes can have the same file open, and they must each have their own read/write position - so vnode:fileglob is a 1:many relationship.

同时,使用vnode对象跟踪文件系统中对象以外的对象也没有任何意义。此外,v_op表是文件系统特定的,而vn_read / VNOP_READ包含适用于文件系统中表示的任何文件的代码。

Meanwhile, using vnode objects to track things other than objects within a file system doesn't make any sense either. Additionally, the v_op table is file system specific, whereas vn_read/VNOP_READ contain code that applies to any file that's represented in a file system.

因此,总的来说,它们实际上是I / O堆栈中的不同层。

So in summary they're really just different layers in the I/O stack.

这篇关于xnu中的vnode和文件描述符,文件操作向量存储在哪里的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆