task_struct进程本体进程描述符files_struct进程打开的文件描述符表fd 数组fs_struct进程的当前目录、根目录、umask进程的 “文件系统视角”内核真实结构struct task_struct { // ... struct files_struct *files; // 打开文件描述符表 → fd 0,1,2... struct fs_struct *fs; // 当前目录、根目录、umask struct mm_struct *mm; // 地址空间 // ... };极简定义1. task_struct进程 / 线程的完整描述符包含PID、状态、调度、信号、内存、文件、fs、credentials…一切进程资源的根2. files_struct重点文件描述符管理进程打开了哪些文件struct file **fdfd 数组fd 0 → stdin…max_fds最大 fd 数量用于open/read/write/close/dup每个进程独立fork 会拷贝核心四层结构task_struct ↓ (current-files) files_struct ← 【文件描述符表本体】 ↓ (fdt-fd) struct file *fd[] ← 【fd 数组下标 文件描述符】 ↓ struct file ← 内核打开文件对象含偏移、flags、f_opfiles_struct 定义struct files_struct { atomic_t count; // 引用计数 struct fdtable *fdt; // 真正的描述符表 }; struct fdtable { unsigned int max_fds; struct file **fd; // 动态数组fd[0], fd[1], fd[2]... };fd 整数 数组下标files_struct 管理这张数组数组元素是struct file*指向内核文件对象工作全过程从 open 到 close1. 进程 open (/tmp/xxx)内核创建struct file在files_struct-fdt-fd[]找最小未使用下标→ 这就是返回的fd将fd[num] struct file返回这个数字如 3、4、5…2. read(fd, buf, size)用 fd 作为下标current-files-fdt-fd[fd]得到struct file*调用file-f_op-read(file, ...)3. close(fd)fd[fd] NULL减少struct file引用计数计数为 0 时真正关闭文件共享 vs 复制fork () 时files_struct 会被复制父子各一张独立 fd 表但struct file 共享引用计数 1结果父子各自 close 不影响对方但文件偏移量是共享的dup / dup2 / fcntl(F_DUPFD)复制数组下标指向两个 fd 指向同一个 struct file偏移、状态完全共享3. fs_struct重点文件系统上下文fs_struct 不管理打开的文件只管理进程在文件系统中的 “位置与环境”。struct path pwd当前工作目录 (current working directory)struct path root根目录 /umask文件创建权限掩码用于chdir、chroot、umask、open(相对路径)默认 fork 共享可通过 CLONE_FS 控制fs_struct内核结构struct fs_struct { atomic_t count; // 引用计数 rwlock_t lock; int umask; // 创建文件默认权限掩码 struct path root; // 进程的根目录 / struct path pwd; // 进程的当前工作目录 (current working directory) };两个最核心成员root进程看到的根目录决定chroot效果pwd进程当前在哪个目录决定相对路径怎么解析umaskopen()创建文件时的权限掩码只要涉及路径、目录、根、权限掩码全部走current-fs相对路径解析open(file.txt)→ 依赖fs-pwdcdchdir修改fs-pwdchroot修改fs-rootumask()修改fs-umask它完全不关心 fd、不关心打开了哪些文件。fork () 默认行为files_struct复制父子独立 fd 表fs_struct共享父子共用同一个 fs这意味着父进程 chdir子进程的当前目录也会变因为他们共享同一个fs_struct。如何不共享使用clone()时不加CLONE_FS或者线程库内部会处理。fs_struct vs files_struct结构体管理内容关键词依赖系统调用fork 时fs_struct进程目录、根、umask位置、环境chdir, chroot, umask共享files_struct文件描述符表 (fd 数组)打开文件、I/Oopen, read, write, close拷贝最简记忆fs 我在哪里目录、根、掩码files 我打开了什么fd 表fork 时行为fs_struct共享父子同目录、同根、同 umaskfiles_struct复制父子各一张独立 fd 表但共享 struct file最关键区别files_struct我打开了哪些文件fd 表、文件句柄、I/O 相关。fs_struct我在文件系统里的位置当前目录、根目录、umask。task_struct我是谁整个进程。内核宏current // task_struct* current-files // files_struct* current-fs // fs_struct*三者整体总图task_struct (进程描述符) │ ├─→ fs_struct 【文件系统视角】 │ │ │ ├─ root 根目录 / │ ├─ pwd 当前目录 │ └─ umask 权限掩码 │ └─→ files_struct 【文件描述符表】 │ └─ fdtable │ ├─ fd[0] → struct file (标准输入) ├─ fd[1] → struct file (标准输出) ├─ fd[2] → struct file (标准错误) ├─ fd[3] → struct file (打开的文件) └─ ...