Skip to content

模型Model

文件描述符与共享打开状态

File descriptor and open file description · OFD · dup fork shared offset

区分进程fd表、打开文件描述与inode,逐次计算dup/fork后的共享offset和引用关闭,并处理短读写。

形式陈述 ​

在POSIX式接口中,文件描述符fd是进程表中的小整数索引。表项指向打开文件描述(open file description,OFD);OFD保存当前文件offset与文件状态标志,并引用一个文件对象。因此至少要分三层:进程:fd -> OFD -> inode。

一次新的open一般建立新的OFD,即使打开同一个inode;dup复制fd表项,仍指向原OFD。成功fork使父子分别拥有描述符表,但继承的对应描述符仍共享原OFD。普通read/write按OFD的当前位置访问,并按实际完成字节数推进offset;pread/pwrite类显式偏移接口另有规则。

OS-16采用顺序执行的普通文件I/O,无append、无并发截断、无信号中断。refs[O]仅计当前fd表项对OFD的引用。close移除一个fd项并减refs;降为0才释放OFD及其inode引用。inode是否随后可回收,还取决于名称链接和其他持有者。

直觉

fd像某个进程自己的编号卡,OFD像共同使用的读写游标,inode像被访问的文件对象。两张卡可以共享一个游标;两个独立游标又可以在同一个文件里工作。把这三层画成一条“fd直接指向字节数组”的箭头,会遗漏fork后最容易出现的offset共享。

进程地址空间私有与文件位置共享并不矛盾。fork给子进程复制的是fd表中的引用,而非为每个引用创建新的打开状态。

例子与边界

一条完整offset轨迹 ​

inode42初始内容abcdefgh。P执行open得到fd3→O7,O7.offset=0、refs=1;dup(3)得到fd4→O7、refs=2。fork C后,P与C各有fd3、fd4,全指O7,refs=4。

操作 返回/内容 O7.offset O7.refs
C从fd3读2B ab 2 4
P向fd4写XY,返回2 文件变abXYefgh 4 4
P关闭fd3 P仅剩fd4指O7 4 3
C关闭fd4 C仅剩fd3指O7 4 2
C关闭fd3 P仍持有fd4 4 1
P关闭fd4 O7释放 不再存在 0

在上述关闭动作之前,C另一次open同一文件得到fd5→O8,O8.offset=0。C从fd5读3B得到abX,O8.offset变3,O7仍为4。两个OFD共享inode内容却不共享offset;共享offset与共享文件数据是独立关系。

fd、OFD与inode三层对象

返回值决定这次到底做了多少 ​

请求写6B而返回2,意味着只有前2B已由这次调用接受,普通位置推进2。应用若需全部写完,应推进缓冲指针与剩余长度,再重试未写部分;从头重发6B会重复前缀。POSIX的实际错误与中断条件更复杂,不能把OS-16“不受中断”的例子推广成每次write必定全长。

对请求长度大于0的普通文件read,返回0表示此次读取在文件末尾没有数据;管道与终端有自己的语义,不能从本页顺序文件模型推出它们的所有阻塞、消息或EOF规则。

推论与应用

顺序轨迹的不变量是:每次使用一个仍有效fd时解析到唯一OFD;OFD.refs等于当前表项引用数;offset按实际成功字节数更新。通过open增加新对象、dup/fork增加引用、close删除引用,逐步保持对象生命周期正确。

数值fd可被重用。线程A关闭3后,线程B可能马上open得到新的3;A若误以为“再次close(3)只是保险”就会关闭B的新文件。Linux的close错误处理中是否已释放fd、EINTR如何处理有平台特定规则,不应无条件重复close。本文没有给出跨平台重试配方。

共享OFD并发read/write的原子范围应查目标接口与文件类型,本表只在明示顺序下计算。即使offset更新原子,也不表示多次调用合起来成为事务,更不表示一次write返回已持久保存。

参考资料
  • The Open Group,POSIX.1-2024,fork、write,继承打开描述与实际返回字节数。
  • Linux man-pages 6.19,open(2)、dup(2)、close(2),2026-10-08核查。
关系图谱7 个相邻概念 · 2 类关系

拖动节点调整位置。

显示关系

显示:依赖

  1. 前置三跳
  2. 前置二跳
  3. 前置一跳
  4. 当前条目
  5. 后续一跳
  6. 后续二跳
  7. 后续三跳
文字版关系按与当前条目的最短距离分组
类型化关系