Linux--初识文件系统fd
01. C/系统调用文件操作
C/系统调用文件操作
02. 文件系统(ext2)结构
Linux ext2文件系统,上图为磁盘文件系统图(内核内存映像肯定有所不同),磁盘是典型的块设备,硬盘分区被划分为一个个的block。一个块的大小(有1MB,2MB或4MB)是由格式化的时候确定的,并且不可以更改。而上图中启动块引导快的大小是确定的。每个块组都有着相同的结构组成。
超级块和块组描述符表 会在多个块组中备份,以提高容错能力。其余结构(数据块位图、inode 位图、inode 表、数据块)是每个块组独立管理的。
文件访问:
- 通过目录数据块找到文件名对应的inode
- 从inode表中读取inode号,在文件混合索引内找到获取数据块指针
- 根据指针访问文件内容
文件创建:
- 在位示图找到为o的inode分配并写入inode表
- 在文件数据块找到空闲块分配给它
- 更新数据块,并添加文件名和inode的映射关系
文件删除:
- 位示图和数据块位图置0,并在目录数据块删除此二元关系
2.1 超级块
存放文件系统本身的结构信息。记录的信息主要有:bolck 和 inode的总量,未使用的block和inode的数量,一个block和inode的大小,最近一次挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间等其他文件系统的相关信息。Super Block的信息被破坏,可以说整个文件系统结构就被破坏了
struct ext2_super_block {__le32 s_inodes_count; /* 索引节点总数 */__le32 s_blocks_count; /* 块总数 */__le32 s_r_blocks_count; /* 保留的块数 */__le32 s_free_blocks_count; /* 空闲块计数器 */__le32 s_free_inodes_count; /* 空闲索引节点计数器 */__le32 s_first_data_block; /* 第一个数据块的块号,总是为1 */...__le32 s_first_meta_bg; /* 第一个元块组 */__u32 s_reserved[190]; /* 填充到块的末尾 */
};
2.2 块组描述符表
描述块组属性信息
2.3 位示图
块组中 Inode 的分配状态(已用/空闲)
struct ext2_inode {__le16 i_mode; /* 文件类型和访问权限,查看S_ISREG()等函数 */__le16 i_uid; /* 所有者 Uid 的低 16 位,拥有者id */// 文件长度,最高位没使用,最大表示2GB文件,大于2GB文件再使用i_dir_acl字段__le32 i_size; /* 大小(字节) */__le32 i_atime; /* 访问时间 */__le32 i_ctime; /* 索引节点创建时间 */__le32 i_mtime; /* 文件数据最后改变时间 */__le32 i_dtime; /* 删除时间 */__le16 i_gid; /* 组 ID 的低 16 位,用户组id */__le16 i_links_count; /* 硬链接计数 */
...
};
2.4. 文件描述符fd
fd是操作系统中用于标识和访问已打开文件或I/O资源的整数标识符。存放
- 每个进程的
task_struct
包含一个files_struct
结构,内部维护一个 fd 数组 file*fd_array[]
中存放多个file*
- 数组索引(下标)即为
fd
,数组内部元素指向内核中的file
对象
在file*fd_array[]
中下标为0
、1
、2
分别预留给stdin
,stdout
,stderr
,所以新分配的原则是选择未使用最小的开始分配。使用close()
即可释放任意已分配的fd,进程结束未关闭的fd
由内核自动回收。
2.5. 重定向
待写…
2.6. inode
存储文件或目录的元数据(不包括文件名)
注:
- 在Unix文件系统中,每个文件必须对应一个inode结点,而 inode结点的总数量是有上限的。如:仅用8KB作为inode区,假设每个inode大小为64B,则该文件系统最多只能存储8KB/64B=128个 inode结点,相应地,该系统最多只能支持128个文件。
- 当一个进程通过open系统调用打开某个文件时,操作系统需要将该文件对应的 inode结点读入主存。
2.7 数据块
- 作用:存储文件的实际内容或目录的结构信息。
- 类型:
- 文件数据块:存储普通文件的实际内容(如文本、图片等)。
- 目录数据块:存储该目录下的条目(文件名 + Inode 号)。
- 符号链接数据块:若链接路径较短,直接存储在 Inode 中;较长时占用数据块。
- 特殊文件:如设备文件(/dev/sda)的元数据存储在 Inode 中,无需数据块。
文件数据块:
当一个文件过大时,则需要多个块储存数据。
目录文件数据块:
存放的是目录下文件名和inode的二元映射关系。
2.8 缓冲区
缓冲区的存在,能够提高数据效率。一般c语言库函数写入文件采用的是全缓冲,而写入显示器是航缓存。
如果一块数据多次分批写入外存效率低开销大,但是一次性写入效率最高。
- 全缓冲:文件输出,效率高但实时性差,缓冲区满
I/O
。 - 行缓冲:**终端(C库)**输出,遇到
\n
或缓冲区满时刷新。 - 无缓冲:如
stderr
,立即输出。
缓冲区刷新:
- 用户强制刷新
- 进程退出
例如有语句char *str="helloworld"
,首先将该字符串存放在FILE结构体
内的C缓冲区,满足条件后将数据刷新到内核缓冲区,在这个区域由OS
维护和操作。
首先关闭文件描述符为1
,open
分配的log.txt
文件的fd为1
,后面printf
和fprintf
会对新打开的文件(fd=1
)执行新操作,改变了刷新机制。但是close(fd)
使得文件描述符被关闭,C缓冲区
内容无法向OS文件内核缓冲区
刷新,故不会将数据刷新到log.txt
内。
03. 软硬链接
二者区别:软链接会创建新的inode,而硬连接不会。
硬链接:
- 在目录条目中新增一个文件名,指向同一 inode。
- inode 的
引用计数
会递增(可通过stat
命令查看)
软链接:
- 创建一个新的 inode 和文件,文件内容为目标路径字符串。
- 访问软链接时,内核会递归解析路径。
04. 动静态库
待写…