操作系统 - 文件系统
Linux文件系统的层次
- General Block Device Layer: 隐藏不同硬件设备的细节,为内核提供统一的IO操作接口。这样无论什么样的硬盘和驱动,他们所提供的IO接口都没区别,被一视同仁看做块设备来处理。
- 文件系统: 大多Linux发行版本默认使用的是ext4。 内核支持的文件系统可以通过内核目录树
fs
目录中的内容来查看。 - VFS: 不管是什么文件系统,用户都只关心mount/umount, open/close等操作,所以,VFS就把不同的文件系统做一个抽象,提供统一的API访问接口,VFS提供的统一API经过系统调用封装一下,用户空间的应用就可以通过系统调用来操作不同的文件系统。Linux所有文件都建立在虚拟文件系统(Virtual File System VFS)之上。Linux支持每个目录用不同的文件系统,而文件也可能是指磁盘,内存,网卡,输入输出设备等 。
Linux : 一切皆文件
将一个文件系统映射到某个目录的过程叫做挂载(Mount),可以使用mount -l
查看已经挂载的文件系统。
sysfs``proc``devtmpfs``tmpfs``ext4
都是不同的文件系统
sysfs
让用户通过文件访问和设置设备驱动信息。proc
是一个虚拟文件系统,让用户可以通过文件访问内核中的进程信息。devtmpfs
在内存中创造设备文件节点。tmpfs
用内存模拟磁盘文件。ext4
是一个通常意义上我们认为的文件系统,也是管理磁盘上文件用的系统。
文件系统的结构
文件系统的四个重要组成部分:目录(directory), 索引(index structure), 存储块(storage blocks)和free space map。
当我们在应用中执行open
命令,打开一个文件,其实是做了一个命名翻译(Name Translation)将,文件路径名翻译成了一个file number(file descriptor), 通过这个file number来找到真实存在于磁盘块上的数据。如下图:
directory
directory是一个包含<file_name: file_number>映射的文件;其中file_number可以是一个文件或者另外一个directory。每一个<file_name: file_bumber>映射被叫做一个directory entry(dentry)。
In-Memory File System Structure如下图
Index Structure
我们有了directory,就有了可以从文件路径到file_number的映射。然而我们的真实数据是存放在磁盘上的,那么就需要一个结构去维护file_number到磁盘块(block)的关系,也就是我们所说的Index Structure。
Case Study FAT
一个类似链表的结构,文件1从块5开始,5->2->9->14->15->-1,-1代表结束,这就是文件1在磁盘块的位置。FAT通过一个链表就解决了文件和物理磁盘块的映射,简单实用。FAT的缺点是非常占有内存,1 T的硬盘,如果块大小是1 K, 需要1 G个FAT条目,占用2-3 G内存空间。
目录结构
/bin : 包含很多用户可以访问的可执行文件,如ls,cp,cd等
/dev : 通常挂载在devtmpfs文件系统上,存放设备文件节点
/etc : 配置文件
/proc : 进程和内核文件
/sbin: 系统二进制文件,系统启动必须的指令
/tmp :临时文件,通常使用tmpfs文件系统,系统重启时会清除/tmp
/var : 可变数据文件, 比如日志通常会放在/var/log
下,/var
下的文件会长期保存
/boot : 存放Linux内核文件和启动镜像。
/opt : 可选软件,通常第三方软件安装在这个目录
/root : 用户家目录
/home: 用户个人数据
/media :自动挂载的设备,比如插入U盘
/svr :服务数据
/usr:(Unix System Resource), vim
编辑器的可执行文件通常放在/usr/bin
下,/usr/lib
目录存放系统的库文件,比如一些重要对象的动态链接库文件,/usr/share
目录下存放文档,比如man的文档
目录遍历
硬盘分块
为了提高性能,会把磁盘分为一个个小块(Block e.g. 4 kb)
Hard Link vs Soft(Symblic) Link
Inode
Inode 即Index node 是索引节点的意思,每个文件都有一个inode, 里面保存着文件的元数据(meta data), 是文件或者目录在文件系统中的唯一标识。
Inode包含的元数据包括:文件类型,访问权限,大小,时间相关信息,硬链接计数,指向数据块指针数组等。以下是inode结构:
struct m_inode {
unsigned short i_mode;/*文件类型和属性,ls查看的结果,比如drwx------*/
unsigned short i_uid;/*文件宿主id*/
unsigned long i_size;
unsigned long i_mtime;/*文件内容上一次变动的时间*/
unsigned char i_gid;/*groupid:宿主所在的组id*/
unsigned char i_nlinks; /*链接数:有多少个其他的文件夹链接到这里*/
unsigned short i_zone[9];/*文件映射的逻辑块号*/
/* these are in memory also */
struct task_struct * i_wait;/*等待该inode节点的进程队列*/
unsigned long i_atime;/*文件上一次打开的时间*/
unsigned long i_ctime;/*文件的inode上一次变动的时间*/
unsigned short i_dev;/*设备号*/
unsigned short i_num;
/* 多少个进程在使用这个inode*/
unsigned short i_count;
unsigned char i_lock;/*互斥锁*/
unsigned char i_dirt;
unsigned char i_pipe;
unsigned char i_mount;
unsigned char i_seek;
/*
数据是否是最新的,或者说有效的,
update代表数据的有效性,dirt代表文件是否需要回写,
比如写入文件的时候,a进程写入的时候,dirt是1,因为需要回写到硬盘,
但是数据是最新的,update是1,这时候b进程读取这个文件的时候,可以从
缓存里直接读取。
*/
unsigned char i_update;
};
查看文件的inode
查看一个文件的 inode,可以用 stat
命令,或者 ls -i
选项来查看。下面分别用这两个命令来查看一个文件 myfile.txt 的 inode 号为 102171635
和元数据对应的就是用户数据(user data),或者也叫做文件数据块(data block), 存放的是文件的真实内容。我们通过文件名可以查到它的inode, 再通过inode查看文件内容。 如下图:
硬链接
当多个文件名指向同一个inode时,这种链接就被叫做硬链接, 如下图,我们为原始文件myfile.txt创建了两个链接,都指向同一个inode。硬链接的作用:
- 节省服务器的磁盘空间
- 防止误删,因为inode会有硬链接的计数,只有硬链接等于0的时候,才会把文件内容的数据块删除
创建硬链接
可以用ln [option] [src file] [link file]
来创建,注意硬链接只能对已存在的文件进行创建,并且不能够跨文件系统。
软链接
软链接也被叫做符号链接(symbolic link)。linux中的软链接和Windows中的快捷方式非常相似,软链接的inode和原文件不同,软链接inode指向的数据块存储的是源文件的路径。如下图。软链接的作用:
- 方便文件管理,比如原文件路径比较复杂,可以在简单的路径下创建软链接便于访问。
但一旦源文件被删除了,软链接就成了一个死链接,指向一个不存在的文件。
创建软链接
软链接可以用命令 ln -s [源文件名或目录] [软链接文件名]
来进行创建。和硬链接不同之处在于,对不存在的文件也可以创建软链接,可以跨文件系统,对文件或者目录都可以创建软链接。
硬链接软链接区别比较
Linux下删除文件
unlink函数
对于硬链接来说,unlink来删除目录项会把inode的硬链接计数减一,直到inode引用计数为0时,才会真正删除文件(操作系统决定何时真正删除磁盘块上的文件);
对于软链接来说,unlink直接删除软链接,对源文件没有任何副作用。
删除文件
大家都很熟悉的rm -rf
命令,用来删除文件。但是执行该操作不一定真的把文件删除掉了。在删除文件时,系统有两个变量来控制,一个是i_link代表文件硬链接数量,一个是i_count代表文件的引用计数,删除文件的前提是i_link和i_count都为0。在磁盘中的文件,只需要让i_link=0就可以把文件删除了,即你找不到这个文件了。但如果这个文件正在被程序打开,还需要把运行的程序给kill掉,或者让它释放这个文件,使i_count=0才可以达到删除文件的目的。
真正地删除文件
假设你一不小心把非常重要的数据删除掉了,这将意味着你的数据就永远也找不回来了,从而造成无法挽回的损失了,由此可见数据的重要性,因此操作系统不会轻易把数据从磁盘中真正的删除掉。
实际上所谓的右键删除操作只是把文件的inode索引号与磁盘中的block的关联断开了而已,但文件的数据并没有真正的被删除掉。如果你想真的删除数据的话,要么把磁盘格式化,要么把原先的数据删除掉,然后写入新的数据覆盖掉,当然,你也可以选择格式化和数据覆盖双重保险,这个时候你的数据想要恢复基本上是非常困难的,即便可以顶多只能恢复一部分数据了吧。
参考资料:
https://www.cnblogs.com/jfzhu/p/12945358.html
https://cloud.tencent.com/developer/article/1725964
https://blog.csdn.net/yuexiaxiaoxi27172319/article/details/45241923