进程打开文件的本质以及文件描述符的本质

本文深入解析了进程打开文件的内部机制,揭示了文件描述符的本质及其在操作系统内存中的数据结构关联。通过详细阐述文件描述符表、文件表和i节点表的作用,帮助读者理解操作系统如何实现对文件的读写操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

进程打开文件的本质

当我们打开文件时,操作系统在内存中要创建相应的数据结构来描述目标文件。于是就有了file结构体。表⽰⼀个已经打开的文件对象。而进程执行open系统调⽤,所以必须让进程和文件关联起来。每个进程都有⼀个指针*files, 指向⼀张表files_struct,该表最重要的部分就是包涵一个指针数组,每个元素都是一个指向打开文件的指针!所以,本质上,文件描述符就是该数组的下标。所以,只要拿着文件描述符,就可以找到对应的文件。

文件描述符的本质

本质是数组元素的下标,每个进程都对应一张文件描述符表,该表可视为指针数组,给数组的元素指向文件表的一个元素,数组元素的下标就是大名鼎鼎的文件描述符
这里写图片描述
图详解:

1.右侧的表称为i节点表,在整个系统中只有1张。该表可以视为结构体数组,该数组的一个元素对应于一个物理文件。
2.中间的表称为文件表,在整个系统中只有1张。该表可以视为结构体数组,一个结构体中有很多字段,其中有3个字段比较重要:


file status flags
用于记录文件被打开来读的,还是写的。其实记录的就是open调用中用户指定的第2个参数
current file offset
用于记录文件的当前读写位置(指针)。正是由于此字段的存在,使得一个文件被打开并读取后,
下一次读取将从上一次读取的字符后开始读取
v-node ptr
该字段是指针,指向右侧表的一个元素,从而关联了物理文件。

3.左侧的表称为文件描述符表,每个进程有且仅有1张。该表可以视为指针数组,数组的元素指向文件表的一个元素。最重要的是:数组元素的下标就是大名鼎鼎的文件描述符。
4.open系统调用执行的操作:新建一个i节点表元素,让其对应打开的物理文件(如果对应于该物理文件的i节点元素已经建立,就不做任何操作);新建一个文件表的元素,根据open的第2个参数设置file status flags字段,将current file offset字段置0,将v-node ptr指向刚建立的i节点表元素;在文件描述符表中,寻找1个尚未使用的元素,在该元素中填入一个指针值,让其指向刚建立的文件表元素。最重要的是:将该元素的下标作为open的返回值返回。
5.这样一来,当调用read(write)时,根据传入的文件描述符,OS就可以找到对应的文件描述符表元素,进而找到文件表的元素,进而找到i节点表元素,从而完成对物理文件的读写。

<think>嗯,用户问的是文件描述符到底关联进程级别的打开文件表还是系统级别的打开文件表。这个问题涉及到操作系统的核心机制,需要仔细梳理。 从用户提供的引用材料来看,关键信息在引用[2]里说得很清楚:每个进程都有一个指针*files指向files_struct表,而文件描述符就是这个表里指针数组的下标。这说明文件描述符首先是进程级别的标识符。不过用户可能没意识到,这个进程级数组里存放的指针,其实指向的是系统级的打开文件表(file结构体)。 引用[3]补充了重要细节:系统级打开文件表(file结构体)再指向更底层的inode表。这样三层结构(进程描述符→系统file表→inode表)既能隔离进程空间,又能共享文件资源。比如两个进程打开同一个文件时,它们各自的文件描述符指向不同的file结构体,但这两个file结构体可能指向同一个inode。 用户似乎对"关联"的具体层级有疑惑。应该强调文件描述符本身是进程私有编号,但它通过系统级file表间接关联到文件实体。这个设计很巧妙——进程通过小整数操作文件,内核负责整数到实际资源的映射。多进程同时读写同一文件时的协调问题,也是通过这三层结构解决的。 考虑到用户正在学习Linux文件系统,或许可以补充个例子:当进程调用dup()复制描述符时,新老描述符在进程表里不同下标,但指向同一个系统级file结构体。这样就能解释为什么关闭副本不影响原描述符的操作位置。</think>文件描述符**直接关联进程级别的打开文件表**,但该表最终会**间接指向系统级别的打开文件表**。以下是详细说明: --- ### 1. **文件描述符本质进程级)** - 每个进程拥有独立的**文件描述符表(File Descriptor Table)**,它是进程私有数据结构的一部分[^1][^2]。 - 文件描述符(如 `0`、`1`、`2`)本质上是**该表的下标索引**(整数),通过下标可定位到进程打开文件信息[^2]。 > 例如:`fd = open("file.txt")` 返回的 `3` 是当前进程描述符表中的索引值。 --- ### 2. **进程表与系统表的关联(系统级)** - 进程文件描述符表中的每个条目,实际存储的是**指向系统级打开文件表(Open File Table)的指针**[^3]。 - 系统级打开文件表(内核维护)包含 `struct file` 结构体,记录文件的**读写偏移量、访问模式、状态等动态信息**[^3]。 > 示意图: > ``` > 进程A文件描述符表 > [0] → 指向系统表条目X > [1] → 指向系统表条目Y > > 系统级打开文件表 > 条目X → 文件1的读写位置、状态 > 条目Y → 文件2的读写位置、状态 > ``` --- ### 3. **关键区别与联系** | **层级** | **作用** | **关联关系** | |----------------|--------------------------------------------------------------------------|----------------------------------| | **进程描述符表** | 管理进程独有文件访问入口(`fd` 是索引) | 条目指向系统级 `file` 结构体[^2] | | **系统文件表** | 管理所有进程共享的文件动态信息(如读写偏移) | 条目指向文件系统 `inode`[^3] | | **inode 表** | 存储文件元数据(权限、大小、磁盘位置等),与具体进程无关[^3] | 被多个 `file` 结构体共享 | --- ### 4. **示例场景** 1. **进程独享文件** 进程A打开文件F,生成 `fd=3` → 系统表新建条目X → 指向F的inode。 若进程B也打开F,会生成独立的 `fd` 和系统表条目Y(但条目X、Y共享同一inode)。 2. **描述符复制(`dup()`)** `dup(3)` 复制描述符时,新描述符(如 `4`)与 `3` 指向**同一个系统表条目**,共享读写偏移[^3]。 --- ### 总结 - **直接关联**:文件描述符进程级表的索引。 - **间接关联**:通过进程表条目访问系统级文件表,最终定位到文件数据(inode)。 - **设计目的**: ✅ 进程隔离(各进程独立管理描述符) ✅ 资源共享(多进程通过不同描述符操作同一文件) ✅ 效率优化(系统表维护文件状态,避免冗余操作)[^1][^3] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_长风_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值