文件系统
负责把用户的文件存到硬盘中。
文件系统的组成
linux系统为每个文件分配两个数据结构:索引节点,目录项;
- 索引节点Inode:记录文件的元信息,是文件的唯一标识;也存储在磁盘中。
- 目录项:记录文件的名字,索引节点指针以及与其他目录项的层级关系;目录项由内核维护,缓存在内存中。
目录项和目录的关系?
目录是文件,存储在磁盘;目录项是内核的一个数据结构,缓存在内存。
如果查询目录频繁从磁盘读,效率会很低;所以内核会把已经读过的目录用目录项缓存在内存;下次读到相同的目录时,直接从内存读。
磁盘格式化时,会分成三个区域:
- 超级块:用来存储文件系统的详细信息:比如块个数、块大小、空闲块等。
- 索引节点区
- 数据块区
虚拟文件系统
文件的使用
操作系统为每个进程维护一个打开文件表;文件表里的每一项代表文件描述符, 记录着打开文件的状态和信息。
文件系统的基本操作单位是 数据块。
- 当用户进程从文件中读取数据时,文件系统需要找到所在的数据块,再返回所需的数据块中对应的部分。
- 当用户进程把数据写进文件时,文件系统需要找到所在的数据块,再修改数据块中对应的部分,最后再把数据块写回磁盘。
文件的存储
连续空间存放方式
读写效率高,但是有 磁盘空间碎片 和 文件长度不易拓展 的缺陷。
非连续空间存放方式
链表方式
隐式链表
:单链表逻辑结构。
显式链接 :把各指针存放在内存的一张链接表中,称为文件分配表(FAT)。
索引方式
若处理大文件的存放:
方案一:
方案二:
UNIX文件的实现方式
空闲空间管理
空闲表法
空闲链表法
位图法
1111110011111110001110110111111100111...
Linux系统采用位图管理空闲空间。
文件系统的结构
超级块和块组描述符表,这两个都是全局信息,但非常重要;所以重复存储。
目录的存储
对文件名进行哈希计算,提高找文件效率。
把当前使用的目录缓存在内存,减少磁盘I/O。
软链接和硬链接
硬链接: 索引节点指针。只有删除文件所有硬链接和源文件后,系统才会彻底删除该文件。
软链接: 文件,有独立inode, 内容为另一个文件的访问路径。
文件I/O
缓冲与非缓冲I/O
- 缓冲I/O,利用标准库的缓存实现文件的加速访问,标准库再通过系统调用访问文件。
- 非缓冲I/O,直接通过系统调用访问文件。
直接与非直接I/O
- 直接I/O,直接经过文件系统访问磁盘;
- 非直接I/O,读操作时,数据从内核缓存中拷贝给用户程序;写操作时,数据从用户程序拷贝给内核缓存,再由内核决定什么时候写入数据到磁盘。
阻塞与非阻塞I/O
阻塞I/O
非阻塞I/O
同步与异步I/O
同步I/O
基于非阻塞I/O的多路复用
真正的异步I/O,是内核数据准备好和数据从内核态拷贝到用户态两个过程都不用等待。
异步I/O
设备管理
设备控制器
控制器有三类寄存器,分别是状态寄存器,命令寄存器,数据寄存器:
输入输出设备可分为:块设备,字符设备;
- 块设备:数据存储在块中;硬盘,USB等。
- 字符设备:以字符为单位;如鼠标。
数据缓存区:
- CPU写入数据到控制器的缓存区时,当缓存区的数囤够一部分,才会发给设备;
- CPU从控制器的缓存区读取数据时,也需要缓冲区囤够一部分,才会拷贝给内存。
CPU与设备控制器的寄存器及数据缓冲区通信方法:
- 端口I/O:每个寄存器都被分配I/O端口,可以通过汇编指令操作;
- 内存映射I/O,将所有寄存器映射到内存空间中,可以像读写内存一样读写数据缓存区。
I/O控制方式
设备驱动程序
设备驱动程序会提供统一的接口给操作系统。
操作系统响应并处理控制器发来的中断请求:中断处理程序
通用块层
Linux通过一个统一的通用块层,来管理不同的块设备; 同时,还会给文件系统和应用程序发来的I/O请求排队,即I/O调度。
linux内支持五种I/O调度算法:
- 没有调度
- 先入先出
- 完全公平(时间片)
- 优先级
- 最终期限调度(分别为读、写请求创建不同的I\O队列)
存储系统I/O软件分层
分为三个层次:
- 文件系统层,包括虚拟文件系统及其他文件系统的具体实现,向上为应用程序统一提供标准的文件访问接口,向下通过通用块层管理磁盘数据;
- 通用块层,包括块设备的I/O队列和调度器,负责I/O调度;
- 设备层,包括硬件设备,控制器和驱动程序,负责最终物理设备的I/O操作。
键盘敲入字母时发生了什么
- 用户输入键盘,键盘控制器扫描数据,并缓存在寄存器中;通过总线向CPU发送中断请求;
- CPU收到后,操作系统保存被中断进程的CPU上下文,并调用键盘的中断处理程序;
- 中断处理程序是在驱动程序初始化时注册的;中断处理函数从寄存器缓冲区中读写数据,并译成ASCII码;
- ASCII码被放入读缓冲区队列中;显示设备的驱动程序定时从读缓冲区队列读取数据到写缓冲区队列,并将其写入到显示设备控制器的寄存器的数据缓冲区;最后显示在屏幕上。
- 显示出结果后,恢复被中断进程的上下文。