当文件没有打开的时候,那么文件存储在磁盘之中。 既然存储在磁盘中,那么我们就要去了解一下磁盘文件的存储
磁盘由多个盘片和多个读写头组成,每个盘面都有两个表面,且每一个表面都可以存储数据。 对于每个盘面来说,每个盘面形成半径不同的同心圆,两个圆之间形成的就是磁道。 磁道又在一次被分割,一个磁道又被划分成一个个扇区。 扇区通常包括512字节的数据。扇区就是磁盘的基本单位
虽然磁盘的基本单位是扇区(512字节),但是比较小,而且有可能不同的生产商给出的扇区的大小可能本不一样,所以操作系统(文件系统)和磁盘进行I/O操作的基本单位的块 块是对磁盘存储和访问的抽象,块通常是一个连续的、固定大小的抽象单元。通常是512字节的整数倍。
块通常由下面几个部分构成: Block Group:ext2文件系统根据分区的大小划分为数个快组BlockGroup。,且每一个BlockGroup都有着相同的结构 Block Group分为: 超级块:存放文件系统本身的结构信息。记录的信息主要有,block和inode的总数,使用了多少block和inode的数量,,block和inode的大小,等等。——可以查资料看看 GDT:块组描述符 块位图:哪些数据块被占用 inode位图:inode是否被占用 inode节点表:存放文件属性 数据区:存放文件的内容
我们知道inode和数据是映射关系,是一种一对多的映射关系——存在软硬链接。为什么这么说看下文
一个目录下,可以有很多文件,但是这些文件都没有重复的文件名!
数据区存储的是文件的内容,没有存储文件名的地方,那么文件名存储在哪里呢?
还有一个问题就是目录是文件吗?
显然是的,因为目录它也要自己的inode号,也有自己的数据区。而目录的数据区就是存储的该目录下所有文件的名字。
这就对应了我们之间讲的,进入一个目录要具有什么权限。
x权限,因为用户要进入目录
如果用户要想在该目录下创建文集或者目录,就需要拥有w权限,因为目录的数据区要进行写入新建的文件名或者目录名。
下面有三个问题:
因为下载是真实的把数据写到磁盘中,而卸载只要把inode和数据直接的链接断开就可以,不需要把数据清空,再次下载其他软件的时候,只需要进行数据的覆盖就可以。 数据的恢复就是利用数据没有被删除这个原理,但在恢复数据之前,最好不要下载安装什么东西,导致数据被覆盖修改而不能被恢复。
命令:ln -s 原始文件路径 软链接的文件路径
软链接有什么特定呢?
下面是创建软链接
我们知道,如果不指定test的路径,就不能运行此可执行程序,在前面的文章中,可以把此可执行文件放在环境变量中,就可以执行 如果不放入环境变量中呢? 可以用软链接
把当前文件所在的绝对路径进行软链接到上级路径 那么就可以直接在上级目录运行了。
命令:ln 原始文件路径 硬链接的文件路径
硬链接没有独立的inode,硬链接创建的文件并不是真正意义上的文件,它主要就是在指定的目录下创建了一个映射而已。
下面演示硬链接:
shellln test.c test1.c
ln test.c test2.c
ln test.c test3.c
我们发现他们的inode都是一样的,就验证了我们之前说的情况了。 这里的4是什么意思呢?——4显然表示有4个inode,这是用来计数的,当inode的个数为0的时候,就是真正的把该文件删除了。 思考:为神马默认创建的目录的计数是2呢?
其实有一个隐藏的文件**.**
所以就有2个了。.
表示的就是当前目录。
静态库以.a
后缀结尾,动态库以.so
后缀结尾
静态库其实链接的时候是直接把代码拷到我们的可执行代码里面的。
而动态库只是链接到我们的可执行程序中。
找动态库,只需要在改好代码处加上偏移量,就可以找到共享库。
我们有很多.c.h
文件,当我们编译它的时候,会很麻烦。
下面我们就要把他们制成静态库。
.o
文件ar -rc libmylib.a .o文件
**注意:**库的写法:前缀必须是lib
开头的,后缀必须以.a
结尾。去到前后缀就是库的名字。
gcc默认的搜索路径是:/usr/include
库文件的默认搜索路径是:/lib64 或者 /usr/lib64
我们可以把静态库的头文件以及库文件拷贝到gcc的默认搜索路径下;但是这样会污染里面的库文件。
可以用下面这个路径:
gcc main.c -I ./MyLib/clude/ -L ./MyLib/lib/ -lmylib
解释一下:
-I
是指定头文件的路径
-L
是指定库文件的路径
-l
(这个是小L)是指明库文件路径下的哪一个库。
为什么使用动态库?
.o
文件,加上选项fPIC
,fPIC
作用就是产生位置无关码.o
文件进行打包生成动态库。gcc -shared 由上一步生成的.o文件 -o 动态库
上面我们就制作好了动态库。
gcc默认是链接的动态库。
如果我们直接按照静态库的方法进行运行,发现不可以运行成功。
gcc main.c -I ./MyLib/clude/ -L ./MyLib/lib/ -lmylib
把生成的a.out
运行,发现报错。
我们不是告诉gcc我们的库的位置了吗?为什么还报错呢 原因就是我们是告诉gcc的,没有告诉操作系统或者说是链接器。那么我们运行的时候就会报找不到共享库。
下面是设置动态库路径的几种方式:
LD_LIBRARY_PATH
,在该路径下面再添加一个你的动态库的路径。一但重启服务器,该环境变量看就没有了,因为它是内存级别的环境变量。/etc/ld.so.conf.d/
,在该文件下随便创建一个.conf
的文件,把动态库的路径写到哪个文件中,然后用ldconfig
更新一下的。需要管理员权限makefile.PHONY:all
all:libmylib.so libmylib.a
libmylib.so:file1dy.o file2dy.o
gcc -o libmylib.so -shared file1dy.o file2dy.o
file1dy.o:file1.c
gcc -o $@ -c -fPIC $^
file2dy.o:file2.c
gcc -o $@ -c -fPIC $^
libmylib.a:file1.o file2.o
ar rc libmylib.a file1.o file2.o
file1.o:file1.c
gcc -o $@ -c $^
file2.o:file2.c
gcc -o $@ -c $^
.PHONY:MyLib
MyLib:
mkdir -p ../MyLib/lib
mkdir -p ../MyLib/clude
cp *.a ../MyLib/lib
cp *.so ../MyLib/lib
cp *.h ../MyLib/clude
.PHONY:clean
clean:
rm -f *.o *.a hello *.so