UNIX高级环境编程(16)文件系统 < 雨后 >
来点绿色放松一下眼睛吧 :)

文件系统是对文件和目录的组织集合。
一 设备文件
设备文件和系统的某个设备相对应。
设备驱动程序
- 处理设备的所有IO请求。
- 提供了一致的API接口,对应于系统调用的open, close, read, write, mmap以及ioctl,屏蔽了底层设备的差异。
设备的类型
- 字符型设备:基于每个字符来处理请求,例如终端和鼠标、键盘。
- 块设备:按数据块处理请求,通常数据块是512字节的整数倍。例如硬盘和磁带。
设备ID
- 每个设备文件都有主、辅设备文件ID。主文件ID标识一般的设备等级,内核会根据主ID查找与该类设备对应的设备驱动程序。
- 辅ID能够在一般等级中唯一标识特定设备。
- 文件的inode中记录了主辅ID
二 磁盘和分区
2.1 磁盘驱动器
磁盘驱动器是一种机械装置,由一个或多个高速旋转的盘片组成。通过在磁盘上快速移动读写磁头,便可获取/修改磁盘表面的磁性编码信息。
其结构见下图。


磁道:磁盘表面的信息存储在称为磁道的一组同心圆上。
扇区:磁道被划分为若干扇区。
物理块:扇区包含一系列物理块,物理块的容量一般为512字节,代表了驱动器可以读写的最小信息单位。
寻道时间:读写磁盘信息,首先,磁头要移动到相应磁道,这段时间叫做寻道时间。
旋转延迟:然后,驱动器要等待相应的扇区旋转到磁头下。
传输时间:最后,从所请求的块上传输数据。
执行上述操作所耗费的时间总量通常以毫秒为单位。
2.1 磁盘分区
分区:可将每块磁盘换分成一个或多个不重叠的分区。内核则将每个分区视为位于/dev路径下的单独设备。
磁盘分区可容纳任何类型的信息,通常包括:
- 文件系统:用来存放常规文件
- 数据区域:可做为裸设备对其进行访问,一些数据库管理系统会这样使用。
- 交换区域:供内核的内存管理之用。
可使用Linux专有文件/proc/swaps来查看系统中当前已激活交换区域的信息,其中包括每个交换区域的大小,以及在用交换区域的个数。
三 文件系统
文件系统是对常规文件和目录的组织集合。
Linux的强项之一是支持种类繁多的文件系统。
以ext2为例来介绍文件系统。
3.1 文件系统结构
逻辑块:在文件系统中,用来分配空间的基本单位是逻辑块,也就是文件系统所在物理设备上若干连续的物理块。在ext2文件系统上,逻辑块的大小为1024、2048或4096。
磁盘分区和文件系统之间的关系如下图所示

文件系统由以下几个部分组成:
- 引导块:总是作为文件系统的首块。引导块不为文件系统所用,只是包含用来引导操作系统的信息。
- 超级块:紧随引导块之后的一个独立块,包含与文件系统相关的参数信息,包括:
- i节点表容量
- 文件系统中逻辑块的大小
- 以逻辑块计,文件系统的大小
- i节点表:文件系统中的每个文件或目录在i节点表中都对应着唯一一条记录。这条记录登记了和文件相关的各种信息。
- 数据块:文件系统的大部分空间都用于存放数据,以构成驻留于文件系统之上的文件和目录。
3.2 i节点
i节点维护的信息如下
- 文件类型
- 文件属主
- 文件属组
- 3类用户的访问权限
- 3个时间戳:对文件的最后访问时间、文件的最后修改时间、文件状态的最后改变时间
- 指向文件的硬连接数量
- 文件的大小,以字节为单位
- 实际分配给文件的数据块,以512字节为单位
- 指向文件数据块的大小
ext2中的i节点和数据块指针
文件的数据块不一定连续,为了定位文件数据块,inode维护了一组指针,如下图所示:

在ext2中,每个inode包含15个指针,其中
- 前12个指针指向前12个数据块在文件系统中的位置。
- 第13个指针是一个一重间接指针
- 第14个指针是一个二重间接指针
- 第15个指针是一个三重间接指针
这样设计的意图是:
- inode结构固定大小固定,并支持任意大小的文件
- 可以不连续地存储文件,并支持lseek随机访问,内核只需要计算所要遵循的指针
- 对于有大量小文件的系统中,可以对数据进行快速访问,一次搜索就可以访问。
四 虚拟文件系统(VFS)
Linux所支持的各种文件系统,其实现细节均不相同。虚拟文件系统是一种内核特性,通过为文件系统操作创建抽象层来解决各种文件系统之间的差异问题。

原理:
- VFS针对文件系统定义了一套通用接口,所有与文件交互的程序都会按照这一接口来进行操作。
- 每种文件系统都会提供VFS接口的实现。
这样一来,程序只需要理解VFS接口,而无需过问具体文件系统的实现细节。
五 日志文件系统
如果系统突然崩溃,对文件的更新的只完成了一半,文件系统元数据也将处于不一致状态。
而系统对文件系统进行一致性检查需要遍历整个文件系统,这是一个非常耗时的操作。
日志文件系统就是为了解决这个问题。具体做法是
- 在实际更新元数据之前,日志文件系统会将这些更新操作记录于专用的磁盘日志文件中。
- 对元数据更新的操作记录是以事务的方式进行的,这样确保总是将文件元数据事务作为一个完整单元来提交。
需要注意的是,通常日志文件系统知会确保元数据的一致性,不会记录文件数据。因此,一旦系统崩溃,可能会造成数据丢失。
六 单根目录层级和挂载点
Linux上的所有文件系统中的文件都位于单根目录树下,其他文件系统都挂载在根目录下。
挂在命令:
mount device directory
下面通过实例来说明挂载后的文件系统的层级关系。
不带任何参数来执行mount命令,可以列出当前已挂载的文件系统。

挂载点和设备的映射关系如下

七 虚拟内存文件系统:tmpfs
Linux支持驻留于内存中的虚拟文件系统,对于应用程序来说,此类文件系统看起来与任何其他文件系统别无二致,不过二者的重要的差别是:
- 由于不涉及磁盘访问,虚拟文件系统的文件操作速度极快
- 该文件系统不仅可以使用RAM,而且在RAM资源耗尽的情况下,还会利用交换空间
- 默认情况下,允许tmpfs文件系统的大小提高至RAM容量的一半
- 一旦写在tmpfs文件系统,或者遭遇系统崩溃,那么该文件系统中的所有数据都将丢失
挂在虚拟文件系统命令如下:
mount -t tmpfs source target

- 由内核内部挂在的隐形tmpfs文件系统,用于实现System V共享内存和共享匿名内存映射。
- 挂在与/dev/shm的tmpfs文件系统,为glibc用以实现POSIX共享内存和POSIX信号量。
UNIX高级环境编程(16)文件系统 < 雨后 >的更多相关文章
- UNIX高级环境编程1
UNIX高级环境编程1 故宫角楼是很多摄影爱好者常去的地方,夕阳余辉下的故宫角楼平静而安详. 首先,了解一下进程的基本概念,进程在内存中布局和内容. 此外,还需要知道运行时是如何为动态数据结构(如链表 ...
- UNIX高级环境编程(14)文件IO - O_DIRECT和O_SYNC详解 < 海棠花溪 >
春天来了,除了工作学习,大家也要注意锻炼身体,多出去运动运动. 上周末在元大都遗址公园海棠花溪拍的海棠花. 进入正题. O_DIRECT和O_SYNC是系统调用open的flag参数.通过指定o ...
- Unix高级环境编程
[07] Unix进程环境==================================1. 进程终止 atexit()函数注册终止处理程序. exit()或return语句: ...
- UNIX高级环境编程(4)Files And Directories - umask、chmod、文件系统组织结构和链接
本篇主要介绍文件和文件系统中常用的一些函数,文件系统的组织结构和硬链接.符号链接. 通过对这些知识的了解,可以对Linux文件系统有更为全面的了解. 1 umask函数 之前我们已经了解了每个文件 ...
- UNIX高级环境编程(15)进程和内存分配 < 故宫角楼 >
故宫角楼是很多摄影爱好者常去的地方,夕阳余辉下的故宫角楼平静而安详. 首先,了解一下进程的基本概念,进程在内存中布局和内容. 此外,还需要知道运行时是如何为动态数据结构(如链表和二叉树)分配额外内 ...
- UNIX高级环境编程(12)进程关联(Process Relationships)- 终端登录过程 ,进程组,Session
在前面的章节我们了解到,进程之间是有关联的: 每个进程都有一个父进程: 子进程退出时,父进程可以感知并且获取子进程的退出状态. 本章我们将了解: 进程组的更多细节: sessions的内容: logi ...
- UNIX高级环境编程(10)进程控制(Process Control)- 竞态条件,exec函数,解释器文件和system函数
本篇主要介绍一下几个内容: 竞态条件(race condition) exec系函数 解释器文件 1 竞态条件(Race Condition) 竞态条件:当多个进程共同操作一个数据,并且结果依赖 ...
- UNIX高级环境编程(9)进程控制(Process Control)- fork,vfork,僵尸进程,wait和waitpid
本章包含内容有: 创建新进程 程序执行(program execution) 进程终止(process termination) 进程的各种ID 1 进程标识符(Process Identifie ...
- UNIX高级环境编程(8)进程环境(Process Environment)- 进程的启动和退出、内存布局、环境变量列表
在学习进程控制相关知识之前,我们需要了解一个单进程的运行环境. 本章我们将了解一下的内容: 程序运行时,main函数是如何被调用的: 命令行参数是如何被传入到程序中的: 一个典型的内存布局是怎样的: ...
随机推荐
- 使用Unicode字符实现换行
要让inline元素换行可以使用Unicode字符实现: <!DOCTYPE html> <html lang="en"> <head> < ...
- 机器学习之scikit-learn库的使用
1.scikit-learn库简介 scikit-learn是一个整合了多种常用的机器学习算法的Python库,又简称skLearn.scikit-learn非常易于使用,为我们学习机器学习提供了一个 ...
- 我的Visual Studio必用工具
自己备用 代码生成工具:Resharper 代码颜色:supercharger 高亮单词 Word highlight with margin Productivity Power Tools 详细介 ...
- C# WebApi 返回JSON
在默认情况下,当我们新建一个webapi项目,会自动返回XML格式的数据,如果我们想返回JSON的数据,可以设置下面的三种方法. 1. 不用改配置文件,在Controller的方法中,直接返回Http ...
- AngularJS学习笔记(五)自定义指令(1)
先来说说自定义指令 ng通过内置指令的方式实现了对html的增强,同时也赋予了我们自定义指令的功能,让我们根据实际需求进行指令的定制.自定义指令涉及到模板(template).作用域(scope).数 ...
- C++中的 CONST 含义(从#define 到 CONST 的转变)
const 与define 两者都可以用来定义常量,但是const定义时,定义了常量的类型,所以更精确一些.#define只是简单的文本替换,除了可以定义常量外,还可以用来定义一些简单的函数,有点类似 ...
- [android] 手机卫士号码归属地查询
使用小米号码归属地数据库,有两张表data1和data2 先查询data1表,把手机号码截取前7位 select outkey from data1 where id=”前七位手机号” 再查询data ...
- RocketMQ NameServer
NameServer 路由管理,服务注册,服务发现.(类比为soa框架中的zookeeper) 一.路由管理 1.路由注册,由 Broker 向 NameServer 发送心跳,NameServer ...
- EF DataFirst修改数据类型
在做软件的时候我们可能会遇到这样的问题,就是在使用EF的时候,有时候精度不一样, 我们用整数来计算肯定是比浮点数来得快的,但我在MySQL里面存储的数据类型是decimal的,我生成EF后, 里面的数 ...
- linux_shell_数组
shell数组类似与C语言,数组下标由0开始编号.想要获取数组中的元素要利用下标. 1.首先定义数组 在shell中,用括号来表示数组,数组元素用“空格”符号分割开.列: name=("d& ...