Skip to content

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,写入的所有文件直接被丢弃

正在精进