文件系统和动静态库

这篇具有很好参考价值的文章主要介绍了文件系统和动静态库。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

再识文件属性

查看文件属性的原理

初识inode

了解磁盘

什么是磁盘

磁盘的结构

磁盘的存储结构

CHS寻址

磁盘的逻辑结构

使用LBA地址的意义

理解文件系统

页框和页帧

分治思想管理

Linux ext2文件系统

软硬链接

软链接

硬链接

文件的三个时间

动静态库

动静态库的基本原理

制作一个自己的静态库

生成静态库

使用静态库

制作一个自己的动态库

生成动态库

使用动态库

动静态库的加载


再识文件属性

查看文件属性的原理

ls -l读取存储在磁盘上的文件信息,然后显示出来:

文件系统和动静态库 

初识inode

//输入指令查看文件属性
ls -li

文件系统和动静态库

//输入指令stat 文件名,看到更多信息

文件系统和动静态库

上述结果中有几个文件属性需要我们理解(inode、Links等)

需要解释清楚它们,我们就需要了解清楚文件系统。

了解磁盘

在了解文件系统前,我们先了解最常见的存储介质,磁盘。

什么是磁盘

        磁盘是计算机的主要存储介质,它可以存储大量二进制数据,并防止断电后数据丢失。早期,计算机中使用软盘,但现在普遍使用硬盘。与之相对应的便是内存,内存有掉电易失性

磁盘的结构

 

文件系统和动静态库

注意点:

  1. 磁盘是我们计算机中的唯一的一个机械结构。

  2. 每个盘面都有一个磁头。

  3. 磁头和盘面是没有接触的,为了防止抖动。

磁盘的存储结构

文件系统和动静态库

 

我们将盘面进行划分:

文件系统和动静态库

注意点:

  • 扇区的面积会不同,但都代表512byte空间,通过控制存储信息的密度

文件系统和动静态库

 

注意点:

  • 磁头是共进退的。

CHS寻址

那么磁盘是如何寻址的呢?

  • 磁盘寻址的单位是扇区(512byte)

文件系统和动静态库

 

  • 磁头来回摆动用来定位在哪个磁道

  • 确定磁道后,盘片旋转时,磁头定位扇区

如何在磁盘中定位任何一个扇区呢?

  1. 先定位在哪一个磁道(柱面(Cylinder))。

  2. 再定位盘面(即对应的磁头(Head))。

  3. 最后定位在哪一个扇区(Sector)。

磁盘中定位任何一个扇区,采用的硬件的基本定位方式:CHS定位法

磁盘的逻辑结构

磁盘在物理上是圆形的,我们能在逻辑上将其抽象为一个数组。

文件系统和动静态库

 

此时,我们只要知道扇区对应的下标就定位了该扇区。(操作系统中我们称这种地址为LBA地址

LBA如何转化为CHS呢?

假设:磁盘有4个盘面,每个盘面有10个磁道,每个磁道中划分了100个扇区,此时共有4000个扇区,每一个盘面有1000个扇区。

我们如何定位123号扇区在磁盘中的位置:

  1. 123/1000 = 0号盘面 H

  2. 123/100 = 1号磁道 C

  3. 123%100 = 23号扇区 S

通过这样的计算,我们就拿到了对应的CHS。

使用LBA地址的意义

  • 便于进行管理,我们只需要有对应的下标就行了。

  • 让操作系统的代码和具体硬件解耦,如果使用CHS,存储就和磁盘绑定在了一起,我们并不想强耦合。

理解文件系统

页框和页帧

虽然磁盘的访问的基本单位是512字节,但其依然很小,操作系统内的文件系统让我们同时对多个扇区进行读取,一般以1KB(两个扇区),2KB(4个扇区),4KB为基本单位。无论一次读取和修改多小的数据都会一次加载4KB空间到内存。这也就是我们所说的局部性原理。

注意点:

  • 内存被划分成了4KB大小的空间,即我们所说的页框

  • 磁盘中的文件按照4KB大小划分好的块,即我们所说的页帧

文件系统和动静态库

 

分治思想管理

我们的磁盘常用的大小是500GB,那么如何管理这500GB的空间呢?

我们要进行分区、分组两个步骤:

文件系统和动静态库

        此时,我们只需要先将一个组管理好,然后就能通过CV(复制粘贴该组的管理方法到其他组)管理好这个分区了,能管理好当前分区自然也能管理好其他分区,最终我们就管理好了整个磁盘。

Linux ext2文件系统

磁盘文件系统图(内核内存映像肯定有所不同):

文件系统和动静态库

磁盘是典型的块设

​        硬盘分区被划分为一个个的block。一个block的大小是由格式化的时候确定的,并且不可以更改。例如mke2fs的-b选项可以设定block大小为1024、2048或4096字节。而上图中**启动块(Boot Block)的大小是确定的**。

1. Block Group:ext2文件系统会根据分区的大小划分为数个Block Group。而每个Block Group都有着相同的结构组成.
2. 超级块(Super Block):存放文件系统本身的结构信息。记录的信息主要有:bolck 和 inode的总量,未使用的block和inode的数量,一个block和inode的大小,最近一次挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间等其他文件系统的相关信息。Super Block的信息被破坏,可以说整个文件系统结构就被破坏了。
3. GDT,Group Descriptor Table:块组描述符,描述块组属性信息
4. 块位图(Block Bitmap):Block Bitmap中记录着Data Block中哪个数据块已经被占用,哪个数据块没有被占用。
5. inode位图(inode Bitmap):每个bit表示一个inode是否空闲可用。
6. i节点表(inode Table):存放文件属性。 如 文件大小,所有者,最近修改时间等(除了文件名)。
7. 数据区(Data Blocks):存放文件内容。

注意点:

1. inode为了彼此区分,每一个inode都有一个自己的ID。
2. 一个文件一个inode。
3. 文件名并不在inode中存储。
4. 查找一个文件,统一使用的是inode编号(文件名和inode存在映射关系)。
5. Super Block在每个组中都有一份,如果Super Block的信息被破坏可以通过其余的备份来恢复。

接下来回答一些问题:

inode中是如何存储文件内容对应的Block的位置的?

假设inode的结构如下:

struct inode
{
    int id;
    mode_t mode;
    uid;
    size;
    //......
    int blocks[15];//存储的对应的Block的位置    
}

        其中有着一个blocks数组用来存储对应的文件内容所在的位置,此时也许你会好奇,就15个位置能存的下吗?答案是能。前13个位置与inode是一一对应,但下标为13和14的位置采用的是二级检索和三级检索。

文件系统和动静态库

 

下标13对应的Block中存放的是其余Block的位置。下标14的同理(再套一层)。

创建的目录文件中存储的是什么呢?

 文件系统和动静态库

        我们可以看到,一个目录是有自己对应的inode的,那么目录文件内容中存储的是什么呢

答案是文件名和对应文件inode的映射关系

如何证明?

 

        一个目录内文件是否能删除取决于是否拥有对应的写权限!即我们需要取消对应文件名和inode的映射关系

文件系统和动静态库

为什么我们下载文件慢而删除文件快

我们都知道下载文件慢而删除文件快,其原理就在于:

  • 当我们下载文件时,首先我们要在inode位图中将对应的indoe由0置1,接着我们需要在数据区不断的申请Block,并将Block位图对应的位置由0置1,还需要在inode中存储其对应的位置。

  • 当我们删除文件时,很简单了,直接把inode位图和Block位图中对应的位置由1置0即可。

所以我们删除文件只是改掉了对应位图中的比特位,实际文件数据还是留在磁盘中的。

文件恢复是什么原理?

        系统日志中会存储删除掉的文件的inode,我们可以找到该inode,恢复其在inode位图中的位置,再通过inode找到文件对应的Block,恢复Block位图中对应的位置,由此,我们便成功恢复了文件。

所以我们误删文件想恢复时最好别瞎操作,避免对原有的数据进行了覆盖导致无法恢复。

软硬链接

软链接

ln -s 源文件所在路径 建立的链接文件名

文件系统和动静态库

 在上图中,我们建立了一个test的链接文件lktest,通过其,我们可以直接运行test.

ls -li //查看inode

文件系统和动静态库

 两者文件的inode不同,lktest是一个全新的文件,那么其内部存储的是什么呢?

文件系统和动静态库

        我们首先删除了test应用程序,我们发现软链接失效了,当我们再次在当前路径创建相同文件名的文件时,其又恢复了正常。由此观之,我们可以推断,其内部存储的是文件所在的路径

注意点:

  • 软链接文件大小很小,是因为其内部只是存储了文件的路径。

  • 我们可以将其看作为Windows的快捷方式

如何解除软链接?

unlink 文件名

文件系统和动静态库

 

硬链接

ln 文件所在路径 链接文件名

文件系统和动静态库

 我们创建了一个硬链接。

ls -li   //查看inode

文件系统和动静态库

 我们发现二者的inode竟然是相同的。并且其硬链接数变成了2.

文件系统和动静态库

删除test后,lktest依然能正常运行,硬连接数变为了1.

我们可以这样理解:

  • test和lktest的链接状态完全相同,他们被称为指向文件的硬链接。内核记录了这个连接数,inode 1054954 的硬连接数为2

  • 创建硬链接时,文件名lktest与文件test的inode建立了映射关系。

  • 我们在删除文件时干了两件事情:

    • 1.在目录中将对应的记录删除。

    • 2.将硬链接数-1,如果为0,则将对应的磁盘释放。

接着来看一个现象:

文件系统和动静态库

 为什么创建目录初始的硬链接数是2?

文件系统和动静态库

Test目录里的.文件也是硬链接。同理..是上一个目录的硬链接

操作系统不允许我们为目录创建硬链接

文件系统和动静态库 

        Linux系统中,磁盘上的文件和目录被组成一棵目录树,每个节点都是目录或文件。如果我们自己在目录c中建立了目录a的硬链接,就可能会在搜索文件时造成死循环的问题。因此操作系统不让我们进行该操作。

文件系统和动静态库

文件的三个时间

通过stat指令查看文件的三个时间:

文件系统和动静态库

 

下面解释一下文件的三个时间:

  • Access 最后访问时间

  • Modify 文件内容最后修改时间

  • Change 属性最后修改时间

注意点:

  • Access时间一般不会立刻更新,因为文件的访问可能十分频繁,操作系统内有自己的更新策略。

  • Modify时间更改时Change时间往往也会一起变化,因为我们更改文件内容时实际上就造成了文件属性的变化,如文件大小等。

动静态库

动静态库的基本原理

程序编译的四个阶段

  1. 预处理(进行宏替换):预处理功能主要包括宏定义,文件包含,条件编译,去注释等。生成XXX.i的文件

  2. 编译(生成汇编):要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,把代码翻译成汇编语言。生成XXX.s的文件

  3. 汇编(生成机器可识别代码):汇编阶段是把编译阶段生成的“.s”文件转成目标文件。生成XXX.o文件

  4. 连接(生成可执行文件或库文件):在成功编译之后,就进入了链接阶段。生成可执行程序。

库的本质:.o文件的集合

#include "mul.h"
#include "sub.h"
int main()
{
    int a = 5;
    int b = 3;
    printf("a*b = %d\n",mul(a,b));
    printf("a-b = %d\n",sub(a,b));
    return 0;
}

文件系统和动静态库

动静态库实际上就是把我们编译出的.o文件(方法的实现)进行了打包。再给出对应的.h文件(对应的方法)。

封装动静态库的标准格式:

我们把自己的库给别人用的时候,实际上需要给别人两个文件夹:

  • 一个文件夹下面放的是一堆头文件的集合。

  • 另一个文件夹下面放的是所有的库文件。

mkdir -p mylib/include      
mkdir -p mylib/lib
cp -f *.a mylib/lib
cp -f *.h mylib/include

我们创建一个目录文件mylib,再在里面分别创建一个lib目录(放库文件),一个include目录(放头文件)。

文件系统和动静态库

我们发布自己的库时只需要发布打包压缩好的mylib就可以了。

制作一个自己的静态库

生成静态库

需要用到命令:

生成静态库

ar -rc libmymath.a mul.o sub.o
  • ar(archive)是gnu归档工具,rc表示(replace and create)

文件系统和动静态库

 查看静态库中的目录列表

ar -tv libmymath.a

文件系统和动静态库

  • t:列出静态库中的文件

  • v:verbose 详细信息

进行打包:

mkdir -p mylib/include     
mkdir -p mylib/lib
cp -f *.a mylib/lib
cp -f *.h mylib/include

使用静态库

gcc -o main main.c -I./mylib/include -L./mylib/lib -lmymath

使用自己制作的库,我们编译时需要增加三个选项:

  1. -I:指定头文件所在的路径。

  2. -L:指定库文件所在的路径。

  3. -l: 指明使用的库的名称。

注意点:

  • 编译器并不清楚我们的头文件在哪里,其只会在当前路径和系统路径下寻找,因此我们需要添加路径。

  • 库文件同上。

  • 库的名称是什么?我们去掉前缀lib和后缀.a或者.so及其后面的版本号,就是库的名称。之所以要指定库的名称,是因为lib目录下可能有大量的库文件。

  • 上面的三个选项后可加空格,并不影响。

文件系统和动静态库

运行成功

使用自制的库每次编译都要带上这一串指令,显得十分繁琐,有何方法能简化呢?

把库文件和头文件拷贝到系统路径下

sudo cp mylib/include/*.h /usr/include
sudo cp mylib/lib/*.a /usr/lib64

我们把库文件和头文件拷贝到系统路径下的过程实际上就是安装了这个库

我们把库安装好后编译时还是需要指明库的名称,这也是为什么我们使用第三方库时总需要指明库名称的原因。

提示:我们并不推荐将自己写的库放进系统路径,因为我们的库并没有很好的经过验证,会对系统文件造成污染。

一个现象:

文件系统和动静态库

我们发现用自己的静态库编译的可执行程序居然显示是动态链接的。为什么?

  • 因为形成一个可执行程序,往往不会仅仅依赖一个库,我们的程序当然还依赖了c语言库。

  • gcc默认是动态链接的(建议行为)。

使用Makefile进行打包

我们可以用Makefile进行打包,方便我们后续的使用

libmymath.a: mul.o sub.o  //生成库
	ar -rc $@ $^
mul.o: mul.c
	gcc -c -o $@ $^
sub.o: sub.c
	gcc -c -o $@ $^

.PHONY:output       //包装库
output:
	mkdir -p mylib/include     
	mkdir -p mylib/lib
	cp -f *.a mylib/lib
	cp -f *.h mylib/include

.PHONY:clean   //删除
clean:
	rm -rf *.o libmymath.a mylib

文件系统和动静态库

我们就可以很轻松的进行操作了。

制作一个自己的动态库

生成动态库

生产动态库我们需要进行两步操作:

  1. //编译时添加fPIC选项
    gcc -fPIC -c -o mul.o mul.c
    gcc -fPIC -c -o sub.o sub.c
  2. gcc -shared -o libmymath.so *.o

注意点:

  • shared: 表示生成共享库格式

  • fPIC:产生位置无关码(position independent code) (让动态库中的指定函数的地址是偏移地址,相对编址方式)

  • 库名规则:libxxx.so

使用Makefile进行打包

 

libmymath.so: mul.o sub.o  //生成库
	gcc -shared -o $@ $^
mul.o: mul.c
	gcc -fPIC -c -o $@ $^
sub.o: sub.c
	gcc -fPIC -c -o $@ $^

.PHONY:output       //包装库
output:
	mkdir -p mylib/include     
	mkdir -p mylib/lib
	cp -f *.so mylib/lib
	cp -f *.h mylib/include

.PHONY:clean   //删除
clean:
	rm -rf *.o libmymath.so mylib

文件系统和动静态库

使用动态库

与静态库时的使用相同

gcc -o main main.c -I./mylib/include -L./mylib/lib -lmymath

文件系统和动静态库

但我们发现我们编译出的可执行程序无法运行,为何?

        我们使用-I-L-l这三个选项都是在编译期间告诉编译器我们使用的头文件和库文件在哪里,但是可执行程序生成后就与编译器没有关系了,操作系统运行可执行程序时可不知道动态库在哪里

我们通过ldd命令可以查看到:文件系统和动静态库

我们一般有四种方法解决该问题:

  • 拷贝.so文件到系统共享库路径下, 一般指/usr/lib64。

文件系统和动静态库

  •   更改 LD_LIBRARY_PATH。

文件系统和动静态库

LD_LIBRARY_PATH是环境变量,里面存储了运行动态查找库时所要搜索的路径。

我们使用export指令将我们库的路径导入其中即可

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:所在的路径

文件系统和动静态库

但此种方法在重启shell后环境变量会重置而失效(环境变量的配置文件)。

  • 配置/etc/ld.so.conf.d/

文件系统和动静态库

        我们可以看到该目录下都是后缀为.conf的配置文件,这些配置文件当中存放的都是路径。我们只需要用库文件的路径生成.conf的文件,然后拷贝到该目录下即可。拷贝后需要使用ldconfig指令更新配置后才会生效。

  • 在当前目录创建软连接

文件系统和动静态库

 我们可以在当前路径下建立一个与库文件同名的软连接,查找动态库时会默认在当前路径查找。

文件系统和动静态库

动静态库的加载

  • 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库

  • 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码

  • 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码。

  • 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking)。

  • 动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。文章来源地址https://www.toymoban.com/news/detail-427854.html

到了这里,关于文件系统和动静态库的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • windows执行完LoadLibrary()后,可以删除源动态库文件,函数不会锁库文件

    windows执行完LoadLibrary()后,可以删除源动态库文件,函数不会锁库文件。 运行结果:

    2024年02月13日
    浏览(42)
  • 【Linux基础】库文件

    (꒪ꇴ꒪ ),hello我是 祐言 博客主页:C语言基础,Linux基础,软件配置领域博主🌍 快上🚘,一起学习! 送给读者的一句鸡汤🤔: 集中起来的意志可以击穿顽石! 作者水平很有限,如果发现错误,可在评论区指正,感谢🙏 ​​         在Linux系统中,库文件(Library files)是一

    2024年02月16日
    浏览(52)
  • linux下头文件及库文件搜索路径知识汇总

    跟gcc相关的搜索目录: 安装gcc时,如果有指定prefix的话,那么系统的默认搜索路径为: C_INCLUDE_PATH:编译 C 程序的时候使用的环境变量 CPLUS_INCLUDE_PATH:编译 C++ 程序的时候使用的环境变量 CPATH:编译 C、 C++及Objective-C 程序时使用的环境变量 OBJC_INCLUDE_PATH:编译 Objective-C 程序

    2023年04月27日
    浏览(43)
  • C标准库文件&常用函数

    编号 头文件 C标准版本 介绍 1 assert.h C89/C90 条件编译宏,将参数与零比较 2 ctype.h C89/C90 用来确定包含于字符数据中的类型的函数 3 errno.h C89/C90 报告错误条件的宏 4 float.h C89/C90 浮点数类型的极限 5 limits.h C89/C90 基本类型的大小 6 locale.h C89/C90 本地化工具 7 math.h C89/C90 常用数据函

    2024年02月12日
    浏览(49)
  • 文件系统和动静态库

    目录 再识文件属性 查看文件属性的原理 初识inode 了解磁盘 什么是磁盘 磁盘的结构 磁盘的存储结构 CHS寻址 磁盘的逻辑结构 使用LBA地址的意义 理解文件系统 页框和页帧 分治思想管理 Linux ext2文件系统 软硬链接 软链接 硬链接 文件的三个时间 动静态库 动静态库的基本原理

    2024年02月01日
    浏览(34)
  • C++有哪些常用的库文件

    常用库文件: iostream:  输入输出流库,包含cin、cout、cerr等标准输入输出对象。 string : 字符串库,包含字符串类型std::string及相关操作函数。 vector : 动态数组库,包含vector类型及相关操作函数。 map:  字典库,包含map、multimap、set、multiset等关联容器类型及相关操作函数。 algorithm

    2024年02月02日
    浏览(46)
  • 7-LINUX--库文件的生成与使用

    库是一组预先编译好的方法的集合。Linux系统存储的库的位置一般在:/lib 和 /usr/lib。 在 64 位的系统上有些库也可能被存储在/usr/lib64 下。库的头文件一般会被存储在 /usr/include 下或其子目录下。 库有两种,一种是静态库,其命令规则为 libxxx.a,一种是共享库,其命令规则为

    2024年03月16日
    浏览(48)
  • openssl缺少libssl.so.1.1库文件

    这是由于openssl库的位置不正确造成的,一般出现在openssl源码升级场景下。 源码编译完成后,需要对libssl.so.1.1做一个软连接,从openssl源码安装目录/usr/local/openssl/lib/下面将编译好的libssl.so.1.1进行软连接。

    2024年01月21日
    浏览(49)
  • makefile 编译动态链接库使用(.so库文件)

    动态链接库:不会把代码编译到二进制文件中,而是在运行时才去加载, 好处是程序可以和库文件分离,可以分别发版,然后库文件可以被多处共享 动态链接库 动态:动态加载 链接:二进制文件和库文件分离。 库 库文件 .so 新建一个文件TestSo 编译一下 main.cpp 写好之后我们

    2024年01月23日
    浏览(47)
  • 第十二部分 使用 make 更新函数库文件

    目录 前言  一、函数库文件的成员 二、函数库成员的隐含规则 三、函数库文件的后缀规则 四、注意事项         函数库文件也就是对 Object 文件(程序编译的中间文件)的打包文件。在 Unix 下,一 般是由命令\\\"ar\\\"来完成打包工作。         一个函数库文件由多个文件

    2024年01月20日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包