文件系统
- 磁盘
 - 磁盘的物理结构
 - 磁盘的存储结构
 - 磁盘的逻辑抽象结构
 - 对磁盘组进行管理
 
- 创建和删除文件时,`os`做了什么?
 - 创建一个文件时,`os`做了什么?
 - 删除一个文件,`os`做了什么?
 
- 制作软硬链接
 - 软连接和硬链接区别
 
- 制作静、动态库
 - 使用动静态库
 - 使用静态库
 - 使用动态库
 
磁盘
文件打开后,会加载到内存中,那么没有又打开的文件在哪里呢?
大量的文件,就在磁盘上
磁盘的物理结构
![]()
磁盘中有若干个光盘,磁头,在光盘中间有一个马达,每一个磁盘面都有一个磁头,我们的文件数据就在磁盘面上存储,访问磁盘上的文件,就是通过马达的旋转,和磁头的摆动进行寻址
磁盘的存储结构
在一个磁盘面上有若干个磁道,一个磁道有若干个扇区,数据就是存储在一个个扇区中,每一个扇区的存储容量为512字节
读写磁盘时,磁头找的是某一个面的某一磁道的某一个扇区,就能找到文件对应的数据
磁盘的基本单位是一个扇区,但我们访问以8个扇面(
4kb)访问
磁盘的逻辑抽象结构
对磁盘进行管理,就是要先描述后组织,那么我们把磁盘上每一个扇面抽象成数组的一个单元,因为一般是以8个扇面来访问的,所以我们把磁盘抽象成数组,每一个单元大小是
4kb
我们管理磁盘时,要对磁盘进行分区,在对每一个分区进行分组,分而治之,管理每一个磁盘组
对磁盘组进行管理
上图是一个磁盘的一个分区,Block group是这个分区的一个磁盘组
在
linux中文件的属性和数据是分开存储的
Data blocks:存储文件的数据(以块为单位(一个单位容量为4kb),存储文件的数据,一个文件可能使用多个块)
Block Bitmap:通过位图标识Data bLocks每一个块的使用情况比如:00001001 表示 第0个块,第3个块已被使用
inode Table:以128字节为单位,存储的是文件的属性,也是数组的形式,每一个块存储一个文件的文件属性(每个文件属性中都有一个inode来标识文件的唯一性(inode在分区内唯一))
inode Bitmap:inode Table块的使用情况
Group Descriptor Table:有多少inode,起始的inode编号,有多少个inode被使用,有多少block被使用,还剩多少
SB(super block):文件系统的等层数据结构,存储这个分区的相关属性(在多个磁盘组中都有,为了恢复数据使用)一个文件只有一个
inode,但是一个文件可能使用多个数据块,如何标识那些数据块属于这一个文件?在
inode Table中每一个块,存储一个文件的属性,在一个块中有一个数组block[15]:在这个数组的[0,11]中直接保存存放该文件数据的数据块的编号,在[12,15]中也指向数据块,但是这个数据块中不存储该文件的数据,而是存储该文件对应的其他存储该文件数据的数据块编号(一级索引)
创建和删除文件时,os做了什么?
 
首先,我们需要知道,目录也是文件,文件=内容+属性,目录文件的
inode就存储目录的属性,而目录的数据块存储的是在该目录下的文件和inode编号的映射关系(linux标识文件是通过inode编号,而不是通过文件名)
创建一个文件时,os做了什么?
 
创建文件时,首先会在
inode bitmap中寻找为0的inode编号,将它置为1,在inode Table中找到对应的inode,把文件的属性写入,为该文件分配数据块,建立inode和Data blocks的映射关系,将block bitmap中对应的标志位置为1,我们会得到文件的inode编号,找到自己所处的目录,根据目录的inode找到目录的数据块,将文件名和inode编号映射关系写入到目录的数据块中。
删除一个文件,os做了什么?
 
通过文件名在该目录的数据块中查找文件名和
inode编号的映射关系,得到inode编号将inode Bitmap中该inode编号对应置为0,将block Bitmap中该文件对应的数据块置为0。
制作软硬链接

软连接和硬链接区别
由上图可知,软链接是一个独立的文件,
inode编号不同(就相当于电脑桌面快捷方式,软链接文件中存放这个文件所在路径),而硬链接就是在目录下,给指定文件添加inode和文件名的映射关系删除软硬连接使用
unlink
这个数表示的就是文件的硬链接数,就是有多少个文件和这个
inode映射
为什么创建一个普通文件的硬链接数是1,而一个目录文件的硬链接数是2
如上图,在test中的
.表示当前路径,映射test目录的inode,该inode就映射两个文件,
制作静、动态库
静态库(.a)
动态库(.so)
.PHONY:all all: libmythod.a libmythod.so libmythod.a:add.o hello.o ar -rc libmythod.a add.o hello.o //生成静态库 add.o:myadd.c gcc -c myadd.c -o add.o hello.o:myhello.c gcc -c myhello.c -o hello.o libmythod.so:add_s.o hello_s.o gcc -shared -o libmythod.so add_s.o hello_s.o //生成动态库 add_s.o:myadd.c gcc -fPIC -c myadd.c -o add_s.o //-fPIC 生成与地址无关的.o文件 hello_s.o:myhello.c gcc -fPIC -c myhello.c -o hello_s.o .PHONY:lib lib: mkdir -p lib-static/include mkdir -p lib-static/lib cp *.h lib-static/include cp *.a lib-static/lib mkdir -p lib-dyl/include mkdir -p lib-dyl/lib cp *.h lib-dyl/include cp *.so lib-dyl/lib .PHONY:clean clean: rm -f *.o *.a *.so
使用动静态库
使用静态库
静态链接使用静态库,就是将静态库拷贝到程序当中
直接
#include“myadd.h”,找不到头文件,头文件的搜索路径是在1、当前路径下2、系统的头文件路径下
解决:
将自己的库文件和头文件拷贝到系统路径下(系统路径:头文件(
usr/include/)库文件(lib64/))(找到头文件)
usr/include/
lib64/
指定使用哪一个库 (
gcc -l第三方库)gcc mytest.c -lmythod
我们不推荐使用上面这种方法,这会污染系统
我们可以指定头文件和库文件的搜索路径
gcc mytest.c -o mytest -I ./lib-staic/include/ -L ./lib-static/lib/ -lmythod
使用动态库
动态链接使用动态库,通过地址将动态库和程序进行关联,不用进行拷贝
使用动态库的两种方法
把头文件和库放进系统路径下(和静态库第一种方法一样,不推荐)
编译时指定头文件,库的路径哪一个库
编译时能够找到库,但是进程运行时找不到依赖的库,静态链接将静态库拷贝到程序中,在运行时就不需要依赖库,而动态链接没有拷贝,在运行时就需要依赖库
如何让进程运行时找到动态库?
将动态库拷贝到
lib64/环境变量
通过导入环境变量的方式–程序运行时,会在环境变量中查找自己需要的动态库路径–
LD_LIBRARY_PATH
配置文件
把库对应的软链接放在
lib64中
如下图所示,可执行程序与动态库是分开加载的,动态库加载到物理内存中,映射到虚拟内存的共享区,多个进程可依赖于同一个动态库,可执行程序运行时,需要使用动态库时,会跳转到动态库,执行动态库代码,之后,再回到可执行程序,继续执行可执行程序的代码
 
 

































