Linux 文件相关底层知识

1. PCB(task_struct,进程控制块)

操作系统每创建一个程序(进程),就要在内存里开辟一块空间记录这个进程的全部信息,这块信息就叫 PCB。 里面存着:进程 ID、进程状态、内存信息、打开了哪些文件等等一大堆东西。

其中有一个成员,是专门管文件的:files,它指向文件描述符表。

简单理解: PCB = 这个进程的「个人档案袋」,档案袋里面有一张清单,就是文件描述符表。

2. 文件描述符表

它本质是一个数组,属于这个进程私有,别的进程看不到这个表。 数组的每一条记录包含两样东西:

  1. 下标:文件描述符 fd,就是一个普通整数(0、1、2、3、4......)
  2. 数组的值:一个指针,指向内核里的 struct file 对象。

举例子 默认启动进程,自动打开 3 个文件: fd=0 标准输入(键盘) fd=1 标准输出(屏幕打印) fd=2 标准错误(报错信息)

重点: fd 只是数组的编号,本身不是文件,只是一个快捷号码。 不同进程可以都用 fd=3,互相之间完全不冲突,因为每个进程有自己独立的这张表。

3. struct file(文件打开实例)

当你调用open()打开一个文件,内核就会在内存新建一个 struct file。

关键点:每 open 一次,就新建一个 struct file。

它记录的是「这次打开文件之后的状态」,里面重要信息:

  • f_pos:当前读到文件的哪个位置(读写偏移量)
  • f_flags:你是以只读、只写还是追加方式打开的
  • f_inode:指针,指向这个文件对应的 inode
  • f_op:文件操作函数(read、write、close 等)
  • f_count:引用计数,记录现在有多少个 fd 在引用这个 struct file

生活化理解: inode 是一本书本身; struct file 就是你翻开这本书看书,会记住你读到第几页(f_pos)。 你两次打开同一本书,相当于翻开两份独立的阅读记录,各自读到的页码互不影响。

重要场景: fork 创建子进程的时候,子进程会复制父进程的文件描述符表。父子进程 fd 指向同一个 struct file。 此时大家共用同一个 f_pos,你写一点,另一个读的时候就从新位置读。管道进程通信就是靠这个特性实现的。

close (fd) 做的事情:把 struct file 的引用计数减 1。当计数变成 0,内核就释放这个 struct file。

4. struct inode(文件本体)

inode 代表文件本身,存在内核内存里(从磁盘加载上来)。 磁盘上的一个文件,永远只对应一个 inode,不管多少个进程打开它。

inode 保存文件的固定属性,不会记录读到哪里:

  • 文件大小、权限、所属用户
  • 文件数据在磁盘上存放在哪些块
  • 文件类型(普通文件、目录、管道、socket、设备文件)

一句话区分: inode:文件本身的静态信息(不变) struct file:一次打开文件产生的动态阅读记录(会变,比如读文件会改变 f_pos)

整体串联一遍流程

  1. 创建进程,内核分配 PCB(进程档案)
  2. PCB 里面有指针,指向属于这个进程的文件描述符表(数组)
  3. 调用 open 打开文件:内核找到磁盘上文件,加载它的 inode 到内存
  4. 内核新建 struct file,让它的 f_inode 指向这个 inode
  5. 在当前进程的 fd 表里找一个空闲下标,填入指向这个 struct file 的指针,返回这个下标给用户,就是 fd
  6. 之后你调用 read (fd): 根据 fd 去 fd 表拿到 struct file → 借助 struct file 里的 inode 找到磁盘数据,同时更新 struct file 里面的读写位置 f_pos

进程间通信(管道)怎么利用这套结构

管道本质不是磁盘上的文件,是内核内存里的特殊 inode。

  1. pipe 系统调用,内核创建管道,生成特殊 inode,创建 struct file
  2. 得到两个 fd(读端 fd、写端 fd),在当前进程 fd 表中,两个 fd 指向同一个 struct file
  3. fork 之后,子进程复制 fd 表,父子进程都持有这两个 fd
  4. 父子进程共用同一个 struct file,共享缓冲区和读写偏移,一个写,另一个就可以读到数据
相关推荐
Lsetea2 小时前
OpenSSL verify报CA certificate key too weak:auth_level与弱密钥链排查
运维·https·ssl证书·openssl·证书链
羔羊++2 小时前
26_实验二十五_busybox构建根文件系统
linux
熊猫钓鱼>_>2 小时前
从闲置平板到家里的“控制大脑“:鸿蒙智慧中控面板完整实战
运维·人工智能·华为·自动化·电脑·ai编程·harmonyos
xUxIAOrUIII2 小时前
日常笔记-1005-1
linux·笔记·python·macos
nazisami2 小时前
程序地址空间
linux·虚拟地址
库拉镜像AI牛牛3 小时前
漫剧工作室量产方案:依托知漫剧 AI 短剧降本增效
大数据·服务器·前端·人工智能·语音识别
不会就选b3 小时前
Linux之TCP<2>
linux·网络·tcp/ip
DP DPharness3 小时前
浏览器自动化插件时,三个可核对的判断维度
运维·自动化
沫璃染墨3 小时前
《从零入门Linux系统篇(五十八):线程篇·十一——线程安全与死锁详解:从可重入到多锁管理》
linux·服务器·开发语言·c++·驱动开发·安全·架构