什么是打开文件描述?

什么是打开文件描述?

当您派生一个进程时,子进程将继承其父进程的文件描述符。据我所知,当发生这种情况时,子进程会收到父进程文件描述符表的副本,每个文件描述符表中的指针都指向相同的打开文件描述。这与文件表相同吗,如http://en.wikipedia.org/wiki/File_descriptor, 或者是其他东西?

答案1

    文件描述符→打开文件描述→目录项
               dup                open                    cp

从进程中打开的文件一直到文件内容时,存在多个间接级别。在实现方面,这些级别通常转换为内核中指向下一个级别的数据结构。我将描述一个简单的实现;真正的实现可能会更加复杂。

进程中打开的文件由文件描述符指定,文件描述符是一个小的非负整数。数字 0、1 和 2 具有常规含义:进程应该从 0(标准输入)读取正常输入,将正常输出写入 1(标准输出),并将错误消息写入 2(标准错误)。这只是一个约定:内核并不关心。内核为每个进程保留一个打开文件描述符表,将这些小整数映射到文件描述符结构。在Linux内核中,这个结构体是struct fd

文件描述符结构包含一个指向打开文件描述。可以有多个文件描述符指向来自多个进程的同一个打开文件描述,例如当一个进程调用dup和朋友,或者在进程分叉之后。如果文件描述符(即使在不同的进程中)是由相同的原始open(或类似)系统调用引起的,则它们共享相同的打开文件描述。打开文件描述包含有关文件打开方式的信息,包括模式(只读 vs 读写、追加等)、在文件中的位置等。在 Linux 下,打开文件描述结构为struct file

打开的文件描述位于文件 API 级别。下一个级别是在文件系统API。区别在于文件 API 涵盖了不存在于文件系统树中的文件,例如匿名管道和套接字。如果该文件是目录树中的文件,则打开的文件描述包含指向目录项。如果同一文件被open编辑多次,则可能有多个打开的文件描述指向同一目录条目。目录项包含有关文件内容的信息,包括指向其父目录的指针以及有关文件所在位置的信息。在 Linux 内核中,目录项分为两级:struct inode其中包含文件元数据和struct dentry它跟踪文件在目录树中的位置。

答案2

我在中找到了答案开放系统调用的文档:

POSIX 使用术语“打开文件描述”来指代系统范围的打开文件表中的条目。在其他上下文中,该对象也被称为“打开文件对象”、“文件句柄”、“打开文件表条目”,或者用内核开发人员的说法,称为结构文件。当文件描述符被复制时(使用 dup(2) 或类似方法),副本引用与原始文件描述符相同的打开文件描述,因此两个文件描述符共享文件偏移量和文件状态标志。这种共享也可以发生在进程之间:通过 fork(2) 创建的子进程继承其父进程的文件描述符的副本,并且这些副本引用相同的打开文件描述。文件的每次 open(2) 都会创建一个新的打开文件描述;因此,一个文件inode可能对应多个打开的文件描述。

答案3

我将这个问题解释为主要与术语有关,特别是“文件表”。

如果您查看早期的实现,就会发现系统中所有打开的文件描述的集合是一个数组。当进程需要新的打开文件描述时,会扫描数组以查找未使用的槽,并返回指向该槽的指针。例如,参见falloc底部的http://minnie.tuhs.org/cgi-bin/utree.pl?file=V7/usr/sys/sys/fio.c

在该系统中,“文件表”是系统范围内的struct file.

如今,打开的文件描述是通过更灵活的机制动态分配的,而不仅仅是在固定大小的数组中选择未使用的槽。系统中所有打开的文件描述的集合不需要排列在连续的类似数组的设置中。因此,实际上不再有“文件表”,除非您将每个动态内存分配池视为一个“表”。

维基百科图中的“文件表”是一组打开的文件描述。文件描述符是打开文件描述的指针数组的索引。由于打开的文件描述始终通过这些指针访问,而不是通过某个数组中的数字索引访问,因此将它们绘制为连续的框列有点误导。将其称为“桌子”强化了这种误导性的形象。

但这是一种相当常见的用法,所以我预计它不会很快消失。

答案4

试图理解你的要求,因为它不清楚。但如果我理解正确的话,您会问多个进程如何写入同一个文件?在 Linux 中,默认情况下,文件不会被进程锁定,并且多个进程始终可以写入同一个文件。这当然有破坏文件格式的风险。写入往往一次是一个缓冲区(在大多数情况下,这意味着一整行文本,如果文件是公共日志并且多个进程正在写入它,那么这种方法可以正常工作),尽管可以使用无缓冲的文件,但是打开文件时需要选择额外的非默认选项。

使用随机 IO 打开的文件确实可能会因为被多个进程打开而变得混乱,并且这种 IO 类型可能需要文件锁定才能安全使用。

另一个相关问题是,文件是否由正在运行的进程保持打开状态,即使该进程不经常或根本不写入该文件。即使“删除”,该文件仍将继续占用磁盘空间。只有当进程通过关闭文件释放其文件句柄后,其使用的磁盘空间才会被恢复。

另一个了解有关打开文件的更多信息的地方是 /proc 目录,特别是 /proc/PID/fd 这是查看给定 PID 进程打开了哪些文件的方法。

相关内容