linux用于存储物理文件的元数据,Linux那点事-文件系统

1. Linux文件系统

在Windows操作系统中,使用驱动器盘符(比如C盘),决定文件的路径名。每个驱动器都会有自己的目录结构,以便访问文件。

Linux的路径名不使用驱动器盘符。而是将文件存储在单个目录结构中,这个目录结构称为虚拟目录 virtual directory。虚拟目录将所有的文件目录纳入到单个目录结构中。

Linux虚拟目录结构只包含了一个称为根(Root)目录的基础目录。

注意:

Linux使用正斜线(/)而不是反斜线(\)在文件路径中划分目录。在Linux中,反斜线用来标识转义字符。

无论是window环境还是Linux环境,我们关注的还是java获取路径的方法。

Java获取文件路径:

public static void main(String[] args) throws IOException {

System.out.println("系统默认的分隔符:"+File.separator);

File emptyFile = new File("");

System.out.println("项目路径:"+System.getProperty("user.dir"));

//返回抽象路径名的绝对路径字符串

System.out.println("absolutePath路径为空时:"+emptyFile.getAbsolutePath());

System.out.println("canonicalPath路径为空时:"+emptyFile.getCanonicalPath());

System.out.println();

//路径是.或者..时候

File file1 = new File(".");

System.out.println("absolutePath路径为.时:"+file1.getAbsolutePath());

System.out.println("canonicalPath路径为.时:"+file1.getCanonicalPath());

System.out.println();

File file2 = new File("..");

System.out.println("absolutePath路径为..时:"+file2.getAbsolutePath());

System.out.println("canonicalPath路径为..时:"+file2.getCanonicalPath());

//路径是绝对路径时

System.out.println();

File absoluteFile = new File("/");

System.out.println("absolutePath路径为绝对路径时:"+absoluteFile.getAbsolutePath());

System.out.println("canonicalPath路径为绝对路径时:"+absoluteFile.getCanonicalPath());

}

执行结果:

df74422bdb92

获取路径的方法

在Linux中,会看到下面这种路径:

/home/Rich/Document/test.doc

这表明文件test.doc位于Document目录, Document又位于Rich目录之下,Rich则是在home路径之下的。路劲本身并没有提供任何有关文件究竟存放在哪个物理磁盘的信息。

1.2 Linux如何协调管理各个存储设备

Linux不使用驱动盘符,而是将文件存储在单个目录结构中,这个目录结构称为虚拟目录。而Linux第一块硬盘。即根驱动器,包含了虚拟目录的核心,其他目录都是在这构建的,可以挂载一些存储设备,我们称之为挂载点。

Linux会在根驱动器上创建一些特别的目录,我们称之为挂载点(mount point),挂载点是虚拟目录中用于分配额外存储设备的目录。虚拟目录会让文件和目录出现在这些挂载点目录中,然而实际上他们却存储在另外一个存储器中。

虚拟目录和挂载:

虚拟目录结构只包含一个称为根目录的基础目录。

Linux第一块硬盘是根驱动器,是虚拟目录的核心,其他目录都是在这挂载的。

Linux在根驱动器上创建一些特别的目录,就是挂载点。挂载点是虚拟目录下分配额外存储设备的目录。文件和目录存储在挂载点目录上,实际上却存储在另外的驱动器上。

访问一个路径时,会选择一个能最大匹配当前路径前缀的挂载点。比如说,有/var的挂载点,也有/var/run的挂载点的情况下,访问/var/run/test.pid,就会匹配到/var/run挂载点设备下面的/test.pid;

访问非挂载路径的时候,按照4中所说,其实就是访问最接近的一个挂载点,如果没有其他挂载点就访问根驱动器上的目录或者文件。

通过挂载点,程序不需要严格区分子目录和独立设备了。这样比如/usr可以是/的子目录,也可以是一个独立的分区,管理起来很灵活。

所谓挂载,就是可以通过文件系统来访问到你存储设备里面的东西。

通常系统文件会存储在根驱动器上,而用户文件则存储在另一驱动器中。

df74422bdb92

Linux文件结构

需要和windows的文件系统区分开来

不是所有逻辑上等的父子关系都必须是同一设备。。。

决定不同路径对应到不同设备的机制就叫做挂载mount。。

通过mouth,可以设置当前路径与设备的对应关系。

你把linux目录结构想象成一棵树,目录就是树枝,分区就是篮子,挂载就是把篮子挂在树枝上,这样你沿着树枝就能进到篮子里获取篮子里的内容。如果篮子没有被挂载到树枝上,你顺着树枝只能拿到一个“空”,也就是null。

1.3 常见的Linux目录结构

Linux文件系统是从Unix文件系统结构演进过来的。在Linux文件系统中,通用的目录名用于表示一些常见的功能。

df74422bdb92

虚拟目录和文件挂载

常见的目录名均基于文件系统层级标准(FHS)。很多Linux发行版都遵循了FHS。深入理解linux系统的目录结构(总结的非常详细)

常见的Linux顶级虚拟目录名及内容:

目录

用途

/

虚拟目录的根节点,通常不会存储文件

/bin

用于存放普通用户可执行的命令

/boot

用于存放Linux启动必需的文件

/dev

用于存放系统的设备信息

/etc

用于存放系统的各种配置

/home

用于存放系统各个普通用户的主目录

/lib

用于存放系统和应用程序共享库文件

/lost+found

文件损坏后找回的文件存放目录

/media

媒体目录,挂载光盘,U盘等文件系统目录

/misc

用来挂载NFS共享目录

/mnt

挂载目录,挂载其他硬盘分区系统的目录

/opt

可选目录,第三方软件包和数据文件

/root

root用户主目录,普通用户无法访问

/sbin

存放只有root用户才能运行的系统管理工具

/tmp

临时目录

/usr

用来存放供所有用户使用的各种应用程序和数据文件目录,该目录中也有对应的/bin、/lib、/etc等目录

/var

可变目录,用于存放系统中经常变化的文件

需要注意的是:我们在一般日常能经常访问的目录:/home、/mnt、/media、/usr

2. Linux文件系统层次

df74422bdb92

Linux文件系统

Application Process:用户层就是我们日常使用的各种程序,需要的接口主要是文件的创建,删除,打开,关闭,写,读。

Virtual File System VFS层: Linux系统分为用户态和内核态,用户态请求硬件需要调用system call通过内核态去实现。用户这些文件操作都有着对应的system call函数接口,接口调用VFS对应的函数。

文件系统层:不同的文件系统实现了VFS的这些函数,通过指针注册到VFS里面,所以,用户的操作通过VFS转到各种文件系统。文件系统把文件读写命令转化成对磁盘的LBA(寻址)操作,起到一个翻译和磁盘管理的作用。

Page Cache:文件系统底下有缓存,Page Cache,加速性能。对磁盘LBA的读写数据缓存到这里。

Block Device Driver 块设备区:用来访问磁盘LBA的层级,读写命令组合之后插入到命令列,磁盘驱动从队列读命令执行。

磁盘驱动层:磁盘的驱动程序把対LBA的读写命令转化为各自的协议,比如ATA命令,SCSI命令,或者是自己硬件可以识别的自定义命令,发送给磁盘控制器。

磁盘物理层:读写物理数据到磁盘介质。

2.1 Virtual File System(虚拟目录系统):

VFS并不是实际的文件系统。它只存在于内存中,不存在于任何外存空间,VFS在系统启动时创建,在系统关闭时被销毁。

VFS的作用:就是屏蔽各类文件系统的差异,给用户、应用程序、甚至Linux其他管理模块提供统一的接口集合。

VFS拥有关于各种特殊文件系统的公共界面,当某个进程发布一个面向文件系统调用时,内核将调用VFS中对应的函数,这个函数处理一些与物理结构无关的操作,并把它重定向为真实文件系统中相应的函数调用。后者处理那些与物理结构相关的操作。

df74422bdb92

VFS访问系统

用户层只能于VFS打交道,而不能直接访问实际文件系统,比如EXT2、EXT3、PROC。

换句话说,用户层不用也不能区别对待真正的文件系统。

不过SOCKET虽然也属于VFS的管筹范围,但是有其特殊性,就是不能像打开打开大部分系统的“文件”一样打开socket,它只能被创建,而且在内核中对其特殊性处理。

2.2 文件系统与工作原理

在Linux中文件系统的种类很多,主要是VFS做了一个软件抽象层,向上提供文件操作接口,向下提供标准接口供不同文件系统对接。下面以EXT4文件系统为例,讲解下文件系统结构与工作原理。

存储系统和inode

数据是保存在磁盘上的,磁盘上最小的存储数据是扇区,每个扇区一般都是可以存放512字节的数据。

那么如果数据大于521字节的时候,磁盘需要不停地移动磁头来寻找数据,一个文件很容易超过512字节,那么如果将多个扇区合并成一个块,那么磁盘就可以提高效率。磁头一次读取多个扇区就为一个块"block"(Linux上称为块,windows上称为簇)。

一个块多为4KB,因为块是文件系统上的概念,所以块也可以在格式化时候自行定义。

文件数据都存储在“块”中我们还必须找到一个地方存储文件的元信息,比如文件的创建者、文件的创建日期、文件的大小等等,这种存储文件元信息的区域就叫做inode(索引节点)。

每个分区都有自己的文件系统,也有一套属于自己的inode。

分析EXT4文件系统

df74422bdb92

EXT4文件系统

引导块:磁盘分区的第一个块,记录文件系统分区的一些信息,引导加载当前分区的程序和数据被保存在这个块中,一般占用2KB。

超级块:超级块用于存储一个已安装的文件系统全局配置参数(例如:块大小,总的块数和inode)和动态信息(例如:当前空闲块数和inode数),其处于文件系统开始位置的1K处,所占大小为1KB,为了系统的健壮性,最初每个块组都有超级块和组描述符表(GDT)一个拷贝,但是当文件很大时,这样浪费很多块(尤其是GDT占用的块多),后来采用了一种稀疏的方式存储这些拷贝,只有快组号是3,5,7的幂的块组才拷贝这个拷贝。通常情况下,只有主拷贝(第0块块组)的超级块信息被文件系统使用,其他拷贝在文件系统被破坏的情况下才使用。

2.1 块组描述符:GDT用于存储块组描述符,其占用一个或者多个数据块,具体取决于文件系统的大小。它主要包含块位图,inode位图和inode表位置,当前空闲块数,inode数以及使用的目录数。

2.2 块组:(管理系统文件的块、inode分配和管理的状态)每个块组包含一个块位图,一个inode位块图,一个或多个用于描述inode表和用于存储文件数据的数据块。除此之外,还有可能包含超级块和所有块组描述符(取决于块组号和文件系统创建时使用的参数)。

块位图: 用于描述该块组所管理的块的分配状态,如果某个块对应的位未置位,那么代表该块未分配,可以用于存储数据;否则,代表该块已经存储数据或者该块不能够使用。

Inode位图:用于描述该块组所管理的inode的分配状态。我们知道inode是用于描述文件的元数据,每个inode对应文件系统中唯一的一个号,如果inode位图中相应位置位,那么代表该inode已经分配出去,否则可以使用,由于其仅占一个块,因此这也限制了一个块组所能够使用的最大inode数量。

inode表:用于存储inode信息,占用一个或多个块(为了有效利用空间,多个inode存储在一个块中),其大小取决于文件系统创建时的参数,由于inode位图的限制,决定了其最大所占用的空间。

以上这几个构成了元素所在磁盘块成为文件系统的元数据块,剩余的部分则用来存储真正的文件内容,称为数据块

block是实际文件的内容,如果文件大于一个块的时候,将占用多个block,但是一个块只能存放一个文件(因为数据是由inode指向的,如果两个文件数据存放在一个块里,就不能指定)

2.3 操作系统读取文件

df74422bdb92

操作系统读取文件

大体过程:

在读取一个文件时,总是从根目录(/)开始读取,每一个目录或者文件,在VFS中,都是一个文件对象,每个文件对象都有唯一的一个inode与之对应。

读取到第一个inode就是根目录,读取到了该目录后,内核对象就会为该对象建立一个目录项对象(dentry),并将其缓存起来,方便下一次读取时直接从内存中取。

目录本身也是一个文件,目录文件的内容即是该目录下的文件的名字与inode号,目录文件的内容就像一张表,记录的文件名和其inode之间的映射关系。根据路径即可找到当前需要读取的下一级文件的名字和inode。同时继续为该文件建立dentry。

dentry结构是一种含有指向父节点和子节点指针的双向结构,多个这样双向结构构成了一个内存里面的树状结构,也就是文件系统的目录结构在内存中的缓存。

一个文件只有一个inode节点存放它的属性信息,那么如果是一个大文件,那么他的block一定是多个,且可能是不连续的,那么inode怎么表示呢?

df74422bdb92

大文件的inode

如果文件内容太大,对应数据库数量过多,inode节点本身提供的存储空间不够,会使用其他间接数据块存储数据块位置信息,最多可以有三级寻址地址。

1、文件拷贝、剪切的底层过程是怎样的?

2、软连接和硬连接分别是如何实现的?

复制文件:创建一个新的inode节点,并拷贝数据块的内容

df74422bdb92

cp复制

移动文件:同一个分区里面移动文件(mv),inode节点不变,只是更新目录文件对应数据块里面的文件名和inode对应关系。跨分区,需要创建新的inode,因为inode节点不同分区是不能共享的。

df74422bdb92

A重命名之后inode

df74422bdb92

同一个分区的inode号不变

软连接:创建软连接会创建一个新的inode节点,其对应的数据块内容存储所链接的文件名信息,这样源文件即便删除了,重新建立一个同名的文件,软连接依然能够生效。

df74422bdb92

软连接

硬连接:创建硬连接,并不会新建inode节点,只是links加一,然后在目录文件对应的数据块上增减一条文件名和inode对应的关系记录。只有将硬链接和原文件都删除之后,文件才会真正的删除,即links为0才是真正的删除。

推荐阅读以及参考:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值