从零写OS(二十一):文件描述符 fd

前几章的用户程序如果想读文件,得直接传 inode 号给内核——read(ino, offset, buf, len)。这意味着用户程序要自己记当前读到哪了,而且根本不知道文件名,只有一个数字。 这一章引入 文件描述符(fd),让用户程序用熟悉的方式操作文件: int fd = open("hello.txt"); int n = read(fd, buf, 64); close(fd); fd 是什么 fd 是一个进程内的整数,通常从 0 开始分配(0=stdin,1=stdout,2=stderr,之后是普通文件)。 它背后有三层: 进程 fd_table[] 内核 open_file 磁盘 fd=3 ──────────→ { ino=42, offset=0 } ──→ hello.txt fd=4 ──────────→ { ino=43, offset=0 } ──→ readme.txt fd 本身只是下标,真正存 offset 的是内核里的"打开文件"结构。这样的好处: offset 由内核自动推进,用户不用管 fork 后父子可以共享同一个打开文件(共享 offset) 文件、管道、设备用同一套接口,背后实现不同 实现:每个进程一张 fd 表 在 process_t 里加一个数组: typedef struct { // ... int32_t fd_table[PROC_MAX_FD]; // fd → vfs_fd,-1 表示空槽 } process_t; fd_table[fd] 存的是 VFS 层的内部 fd(VFile 数组下标)。 ...

May 14, 2026 · 2 min · 大飞

从零写OS(十二):VFS,让系统调用不认识具体文件系统

上一章我们写了一个 SimpleFS,可以创建文件、读写内容。但现在有个问题:open() 系统调用直接调的是 fs_create、fs_read 这些 SimpleFS 专属函数。 如果哪天要支持 FAT32,就得去改系统调用的代码。这显然不对。 这一章加一层 VFS(Virtual File System,虚拟文件系统),把系统调用和具体文件系统隔开。 先把概念搞清楚 间接层解耦 软件里有句老话:任何问题都可以通过加一层间接层解决。VFS 就是这层间接层。 用户进程 ↓ open / read / write VFS(统一接口) ↓ ↓ SimpleFS FAT32 系统调用只跟 VFS 说话,VFS 再转发给具体 FS。新增一种文件系统,只需要实现 VFS 要求的那几个函数,不动系统调用层。 file_operations:C 语言的多态 VFS 要求每种文件系统提供一张函数指针表: typedef struct { int (*read) (...); int (*write)(...); uint32_t (*lookup)(...); uint32_t (*create)(...); } FileOps; VFS 调 fops->read(...) 时,实际执行的是哪个函数,取决于挂载时注册的是哪张表。这是 C 语言实现"多态"的标准手法,Linux 内核里到处都是这个模式。 vnode:VFS 的通用 inode 具体 FS 有自己的 inode,VFS 层包一层 vnode,里面放着具体 FS 的 inode 号和对应的函数指针表。对上层完全屏蔽了底层差异。 ...

May 6, 2026 · 2 min · 大飞
京ICP备14031575号-3