七、Linux系统下的文件IO (一)
标准 C 库 IO 函数
标准 C 库 IO 和 Linux 系统 IO 的关系
虚拟地址空间
1. 概念
- 本质:虚拟地址空间是程序员想象出来的概念,实际并不存在物理实体
- 作⽤:
- 解决程序加载到内存时的空间分配问题(如4G内存⽆法同时加载1G+2G+2G程序
的情况) - 解释编程模型中的关键概念(如栈、堆等数据结构的内存分布)
- 解决程序加载到内存时的空间分配问题(如4G内存⽆法同时加载1G+2G+2G程序
- ⽣命周期:
- 程序执⾏时由系统创建对应进程和虚拟地址空间
- 程序结束后虚拟地址空间即消失
- ⼤⼩决定因素:
- 32位系统:2322^{32}232字节 = 4GB
- 64位系统:通常为2482^{48}248字节(⾮2642^{64}264)
2. 用户区详解
- 地址范围:0-3GB(32位系统)
- 可操作性:普通⽤户可直接读写
- 核⼼区域:
- 受保护区域:0-4KB(存放NULL指针等特殊值)
- text段:存储⼆进制机器指令(程序代码)
- data段:已初始化的全局变量
- bss段:未初始化的全局变量(包括显式赋0的情况,int a=0;)
- 堆空间:
- 通过
new/malloc分配 - 从低地址向⾼地址增⻓
- 空间通常较⼤
- 通过
- 栈空间:
- 存储局部变量等
- 从⾼地址向低地址增⻓
- 空间通常较⼩
- 共享库:动态链接库的加载区域
- 命令⾏参数:
main函数的argc,argv参数存储区 - 环境变量:通过
env命令查看的系统环境变量存储区
3. 内核区详解
- 地址范围:3-4GB(32位系统)
- 访问限制:
- 普通⽤户⽆读写权限
- ⾮法访问会导致段错误
- 访问⽅式:必须通过系统调⽤(Linux API)
- 核⼼功能:
- 内存管理:包括虚拟内存映射
- 进程管理:进程调度与控制
- 设备驱动:⽹卡/显卡等硬件驱动
- VFS:虚拟⽂件系统管理
- 映射机制:
- 通过 CPU 的 MMU(内存管理单元)实现虚拟地址到物理地址的转换
- 实际物理内存占⽤远⼩于 4GB 虚拟空间
文件描述符
1. 程序与进程的区别
- 程序特性:
- 源代码和可执⾏⽂件都是程序
- 只占⽤磁盘空间,不占⽤内存空间
- 进程特性:
- 程序运⾏时的实例
- 操作系统为进程分配资源(CPU、内存等)
- 占⽤内存空间,具有虚拟地址空间
- 映射关系:通过 CPU 的 MMU 单元将虚拟地址映射到物理内存
2. 可执⾏⽂件的操作
- ⽂件操作流程:
- 使⽤
fopen打开⽂件 - 使⽤
fread/fwrite进⾏读写操作
- 使⽤
- 定位机制:
- ⽂件指针包含⽂件描述符
- 描述符⽤于定位磁盘上的具体⽂件
3. 文件描述符的位置
(1)文件描述符在内核区
- 内存布局 (32 位的系统举例):
- 0-3G 为⽤户空间
- 3G-4G 为内核区
- 存储位置:⽂件描述符保存在进程内核区
(2)⽂件描述符由内核管理
- 管理机制:
- 通过 PCB(进程控制块)管理
- PCB 是内核中复杂的结构体
- 包含内存管理、⽂件描述符等模块
4. 文件描述符表
(1)文件描述符表的作⽤
- 数据结构:PCB 中的数组结构
- 功能:
- 存储多个⽂件描述符
- ⽀持进程同时操作多个⽂件
- 必要性:⼀个进程可能同时打开多个⽂件
(2)文件描述符表的大小
- 默认容量:1024 个描述符
- 实际限制:决定进程能同时打开的最⼤⽂件数
(3)⽂件描述符表的前三个默认被占⽤情况
- 标准描述符:
- 0:STDIN_FILENO(标准输⼊)
- 1:STDOUT_FILENO(标准输出)
- 2:STDERR_FILENO(标准错误)
- 绑定对象:都指向当前终端设备
/dev/tty - 状态:默认保持打开状态
(4)Linux 系统⼀切皆文件
- Linux特性:
- 硬件设备虚拟为⽂件(如显示器、⽹卡)
- 通过设备⽂件管理硬件
- 终端文件:标准 I/O 对应的终端设备⽂件
Linux 系统文件的底层存储架构
在 Linux 文件系统中,一个文件并不是作为一个整体连续存放在磁盘上的,而是被拆分为以下三个核心部分:
Inode(索引节点,Index Node)
- 本质:文件的元数据面板。
- 包含内容:文件大小、访问权限(rwx)、所有者(UID)、所属组(GID)、时间戳,以及指向实际数据块的指针。
- 唯一标识:每个 Inode 在所属的文件系统内都有一个唯一的、非负整数编号,称为Inode ID。内核访问文件时,实际上是通过 Inode 号来识别的,而非文件名。
Data Block(数据块)
- 本质:磁盘上实际存放文件内容的物理区域(如代码、文本、图片等)。
Directory Entry(目录项,简称 dentries)
- 本质:Linux 中“一切皆文件”,目录也是一个文件。目录的数据块中存放的是一张映射表,记录了该目录下的
| 文件名 | Inode 编号 |的对应关系。 - 结论:文件名并不存储在文件本身的元数据中,而是存储在其父目录的映射表里。
