7.1 文件系统全家桶
Linux 「一切皆文件」
- 普通的文件和目录
- 普通文件保存文件数据
- 目录保存文件的指针,Linux 使用哈希表进行保存,快速查找、插入、删除,会优先缓存在内存中
- 块设备
- 管道
- socket
Linux 目录项是一个内核的一个数据结构,存储在内存中
Linux 系统上供用户可访问的内存分为两个类型,即:
- page:内存管理分配的基本单位,通常是 4KB 大小
- File-backed pages:文件备份页
- 对应于磁盘上的数据;
- 回收代价较低
- 如果是脏页,需要落盘后回收
- 如果是干净页,直接释放即可
- 且对应文件,所以可以顺序 I/O 落盘
- Anonymous pages:匿名页
- 不对应磁盘上的任何磁盘数据块
- 回收代价较高,所有都需要落盘后回收(Swap),且通常随机写入
- 是进程的运行是内存空间(例如方法栈、局部变量表等属性);
虚拟文件系统
文件系统的种类众多,而操作系统希望对用户提供一个统一的接口,于是在用户层与文件系统层引入了中间层,这个中间层就称为虚拟文件系统(Virtual File System,VFS)。
文件系统首先要先挂载到某个目录才可以正常使用,比如 Linux 系统在启动时,会把文件系统挂载到根目录。
文件的使用
读取一个文件的过程:
open:打开文件,指定以下信息- 文件路径和文件名
- 文件的权限
write:写数据- 使用
open所返回的文件描述符,而不是文件名。
- 使用
close:关闭文件,避免资源的泄露。- 在打开过程中会维护文件状态和信息
- 文件指针:读写位置,每个进程一个;
- 文件打开计数器:
- 一个文件被一个进程打开,计数器+1
- 当该计数为 0 时,系统关闭文件,删除该条目;
- 文件磁盘位置:为了满足修改文件数据方便落盘;
- 访问权限:创建、只读、读写、添加等;
文件的存储
有以下两种:
连续空间存放方式
- 优点:效率高,一次寻址可以独处整个文件
- 缺点:磁盘空间碎片,文件长度扩展成本高
非连续空间存放方式
- 分为「链表方式」和「索引方式」
位图法(空闲空间管理)
- 利用二进制的一位来表示磁盘中一个盘块的使用情况,磁盘上所有的盘块都有一个二进制位与之对应。
- 是 Linux 文件系统采用的
软链接和硬链接
文件别名
- 硬链接:
- 创建命令
ln link source - 存放了文件的地址
- 删除一个硬链接对其他硬链接不影响
- 一个文件至少一个,所有硬链接和源文件删除才会删除该文件
- 不可以跨系统,每个系统不同
- 创建命令
- 软链接(快捷方式)
- 创建命令
ln -s slink source - 存放另一个文件的路径名
- 目标文件被删除,就成了死链接(没用了)
- 可以跨文件系统,每个系统的文件名可以相同
- 创建命令
Page Cache
Linux 内核管理的内存区域 ,即内核缓冲区;
- Page Cache:缓存文件的页数据
- 与文件系统同级
- 读数据时首先看这里有没有,没有才去磁盘获取,并且将数据放在这里
- 会有预读,将相邻的几个页数据也一起加载到内存
- buffer cache:缓存块设备(如磁盘)的块数据
- 与块设备驱动程序同级
- 直接 I/O 也会被加载
- 一般情况直接通过指针指向Page Cache,避免浪费,跳过Page Cache的(如直接I/O)才会放到buffer cache中
- 两者目的都是加速数据 I/O
- 最直接的缺点是需要占用额外物理内存空间,物理内存在比较紧俏的时候可能会导致频繁的 swap 操作,最终导致系统的磁盘 I/O 负载的上升。
- 且没有提供API管理,所以如 Mysql 自己实现了 page 管理
- 且比 直接 I/O 多了一次磁盘读写
这是因为从磁盘中加载到内存的数据不仅仅放在 Page Cache 中,还放在 buffer cache 中。
例如通过 Direct I/O 技术的磁盘文件就不会进入 Page Cache 中(只会进入到buffer cache中)。
Swap 与缺页中断
- Swap:
- 当物理内存不够用,将部分数据交换到磁盘后腾出空间
- 频繁swap会影响性能(I/O慢)
swappiness控制频率,越大频率越高
- 缺页中断:
- 当进程发现需要访问的数据不在内存时,操作系统可能会将数据以页的方式加载到内存中。
文件 I/O
- 缓冲与非缓冲 I/O
- 缓冲:利用标准库,标准库调用系统访问文件
- write 会先将文件写入内核的page cache
- 这个时候进程崩溃,page cache中有崩溃前的数据,不会数据丢失
- 这个时候系统崩溃,会丢失数据
- 非缓冲:直接调用系统访问文件
- 缓冲指标准库内部实现的缓冲
- 缓冲:利用标准库,标准库调用系统访问文件
- 直接与非直接 I/O
- 直接:跳过内核缓冲区直接访问磁盘(write through)
- 非直接:内核缓冲区作为过渡进行访问(write back默认)
- 内核定时刷盘(如果内存不够也会刷)
- 主动调用 fsync 进行刷盘
- 写入当文件称为脏页
- 直接 I/O 保证了即使系统宕机数据也持久化了,但是频繁和磁盘 I/O 效率很低
- 阻塞与非阻塞 I/O VS 同步与异步 I/O
- 阻塞:执行读写,线程阻塞直到内核将数据拷贝到应用缓冲区,会轮询内核是否准备好(I/O多路复用)
- 非阻塞:执行读写,CPU立刻切换到其他线程,直到数据准备好,拷贝到应用缓冲区
- 两个都是同步的,需要CPU将数据从内核缓冲区拷贝到应用缓冲区
- 异步 I/O:拷贝过程CPU完全不参与
特殊文件
- 终端:/dev/tty
- 黑洞文件:
/dev/null,写入的所有文件直接被丢弃
