一.软硬链接
1.建立软硬链接
2.软硬链接的区别
软链接是一个独立文件,有自己的独立的inode和inode编号。
硬链接不是一个独立文件,它和目标文件使用的是一个inode。
3.认识软硬链接
软链接是一个独立的文件,因为软链接有自己独立的一个的编号,软链经常用来作为我们对应某一个文件的链接来帮我们进行对应的文件的快速访问。软链接就相当于linux下的快捷方式。
硬链接其实就是单纯的在linux指定的目录下给指定的文件新增文件名和inode的编号的映射关系。
4.删除软硬链接
5.什么是硬链接数
inode编号,其实就是一个“指针”的概念,本质就是该文件inode属性中的一个计数器(count),标识有几个文件名和我的inode建立了映射关系。总而言之,就是有几个文件名指向我的inode(文件本身)。
为什么创建普通文件,硬链接数默认是1?
因为普通文件名本身就和自己的inode存在映射关系,只有1个。
为什么目录硬链接数是2?
除了自身之外,目录中有一个隐藏的“·”指向当前目录。
. 和 .. 是Linux为目录文件建立的硬链接 ,Linux下不允许手动为目录文件建立一个硬链接,这是因为Linux的目录结构是一颗以"/目录"为根节点的树,如果允许自定义硬链接,则很有可能会破坏这个结构,甚至形成循环;而一旦形成循环,对于需要遍历目录树的命令是致命的,为了避免对目录树结构的破坏,Linux不允许用户自定义硬链接在目录上。
6.什么是软连接
软链接既然是一个独立文件,inode是独立的,软链接的文件内容保存的是指向文件所在的路径。
二.动静态库
1.静态库与动态库
- 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库
- 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
- 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码
- 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking)
- 动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。
2.静态库的制作
创建mymath.h/mymath.c ,myprint.h/myprint.c制作动静态库
链接:把所有的.o链接成一个可执行程序。
如果把我的.o文件给别人,别人同样可以使用
生成静态库
ar是gnu归档工具,rc表示(replace and create)
[abc@aly mklib]$ ar -rc libmymath.a mymath.o myprint.o
对应文件的makefile命令
libmymath.a:mymath.o myprint.o
ar -rc libmymath.a mymath.o myprint.o
mymath.o:mymath.c
gcc -c mymath.c -o mymath.o -std=c11
myprint.o:myprint.c
gcc -c myprint.c -o myprint.o -std=c11
.PHONY:clean
clean:
rm -f *.o
3.静态库的交付
改写对于的makefile文件
4.动态库的制作
- shared: 表示生成共享库格式
- fPIC:产生位置无关码(position independent code)
- 库名规则:libxxx.so
示例:
[abc@aly mklib]$ gcc -fPIC -c sub.c add.c
[abc@aly mklib]$ gcc -shared -o libmymath.so*.o
[abc@aly mklib]$ ls add.c add.h add.o libmymath.so main.c sub.c sub.h sub.o
对应的makefile文件
libmymath.so:mymath.o myprint.o
gcc -shared -o libmymath.so mymath.o myprint.o
mymath.o:mymath.c
gcc -fPIC -c mymath.c -o mymath.o -std=c11
myprint.o:myprint.c
gcc -fPIC -c myprint.c -o myprint.o -std=c11
clean:
rm -rf *.o *.so
5.动态库的交付
改写对于的makefile文件
6.动静态库合并发布
改写对应文件的makefile
这样就完成了动静态库的合并发布
7.使用动静态库
7.1.头文件的搜索路径
- 在当前路径下查找头文件
- 在系统头文件路径下查找头文件
7.2.静态库使用方法
方案一:将静态库和头文件拷贝至对应的系统库路径和头文件路径下(不推荐)
方案二: 指定静态库头文件搜索路径 -I头文件搜索路径 -L库路径搜索路径 -l在-L指定的路径下你要链接哪一个库
$gcc mytest.c -o mytest -I ./lib-static/include/ -L ./lib-static/lib/ -lmymath
7.3.动态库使用方法
指定动态库头文件搜索路径 -I头文件搜索路径 -L库路径搜索路径 -l在-L指定的路径下你要链接哪一个库进程无法运行,是因为进程找不到对于的动态库。
那么静态库的时候,怎么没有这个问题呢? 形成可执行程序之后,程序已经把需要的代码拷贝进我的代码中! 运行时,不依赖你的库!-- 不需要运行时查找
为什么动态库会有这个问题?
是因为程序和动态库,是分开加载的!
7.4.如何让进程找到动态库
方案一:动态库拷贝到系统路径下/lib64 --安装
方案二:更改环境变量LD_LIBRARY_PATH(通过导入环境变量的方式--程序运行的时候,会在环境变量中查找自己需要的动态库路径)
用于指定查找共享库(动态链接库)时除了默认路径(./lib和./usr/lib)之外的其他路径。
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/abc/file/0823/mklib/test/lib-dyl/lib/
当然这个环境变量在下次重新登录就没了,如果想让这个环境变量永久生效,可以把这个环境变量添加到登录相关的启动脚本里,下面两个都行,但是不建议,如果真要改,多开几个终端,防止改了之后登不上Linux:
vim ~/.bash_profile
vim ~/.bashrc
方案三:ldconfig
[abc@aly ld.so.conf.d]$ ll /etc/ld.so.conf.d/ -d
drwxr-xr-x. 2 root root 4096 May 19 2022 /etc/ld.so.conf.d/
/etc/ld.so.conf.d/是系统搜索动态库的路径
[abc@aly ld.so.conf.d]$ sudo touch new.conf
[abc@aly ld.so.conf.d]$ sudo vim new.conf
[abc@aly ld.so.conf.d]$ cat new.conf
/home/abc/file/0823/mklib/test/lib-dyl/lib/
更新ldconfig
[abc@aly ld.so.conf.d]$ sudo ldconfig
方案三重启有效。
方案四:建立软链接
[abc@aly test]$ sudo ln -s /home/abc/file/0823/mklib/test/lib-dyl/lib/libmymath.so /lib64/libmymath.so
7.5.动静态库的加载
静态库只能静态链接,动态库只能动态链接。一般需要提供动静态两种版本的库,gcc和g++优先默认使用动态库进行链接,想要静态链接,需要手动在编译指令后添加-static选项。
Linux操作系统中一定会存在动态库,操作系统中有很多命令是由C语言写的,它们采用动态链接。
无论是采用动态链接还是静态链接,程序在预编译的时候,都会把所包含的头文件进行展开,这里展开的仅仅是库中的声明;当程序在链接的时候,静态链接会将库函数的定义拷贝一份到程序的代码段中,而动态链接会将动态库中所需的定义通过地址偏移量的方式加载到内存而不是可执行程序中,可执行程序运行时将这些定义通过页表映射至共享区,所以动静态库的体积存在巨大的差距。