通过ls的-i选项可以看到显示的文件属性最前面多了一列数字(两两不重复),它们就是文件的inode编号。
磁盘文件是由文件内容和文件属性(也叫元信息)构成的,例如ls -l显示的就是文件的属性,cat命令显示的就是文件的内容。
Linux下将文件内容和文件属性进行分离存储,保存文件属性的结构就是inode,也就是说inode是一个文件的属性集合;文件内容则保存在磁盘的block中。
Linux中每一个文件都有一个inode,这样就会存在大量的inode,为了区分它们,使用inode编号。
磁盘几乎是计算机内唯一一个机械设备(这也注定了它的效率比较低),在冯诺依曼体系中可以充当输入设备、输出设备,它一般是永久性存储设备。
硬盘的空间一般很大,所以如何管理就是个问题,下面的图大致介绍一下硬盘的管理方式。
(可以类比一个国家先按省管理,每个省之下又按市管理)
以 创建一个test.c并写入1kb内容 为例说明文件的创建过程:
先遍历inode Bitmap找到值为0的inode并置为1,并将该inode、文件的信息填入inode Table,由于暂时是个空文件,不需要使用Data blocks内的块来保存文件的内容。写入时,先在Block Bitmap中找到一个为0的位,然后将该位的值置为1,并在其对应的块中写入内容。
那么删除过程呢?只需要找到对应的inode然后找到inode Table,在其中可以找到文件使用的块,把inode和使用的块在两个位图中的值置为0即可,如果之后需要别的文件写入,直接覆盖原来的内容即可。(显然删除过程很简单且没有删掉文件的内容,所以删除文件速度很快、且可以恢复)
目录本身也是一个文件,它也有自己的各种信息。创建目录的过程与创建文件的过程大致相同。
与创建文件不同的是,目录的内容是当前目录下各个文件的文件名和对应的inode指针(不准确地说,可以理解为inode号)。
所以说文件名并不是在该文件的inode中保存,而是保存在它所在的目录文件的内容中;而目录中的内容保存的是文件名和inode号间的对应关系。(事实上,系统寻找文件只看inode号,之所以要保存文件名是便于用户查看)
由上图可以看出,file的内容保存的是其下的文件名和inode编号的对应关系。
了解了目录后,可以知道上面创建文件的大致过程最后少了一步,就是需要将文件名和inode的映射关系添加到目录文件的内容中。
下面重要的内容主要都放在图片内,请仔细阅读图中的文字。
通过ln -s来创建软链接,注意后面两个文件的顺序。
//test.c中的内容
#include
int main()
{
printf("hello link\n");
return 0;
}
通过ln来创建硬链接(不带任何选项)。
那么创建硬链接有什么用处?
下面删除掉test文件,显然软链接的箭头后方在提示test不存在,但此时硬链接仍然可以正常运行,但是软链接无法再运行。
还有一个系统常见的使用硬链接的地方,就是在一个目录创建时默认生成的.(代表当前目录)和…(代表上级目录)。
Access是最后访问的时间、Modify是文件内容最后修改的时间、Change是文件属性最后修改的时间
动静态库实际上是一个可执行程序的“半成品”。.c源文件经过编译形成.o文件,库的本质是许多.o后缀文件的集合,它们是一个个方法(函数)的二进制文件。
在test.c中写入下列代码:
#include
int main()
{
printf("hello world\n");
return 0;
}
查看/lib64/libc.so.6文件的具体信息如下,发现它正是一个软链接的文件。
再看这个libc-2.17.so的位置,并查看这个文件,发现他就是个object(.o)文件
Linux下以.so结尾的库是动态库,以.a结尾的是静态库。(在Windows下以.dll结尾的库是动态库,以.lib结尾的是静态库)
gcc编译时默认是链接动态库、release版本,如果想要链接静态库可以加-static选项。
静态加载时,把用到的整个库都加载到可执行程序中,这就导致单个的可执行程序很大,上图静态加载的test显然比动态加载的大得多。而且如果多个静态加载的文件都调用同一个库,那么内存中就会有大量冗余的代码,非常浪费空间。
但是由于可执行程序中已经包含了库的代码,所以可以独立运行。
动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库代码被用到该库的所有进程共享,这样节省了内存和磁盘空间。
动态加载产生的可执行文件依赖库,如果没有库就无法运行。