1.软硬链接
(1)软链接
例:ln是一个用于链接的指令(对后缀无要求,但最好使用例子的格式)
//后者是前者的软链接
ln -s code.c code.soft
使用后者就相当于使用前者,但两者的inode_number并不相同,说明后者是一个独立的文件。
用途就相当于给一个路径较长的文件在当前路径起一个别名(类似于windows下的快捷方式)
软链接作为一个独立的文件,其的文件属性与指向文件相同,内容就存储了指向文件的路径。
指令:unlink + 软链接
能删除该软链接。
(2)硬链接
ln code.c code.hard
硬链接并没有独立的inode,因此其并不是一个独立的文件,本质是一组新的文件名与一个inode_number建立的又一组映射关系,也就是说一个inode_number其实是可以有多个文件名对应的,inode中有一个成员links_count就是用于记数该inode有多少个对应的文件名,这个数字会使用ls -l时在文件权限和用户名中展现出来:
[root@VM-0-2-centos lesson]# ll gal
//这个就是gal这个文件所有的硬链接数
-rw-r--r-- 1 root root 0 Apr 1 13:54 gal
用途:
(1)对文件进行备份,防止误删
(2)一个目录新建时的引用记数即为2,因为其内部的.隐藏文件就是该目录的硬链接,同时..就是该目录的上级目录的硬链接,因此该目录的上级目录的引用计数至少为3.
(3)linux不允许用户自己给目录做硬链接(只允许给文件做硬链接),只有OS自己可以给目录做硬链接。原因在于用户自己给目录做硬链接容易形成路径环问题(例:根目录路径通过硬链接(对象是根目录)来回到根目录自己了)
其实.和..文件也有路径环问题,但OS对这两硬链接进行了特殊处理。
软链接也会有路径环问题,但软链接文件有其自己的l属性来让OS对其进行特殊处理了。
缓存的有一个意义就是使磁盘中的一片连续的空间中存储的是同一个文件的数据从而提高读写效率。
2.库点的制作
动静态库中不要包含main函数。
.h文件的本质就是对函数的说明指南,也就是.h文件并不会进入链接过程中。
(1)静态库
静态库的本质就是将.o文件打包在一起。
生成静态库的指令(.a后缀就是静态库)
//将所有.o文件打包进libmyc.a这个静态库中
ar -rc libmyc.a *.o
静态库的命名要有.a后缀,.lib前缀。-r为替代文件,-a为新建文件,从这里可以看出打包前该静态库不一定为空。
gcc能直接认识静态库文件,所以直接使用即可。
安装包的简单设计:一个目录中有两个目录分别存.h和.c文件然后打包成安装包。
[root@VM-0-2-centos lesson]# tree bag
bag
|-- head
| `-- test.h
`-- stream
`-- test.c
gcc的几个子指令-l,-L,-I(一个是大写的i,一个是小写的l)
(1)-大写的i
指定.h的目录,帮助编译器找到函数声明
(2)-L
指定库函数所在的目录,帮助编译器找到库函数的位置
(3)-小写的l
要去掉lib前缀和后缀,用于指定需要链接的库名
例:
//指定库目录 指定头文件 指定库名
gcc -o code.exe code.o -L /lesson/bag/stream -I /lesson/bag/head -l myc
我们还可以在include" "时直接写目录的路径从而不用写-L.
想要不写-L和-I(大写的i),一种方法是将其拷贝到系统中。
系统中存库的头文件的路径是/usr/include,存数据库的路径是/usr/lib64.
我们将我们的外部库存到这些路径的方式其实就叫安装,但依旧要指定数据库。
c/c++标准库不用加-(小写l)是因为gcc/c++直接认识这些库。
(2)动态库
使用gcc/g++将一个源文件编译成动态库所存的.o文件时要加一个-fPIC的修饰(生成位置无关代码)。
例:
gcc -c -fPIC code.c -o code.o
意义:
(1)普通文件的逻辑地址是固定的,但采用-fPIC后就没有固定的逻辑地址,也就是允许动态库加载到共享区的原因。
(2)生成GOT(后面会讲)
形成动态库使用gcc/g++即可,例:
gcc -shared(说明形成动态库) -o libmyc.so(动态库后缀) *.o
将自己的文件链接动态库的方式与静态库完全一样
例:
gcc main.c -o main -L /path/my.so -I /path/myhead -l myc
但在动态库的链接中有一个问题:
这样链接完后只有gcc知道动态库的位置,但OS在执行可执行文件时并不知道我们自己的动态库的位置(静态库没有这个问题的原因是静态库在gcc运行完后该可执行程序就不需要静态库了,但动态库在.exe启动时依旧需要)
解决方法:
(1)OS一般默认在/usr/local/lib64路径下找动态库,因此我们可以直接将自己的动态库拷贝到该目录下,或者在该目录下给我们的动态库建立软链接。
(2)有一个环境变量LD_LIBRARY_PATH,OS运行.exe时也会在该环境变量下查找动态库(这个动态库经常都是空的),因此我们也可以在这个环境变量下存我们的动态库所在路径即可,不过其为内存级存储,重启就没有了(当然我们可以在bash进程的.bashrc文件中修改该环境变量的值来永久存储)
(3)OS中还有一种文件叫配置文件,在/etc/ld.so.confd/ 里面的文件存储了OS寻找所需数据库的路径,我们只需在里面自己生成一个.conf文件然后往里面写入自己数据库所在的路径即可。
ld config指令可以刷新OS的配置文件数据。
补充:我们在运行.exe时不需要再用-l指定库名了,因为OS是找不到我们的数据库而不是不认识我们的数据库。
动态库与静态库都存在的情况:
在生成.exe时的指定路径有两个数据相同,名字相同的动/静态库共同存在时,gcc会默认使用动态库,只有加了-static修饰时才使用静态库且必须是静态库。