Linux基础IO与Ext文件系统深度复习:从文件描述符到磁盘存储原理

📅 发布时间:2026/8/18 9:32:50
Linux基础IO与Ext文件系统深度复习:从文件描述符到磁盘存储原理
前言为什么学习IO和文件系统在 Linux 学习过程中很多同学第一次接触文件操作时会觉得fopen()为什么可以打开文件printf()输出到屏幕本质上到底发生了什么open()返回的数字3、4有什么意义删除文件到底删除了什么一个文件的数据究竟保存在哪里这些问题的答案都需要理解 Linux 的基础IO机制和文件系统原理。本文结合两个核心知识模块Linux 基础 IOExt 系列文件系统帮助快速建立完整知识体系应用程序 | | fopen/read/write | 系统调用接口 | | open/read/write | Linux内核 | | 文件系统(ext) | | 磁盘(block/sector)基础IO部分重点包括文件、系统调用、文件描述符、重定向等内容文件系统部分重点包括磁盘寻址、inode、block、Ext文件系统组织方式等。一、Linux中的文件到底是什么1. 狭义理解磁盘上的文件传统理解文件就是存储在磁盘中的数据。磁盘属于外部设备因此文件操作 ↓ 磁盘数据读写 ↓ IO操作也就是说文件操作本质就是输入输出操作。文件并不是只有内容。一个文件由两部分组成文件 | ---- 属性(metadata) | ---- 内容(data)例如ls -l test.txt显示-rw-r--r-- 1 root root 1024 test.txt其中权限文件大小所属用户修改时间都是文件属性。而hello linux属于文件内容。Linux 文件属性和内容是分离管理的这一点在后面的 inode 中非常重要。二、C语言文件IO用户看到的接口我们最开始学习文件操作一般使用FILE *fp fopen(test.txt,w);例如#include stdio.h int main() { FILE *fp fopen(test.txt,w); if(fp NULL) { perror(fopen); return 1; } fprintf(fp,hello linux\n); fclose(fp); return 0; }这里fopen fwrite fread fclose都是 C 标准库提供的接口。它们并不是直接操作磁盘。真实流程fwrite() | ↓ C标准库(libc) | ↓ 系统调用(write) | ↓ Linux内核 | ↓ 文件系统 | ↓ 磁盘文件读写最终依靠的是系统调用而 C 库函数只是对系统调用进行封装方便程序员使用。三、系统调用IOopen/read/writeLinux提供更加底层的文件接口open() read() write() close() lseek()例如写文件#include fcntl.h #include unistd.h #include string.h int main() { int fd open( test.txt, O_WRONLY | O_CREAT, 0644 ); char *msghello syscall\n; write(fd,msg,strlen(msg)); close(fd); return 0; }这里int fd就是文件描述符。四、文件描述符 fdLinux IO核心概念1. fd是什么文件描述符本质是一个小整数。例如int fdopen(test.txt,O_RDONLY); printf(%d\n,fd);可能输出3为什么不是1因为 Linux 默认已经打开三个文件fd含义0stdin 标准输入1stdout 标准输出2stderr 标准错误所以0 - 键盘 1 - 显示器 2 - 显示器 3 - 新打开文件Linux进程默认拥有三个文件描述符标准输入0、标准输出1、标准错误2。2. fd为什么只是数字因为进程内部维护了一张表进程 | files_struct | 文件描述符表 | ----0 --- stdin | ----1 --- stdout | ----2 --- stderr | ----3 --- test.txt所以fd 数组下标拿到fdfd | ↓ 找到文件对象 | ↓ 访问文件文件描述符本质就是进程文件表中的索引。五、Linux重定向原理我们经常使用ls log.txt表示把输出保存到文件。为什么可以做到1. stdout本质也是文件默认stdout(fd1) | ↓ 显示器如果修改stdout(fd1) | ↓ log.txt那么printf(hello);自然进入文件。2. dup2实现重定向代码#include unistd.h #include fcntl.h int main() { int fdopen( log.txt, O_CREAT|O_WRONLY, 0644 ); dup2(fd,1); printf(hello redirect\n); return 0; }执行后printf | stdout(fd1) | log.txt完成输出重定向。shell中的 本质都是修改文件描述符对应关系。六、磁盘如何存储数据文件最终需要保存到磁盘。但是磁盘不是简单的一块空间。1. 扇区 Sector磁盘最基本存储单位Sector通常512 Bytes操作系统访问磁盘时并不是直接使用文件名而是访问磁盘上的地址。七、磁盘寻址CHS与LBA1. CHS寻址早期磁盘C Cylinder H Head S Sector通过柱面 磁头 扇区定位数据。公式LBA C*(磁头数*每磁道扇区数) H*每磁道扇区数 S-1CHS适合早期磁盘但是容量有限。2. LBA寻址现代系统更加喜欢Logical Block Address也就是逻辑地址。把磁盘抽象成sector0 sector1 sector2 sector3 ...类似数组disk[100]访问disk[50]就是访问第50个扇区。操作系统主要使用LBA具体转换由磁盘内部完成。八、为什么需要文件系统如果只有磁盘00000000 00000001 00000002 ...我们不知道哪些数据属于哪个文件文件属性在哪里空闲空间在哪里所以需要文件系统负责管理文件 目录 inode block 空间分配Ext系列文件系统就是 Linux 中经典文件系统之一。九、Ext文件系统核心inode block1. inode保存属性Linux中inode保存文件大小权限用户时间数据块位置例如inode | ---- 文件大小 | ---- 权限 | ---- block地址注意文件名不保存在inode中。文件名属于目录数据。2. block保存内容文件内容Data Block例如hello.txt inode | | block1 block2 block3inode负责找到数据。十、Ext2文件系统结构一个分区格式化以后Block Group ------------- | Super Block | ------------- | GDT | ------------- | BlockBitmap | ------------- | InodeBitmap | ------------- | InodeTable | ------------- | DataBlock | -------------Super Block保存整个文件系统的信息例如block数量inode数量空闲空间文件系统状态超级块损坏会影响整个文件系统。Block Bitmap记录哪些block已经使用。例如11110000表示前4个block占用。Inode Bitmap记录哪些inode可以使用。例如11001000表示部分inode已经分配。Inode Table保存所有inode。例如inode 100 | test.txt属性 inode 101 | main.c属性十一、创建文件时发生了什么执行touch abc系统大概做第一步寻找空闲inodeinode bitmap | ↓ 找到空inode记录abc属性第二步分配数据块找到Data Block第三步建立目录关系目录保存文件名 - inode编号最终abc | inode | block | 数据内容文件系统通过inode和block完成文件管理。十二、软链接与硬链接理解硬链接不是一个独立的文件本质是一组新的文件名和目标inode number的映射关系即多了一个新的文件名指向目标文件作用对文件进行备份多个名字指向同一个inodefile1 | inode100 | data file2 | inode100特点inode相同删除一个名字不影响数据查看ls -li使用ln code.c code.c.back 之后删了code.c再cat code.c.cback还是可以看到code.c内容软链接类似Windows快捷方式link | 指向路径 | file创建ln -s target link特点有自己的inode保存目标路径使用一个文件叫a.out 要运行它输入它的路径: ln -s .bin/exe/execute/a.out exe 这样以后输入exe可以直接运行a.out删除unlink exe十三、总结基础IO核心记住FILE* ↓ 库函数 ↓ 系统调用 ↓ fd ↓ 文件对象 ↓ 文件系统 ↓ 磁盘重点fopen是库函数open是系统调用fd是数组下标0/1/2分别对应stdin/stdout/stderr重定向本质是修改fd映射Ext文件系统核心记住文件 inode(属性) block(内容)磁盘sector ↓ block ↓ filesystem ↓ fileExtSuper Block GDT Bitmap inode table Data Block最终理解Linux 文件系统设计思想可以总结为应用程序看到的是文件内核管理的是文件描述符文件系统管理的是inode和block而磁盘最终管理的是sector。理解这条链路基础IO和Ext文件系统的大部分知识点都会串起来。