本地网站建设软件,技术支持 广州骏域网站建设专家,做网站品,静态网站做新闻系统目录文件系统与动静态库的基本了解文件系统了解Access Modify Changeinode硬链接软链接静态库与动态库概念静态库的制作使用静态库动态库的制作使用动态库总结如何制作文件系统与动静态库的基本了解
文件系统
了解Access Modify Change
当文件没有被打开时#xff0c;他们存…
目录文件系统与动静态库的基本了解文件系统了解Access Modify Changeinode硬链接软链接静态库与动态库概念静态库的制作使用静态库动态库的制作使用动态库总结如何制作文件系统与动静态库的基本了解
文件系统
了解Access Modify Change
当文件没有被打开时他们存放在哪里呢是磁盘上面我们可以通过命令行上面输入ls -l(读取存储在磁盘上的文件信息然后显示出来) 或者 stat filename来查看文件信息ls命令已经很熟悉了我们这里来看看stat命令 这里我们来着重了解一下这三个时间
Access最近一次访问时间Modify最近一次修改时间–指文件内容Change最后一修改时间–指文件属性
我们经常使用的Makefile和make我们知道当我们不做修改时如果已经make过一次之后再次make就会报错说文件已经存在(虚拟依赖除外)那么操作系统到底为什么能够知道文件已经编译过不需要在编译了呢原因就在于Modify也就是修改时间如果一个文件刚刚编译形成了一个可执行程序那么形成的可执行程序它的修改时间一定比文件的修改时间要晚这样Makefile就可以根据两个文件的最近一次的修改时间来判断是否需要继续编译以下是例子
要注意虽然说Access是最近一次的访问时间可是linux内核版本在2.6左右往上这个访问时间都不会被立即刷新要有一定的时间间隔OS才会自动进行更新时间主要是因为访问这一操作比较频繁如果频繁的刷新会让系统变卡当我们修改文件内容的是时候大概率是会修改文件的属性的比如可能会更改文件的大小(文件大小也是属性)
inode
Linux上文件名在系统层面没有意义文件名是给我们用户用的Linux中真正标识一个文件是通过文件的inode编号来标识的当我们的文件没有被加载到内存中的时候它们就存储在磁盘上面磁盘中最小的存储单元是扇区(1扇区512Bytes)文件系统的最小存储单元是block(1Block4kb8扇区) 我们都知道磁盘上面有很多的扇形分区如果我们把扇形的分区抽象成长方形来看待我们就会得到这样一个图 Linux ext2文件系统上图为磁盘文件系统图内核内存映像肯定有所不同磁盘是典型的块设备硬盘分区被划分为一个个的block。一个block的大小是由格式化的时候确定的并且不可以更改。例如mke2fs的-b选项可以设定block大小为1024、2048或4096字节。而上图中启动块Boot Block的大小是确定的 Block Groupext2文件系统会根据分区的大小划分数个Block Group都有这相同的结构组成 超级块(Super Block)存放文件系统本身的结构信息。记录信息主要有block和inode的总量未使用的block和inode的数量一个Block和一个inode的大小最近一次的挂载的时间最近一次写入数据的时间最近一次检验磁盘的时间等其他文件系统的相关信息。Supper Block的信息被破坏就相当于整个文件系统结构就被破坏了 GDT(Group Descriptor Table)组描述符表。由很多组描述符组成整个分区分成多少个组就对应有多少个组描述符。每个组描述符Group Descriptor存储一个组的描述信息例如在这个组中从哪里开始是inode表从哪里开始是数据块空闲的inode和数据块还有多少个等等。 块位图(Block Bitmap)这里面记录着Data Block中哪个数据块被占用哪个数据块没被占用 inode位图(inode Bitmap)每个bit表示一个inode空间是否空闲可用 inode节点表(inode Table)存放文件属性如文件大小所有者最近修改时间等等 数据区(Data blocks)存放文件内容 将属性和文件数据分开存放实际上应该如何实现呢
我们以touch一个文件为例来看 创建文件主要有以下四个操作 存储属性 内核先找到空闲的inode节点(这里是1049849)内核把文件信息记录到其中 存储数据 该文件需要三个磁盘块内核找到了三个空闲块400600,800.将内核缓冲区的第一块数据复制到400接着是600依次类推 记录分配情况 文件内容按顺序400,600,800存放内核在inode上的磁盘分布记录了上述块列表 添加文件名到目录 新的文件名file.txt。Linux如何在当前文件目录中记录这个文件内核将入口(149849,file.txt)添加到目录文件文件名和inode之间的对应关系将文件名和文件内容及其属性连接起来 几个相关问题(仅是我的理解)
目录的本质是什么呢
本质可以理解为存放了文件名和对应的inode的链接关系的文件可以通过文件名去找到对应的inode从而可以通过inode table来查看文件的属性或者内容数据
删除的本质是什么呢
删除的本质其实就是把inode bitmap中的对应位置改为未被占用即可这也是有时候误删之后可以恢复的原理当如果误删掉一个文件之后如果自己不会恢复就尽量保持原样不要再进行多余的操作去找专业的人去解决因为保持刚删除后的样子能最大程度保证删除之后的数据块没有被覆盖这样恢复的可能会更大(也就是把inode和数据块之间重新建立链接) 硬链接
首先怎么使用硬链接在shell中的做法是ln 被链接的文件路径及文件名 文件名 我们看到真正找到磁盘上文件的并不是文件名而是inode。 其实在Linux中可以让多个文件名对应于同一个inode硬链接本质就不是一个独立的文件而是一个文件名和inode编号的映射关系因为它没有自己的inode
file1.txt和hard.txt的链接状态完全相同它们被称为指向文件的硬连接。内核记录了这个连接数inode是1053256硬连接数是2我们在删除文件时干了两件事 在目录中将对应的记录删除将硬连接数-1如果为0则将对应的磁盘释放 目录文件在创建时就有两个硬连接
软链接
用法与硬连接相同只是多了个-sln -s 要链接文件的路径以及文件名 文件名
软链接形成的是一个新的文件因为它具有自己的inode属性也有自己的数据块(保存的是指向文件的所在路径和文件名)如果被链接的文件被删除那么链接文件也会失效 静态库与动态库
概念
在Linux中如果是动态库库文件是以.so为后缀的静态库是以.a为后缀的在windows中动态库.dll静态库.lib
静态库.a程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库动态库.so程序在运行的时候才去链接动态库的代码多个程序共享使用库的代码。一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表而不是外部函数所在目标文件的整个机器码在可执行文件开始运行以前外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中这个过程称为动态链接dynamic linking动态库可以在多个程序间共享所以动态链接使得可执行文件更小节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用节省了内存和磁盘空间 ldd filename显示可执行程序依赖的库这里就是libc.so.6库名字就是c库库文件的命名libXXXX.so or libXXXX.a-…动静态库的名字是去掉lib前缀和.so-或者.a-后缀剩下的部分一般云服务器可能没有内置语言的静态库而只有动态库可以自己添加一下sudo yum install glibc -static 同样file命令也可以查看可执行程序是什么链接这里就是动态链接使用的是共享库 静态库的制作
首先我们我们先了解一下原理我们都知道一个文件想要到可执行需要以下几个步骤预处理编译汇编链接。其中汇编之后会形成一个.o下标的二进制文件并不可以被直接执行,叫可重定向目标文件(-c 是开始进行程序的编译完成汇编工作就停下)这个.o文件就是制作动静态库所需的文件因为其本身已经具有可执行的属性了只是没有被链接动静态库其实也就是打包这些.o文件并且附代上.h的头文件了解到这里我们开始进行一个简单的静态库的制作 制作静态库我们可以使用ar -rc打包静态库ar是gnu归档工具rc表示replace and create 查看已经制作完成的静态库:ar -tv查看打包内容 t:列出静态库中的文件 v:verbose 详细信息
举例 首先我们先创建四个文件文件内容如下 //add.h,add.c,sub.h,sub.c
//sub.h
#includestdio.h
extern int sub(int x,int y);
//sub.c
#includesub.h
int sub(int x,int y)
{return x-y;
}
//add.h
#includestdio.h
extern int add(int x, int y);
//add.c
#include add.h
int add(int x,int y)
{return x y;
}创建出Makefile文件 我们之前写的那些代码也都用了库(如c库)为什么没有指名这些选项呢—之前的库在系统的默认路径下:/lib64/usr/lib, /usr/include等等所以如果我们不想带这些选项我们可以直接把对应的库和头文件拷贝到默认路径下首先是可行的但是非常不推荐这样做这会污染库有时如果库的一些文件与拷贝文件重名还会覆盖掉原先的库一般软件安装的过程其实也就是上面的过程
这样就把静态库制作完成并打包了
使用静态库
我们制作好了静态库应该如何使用呢其实也就是链接的过程我们需要先写一段简单的代码
//因为头文件不在同一目录下所以需要指定一下路径
#include ./libs/add.h
#include ./libs/sub.h
int main()
{int x20;int y10;printf(add %d\n,add(x,y));printf(sub %d\n,sub(x,y));return 0;
}这样就可以去执行了因为静态链接的特性编译的时候会把静态库代码拷贝进我们所写的测试代码中去所以只要指定好路径编译形成可执行文件之后就可以直接运行了
动态库的制作
动态库的制作原理和静态库基本一致总的来说就是打包.o文件具体我们来看操作还是上面的例子 创建四个文件并写上相应的内容 //sub.h sub.c add.h add.c创建出Makefile文件 gcc -fPIC -c $产生.o目标文件程序内部的地址解决方案是与位位置无关库文件可以在内存的任何位置加载而且不影响和其他程序的关联性(-fPIC的作用)-shared就是形成一个动态链接的共享库
之后直接makemake libd即可形成动态库
使用动态库
在使用之前我们得先认识到一个东西文件编译形成可执行文件的是编译器而形成的可执行文件要运行需要的是加载器两者不是同一个东西
使用动态库同样需要写一个简单的代码
#include ./libd/add.h
#include ./libd/sub.h
int main()
{int x20;int y10;printf(add %d\n,add(x,y));printf(sub %d\n,sub(x,y));return 0;
}然后开始写Makefile内容与静态库的使用基本一致 静态库这样就直接可以运行了但是动态库不行这只是代表了编译能通过但是运行时会报错 这种情况的解决方法有很多种但是这里推荐一种使用LD_LIBRARY_PATH具体用法如下
export LD_LIBRARY_PATH 库所在的绝对路径为什么这里不需要指定库名(这里是dynamic)呢从ldd可以看出可执行文件已经知道所链接的库名了只是没有路径找不到这种方法需要每一次打开端口的时候都设置一次export只适用于当前登录退出之后所做的修改就清除了
还有其他的方法就是:
拷贝.so文件到系统共享库路径下一般指/usr/lib不过不推荐ldconfig 配置/etc/ld.so.conf.d/ldconfig更新 总结如何制作
所有的源代码都需要先被编译成为.o(可重定向目标文件)制作动静态库的本质就是将所有的.o打包(使用ar或者gcc来进行打包)交付头文件 -.a 或者 -.so 文件
gcc和g优先链接动态