文件操作的底层原理(inode与软硬链接)
@[toc]
零.前言
上一节中我们学习了当文件已经加载到内存中的操作,那么操作系统是如何在磁盘中寻找文件并加载到内存中的呢?本节将讲述这一内容。
一、磁盘
要了解文件在没有打开的时候的存储情况,我们就需要了解存储它的硬件:磁盘。
在计算机中磁盘属于外设范畴,它是计算机内部的一个机械设备。
磁盘分为机械磁盘和固态磁盘,目前的笔记本上基本都装载的是固态磁盘。
磁盘的基本单位是扇区,每一个扇区大概存储512k的数据量。
但是我们理解磁盘时要把它想象成条形结构来理解。就是将圆形磁盘看成矩形。
同时,我们又对这个长条形的磁盘分为不同大小的区域,就是所谓的C盘,D盘,E盘。
大部分计算机是只有一个磁盘的,只是将其分为不同的区域。
同时,由于每一个盘的空间较大,因此我们需要继续划分管理。
我们将D盘分为很多个组来进行管理,它的组头有一个BootBlock这是和启动有关的。
而每一个组我们还要进行划分管理,我们:
其中SuperBlock是与文件结构相关的和GroupDescriptorTable是与组相关的。不过这两个都不是本文的重点。
本文的重点在于理解BlockBitmap,inodeBitmap,inodeTable和DataBlocks。
二、文件属性与数据的存储
1.inodeTable与Datablocks
当我们存储一个文件的时候,我们不仅要存储它的属性信息还要存储它的数据信息。其中InodeTable与Datablocks分别存放的就是文件的属性信息和数据信息。
在InodeTable中有很多小块,每一个小块就是一个inode。它存放的是一个文件的属性信息。
在Datablocks中和inodeTable是类似的,它包含很多block单元,每一个block单元存储一定大小的信息:
操作系统在寻找文件时是使用inode编号来进行查找的,而不是通过文件名,文件名是用户层才进行使用的。Linux系统真正标识一个文件,是通过inode编号。每一个文件都有一个inode编号。同时在inode中还会存放文件相对应的block块中的编号。
如果是目录文件,它存放在DataBlock中的内容是目录中的文件名与inode的映射关系。
2.InodeBitmap与BlockBitmap
InodeBitmap和BlockBitmap存放的是,InodeTable和DataBlocks的位图。其中比特位的位置表示的是编号,比特位的内容表示的是是否被占用。
比如:在InodeBitmap中的数字为0000 1010,表示的就是0号位的inode没有被占用,而1号位的inode已经被占用了。
Blockmap同理。
3.举例
我们通过举一个例子来理解以上的内容:
mkdir tmp
cd tmp
touch hello.c
echo "hello bit" >hello.c
cat hello.c
rm hello.c
touch hello.c:在InodeBitmap中找到没有被占用的inode单元,把属性的信息存放进去。
echo “hello bit”>hello.c:查看BlockBitp中没有使用的block单元,将其余inode建立映射,并将文件的内容存放进去。
cat hello.c:通过tmp的inode找到并查看tmp的Datablock,找到与hello.c文件名形成映射关系的inode值,通过这个inode找到对应的hello.c文件的Datablock,从而打印其中的内容。
rm hello.c:在tmp的DataBlock找到与文件名hello.c相对应的inode,只需要将inodeBitmap中的该inode位置的数字由1置为0即可。不需要对其的inodeTable与DataBlock进行操作。
这也就是为什么文件的删除非常的快,因为没有删除属性和数据,只是将是否有效删掉了。而对比于windows系统的回收站,其实在回收站中的文件并没有被删除掉,仅仅只是被换了一个目录而已。当我们不小心删除了文件,最好的做法就是什么都不做,避免内容被覆盖掉。
同理,mv指令其实只是在移动文件名与inode的映射关系。
三、软硬链接
在Linux系统下的软硬链接,我们可以理解为快捷方式。
使用ln选项来创建软硬链接:
ln -s//创建软链接
ln //创建硬链接
这里我们就创建了一个关于log.txt的软链接log_s。
创建一个硬链接log_h。
如果是软链接,软链接的inode和文件的inode是不同的。说明软链接新建了一个文件,它有自己的属性信息和数据块(保存的是所指文件的路径+文件名)。而硬链接的inode和原来文件的inode是相同的,说明硬链接并没有创建文件,而是增加了目录DataBlock中文件名和inode的对应关系。
前一个红色框表示的是硬链接的个数,当我们创建硬链接时,硬链接和该文件都变成了2。当该值为0的时候表示文件被删除。
当我们创建文件的时候,该值为1,但是当我们创建一个目录的时候,该值为2。
这是因为test目录下的.也是该目录的一个硬链接。当在该目录下再创建一个目录时,值为3,这是因为该目录下的…也表示test目录。
四、文件的时间属性
我们可以通过stat来查看文件的基本属性,比如我们新建一个file.txt。并向其中写入一定的内容。
stat file.txt
其中access,modify,change表示的就是文件的三个时间属性.
1.Access
Access表示的是文件的最近一次被访问时间,但是我们通过cat指令访问文件发现,文件的access时间并没有发生变化。
这是因为打开文件是一个高频操作,为避免大量重复刷新,在较新的Linux内核中,Access不会立即被刷新,而是有一定的时间间隔OS才会自动更新时间。
2.Modify
Modify表示的是最近一次的修改时间,时间被实时更新。
echo “hello bit”>>file.txt
3.change
最近一次修改文件属性的时间:
chomd u+x file.txt
注意,当修改文件属性的时候,Modify没有发生变化。但是当修改文件内容的时候,change有可能会发生变化。这是因为修改文件内容一般都会修改文件属性,比如增加内容就会修改文件的大小属性。
4.Makefile判断文件更新的方式
mytest:test.c
gcc $^ -o $@
.PHONY:clean
clean:
rm mytest
其中test.c为mytest所依赖的源文件。当Makefile进行make的时候,会检查mytest和test.c的Modify时间,正常来说肯定是test.c的Modify时间比mytest的更早(因为mytest是由test.c进行生成的)。如果我们更改了test.c中的内容,那么test.c的Modify时间就会比mytest的晚,此时Makefile会执行相应的依赖方法。
我们还可以验证一下:在没改test.c的情况下进行touch(touch一个存在的文件表示修改时间),此时就可以进行make了。
五、总结
我们使用整个文件的创建,使用以及删除来对文件操作进行总结。
1.touch file.txt
建立文件,首先操作系统在InodeBitmap和BlockBitmap分别找到不为1的数字,将其下标作为该文件的Inode和block的编号。并将之置为1,其中Inode只有一个,block可以有多个。
2.echo “I am the king of Asgard”>>file.txt
将调用echo进程,先将标准输出关闭(close(1))在该进程中将file.txt文件使用系统调用函数open打开,
首先通过目录文件的Blocktable,找到file.txt与inode的映射。然后通过该映射找到file.txt这个文件以及它的内容,并加载到内存中,形成file结构体成为该进程的一个文件。
file.txt获得一个文件描述符,存放在该进程的files结构体中,该文件描述符就是原来标准输出的文件描述符:1。
进程通过打印函数向文件描述符为1的文件中打印内容,此时就是在向file.txt中打印内容。
3.rm file.txt
将InodeBitmap中表示file.txt文件的的数字1置为0。
- 点赞
- 收藏
- 关注作者
评论(0)