一、软链接
1.1 如何建立软链接
//建立软链接 -s代表soft
ln -s 目标文件名 链接文件名
//删除软链接
rm 链接文件
或
unlink 链接文件
1.2 软链接的特点与功能
通过ls -i指令可以查看文件的inode编号
、
可以看出目标文件与软链接文件各自有自己的inode,所以软链接是一个独立的文件
查看目标文件与查看链接文件的内容是相同的,这个类似于快捷方式的功能
所以在项目中当我们需要访问一个路径很深的文件时,我们可以建立一个软链接,这样访问文件就不需要每次都输入完整的路径了
当我们删除目标文件时,会发现软链接失效了,这是因为软链接的内容保存的是目标文件对应的路径字符串,当目标文件被删除时,软链接也就失效了
二、硬链接
2.1 如何建立硬链接
//建立软链接 ln默认为硬链接
ln 目标文件名 链接文件名
//删除软链接
rm 链接文件
或
unlink 链接文件
2.2 硬链接的特点与功能
可以发现硬链接与目标文件的inode编号是相同的,所以硬链接不是一个独立的文件,其使用的是目标文件的inode,并且我们发现当建立硬链接后,文件中间的有个数字从1变成了2,这个数字类似于引用计数,表示与该inode编号映射的文件的个数
所以硬链接就是文件名与inode编号的一个映射关系,建立硬链接的本质就是在指定目录下,建立一个新用户名与inode编号的映射关系
当删除目标文件时,硬链接还可以正常使用,只是引用计数会减1,对文件建立硬链接然后删除目标文件就相当于对文件重命名
#硬链接的功能:
1.构建Linux路径结构(.与..)
当新建一个文件其引用计数是1,因为只有一个文件名与inode编号对应,而当建立一个目录,其引用计数是2,这是因为每个文件默认有两个名字为 . 和 ..的文件,.对应的是当前目录,所以新建一个目录其引用计数必定是2,当在目录中创建子目录时(仅父子关系),父目录的引用计数也会加1,因为子目录的..对应父目录,所以我们也可以通过查看目录的引用计数,来判断该目录下有几个子目录
2.做文件的备份
当对目标文件建立硬链接后,若误删目标文件,我们也可以通过硬链接找回,所以硬链接可以做文件的备份
三、动静态库
3.1什么是动静态库
静态库和动态库是计算机程序开发中两种不同的库类型,它们都是预先编译好的二进制代码集合,用于提供可重用的功能模块给其他程序调用。
#静态库:
静态库在链接阶段会被完整地加入到最终生成的可执行文件中。当编译器在创建一个程序时,如果程序引用了静态库中的函数或对象,那么静态库中的相关代码会被复制并整合到该程序内部。因此,静态链接后的可执行文件包含了程序运行所需的所有库代码,不需要在运行时依赖外部文件。静态库常见的扩展名有 `.a`(Unix/Linux 系统)或 `.lib`(Windows 系统)。
#动态库:
动态库(也称共享库或DLL - 动态链接库,在Windows系统中)则在程序运行时加载,并且多个程序可以共享同一份库代码。这意味着,动态库并不被直接合并到可执行文件中,而是作为独立的文件存在(扩展名为 `.so` 在Unix/Linux系统中,`.dll` 在Windows系统中)。当程序启动时,操作系统根据程序内存储的引用信息,将动态库加载到内存中,并让程序通过某种机制(如符号查找)来调用库中的函数或数据。这样做的好处是可以减少磁盘空间占用和内存开销,同时方便更新库文件而不必重新编译连接依赖它的所有程序。
总结来说,静态库的特点是编译时链接、代码体积大但独立运行,而动态库的特点是运行时链接、节省资源但依赖环境,当库被删除时,程序就跑不起来了
3.2 静态库
如何建立与使用静态库
以如下四个文件举例:
Add.h:
#pragma once
#include<stdio.h>
int add(int a,int b)
Add.c:
int add(int a,int b)
{
return a+b;
}
Sub.h:
#pragma once
#include<stdio.h>
int sub(int a,int b)
Sub.c:
int sub(int a,int b)
{
return a-b;
}
当我们写了一份代码需要给别人,但是不想让他知道源代码是什么,我们可以将所有的.c文件先编译成.o的二进制文件,在给他提供相应的头文件信息,这样别人就可以使用我们的程序而不知道我们的代码了
但是这样操作有很大的局限性,如果我们的代码有几百个头文件,几百个.o文件,用户必须将所有的.o文件放到他的目录下,少一个可能程序就跑不起来了,如果将头文件与实现封装成一个库,那这样的问题就解决了
如何建立一个静态库:
1.先将所有的.c文件以仅编译不链接的方式形成.o文件
gcc -c xxx.c
(会默认形成一个同名的.o文件)
2.使用ar命令形成静态库,静态库名称一般以lib开头.a结尾
ar -rc libmyc.a *.o
ar:gnu归档工具
-r(replace):若静态库中的文件有所更新,就替换为新文件
-c(create):若静态库中的文件更新后,不存在某些文件,就建立这些文件
3.第二步其实就已经形成静态库了,但是为了方便管理,可以将对应的头文件也封装到一个include目录(名字随意)下,并将libmyc.a与include在封装到一个mylib文件中,这样一个第三方静态库就建立好了
如何使用第三方静态库:
方法一:
将第三方的头文件与库文件加载到系统的库搜索路径中
zyq@iZf8z3j2ckkap6ybtz8qseZ:~/mydir$ sudo cp mylib/include/*.h /usr/include/
zyq@iZf8z3j2ckkap6ybtz8qseZ:~/mydir$ sudo cp mylib/lib/*a /lib64
若此时直接编译main文件,会发现找不到add与sub函数,这是因为gcc/g++默认认识系统原本的库,而libmyc.a是第三方库,gcc不认识它,所以就找不到库中方法的实现
在使用第三方库时,需要用到 -l 选项标识自己用的库文件名(库文件名默认是去掉lib前缀和.a后缀)
方法二:
利用选项
- -I:(大写的I) 指明用户自定义头文件的路径
- -L:指明用户自定义库的路径
- -l:(小写的L)指明引用到的库文件
3.3 动态库
如何建立动态库
1.首先将.c文件编译为.o文件,与静态库的方式不同的是需要加一个 -fpic(产生位置无关码(position independent code) )的选项
gcc -fpic -c Add.c Sub.c
2.将.o文件封装成动态库
- shared: 表示生成共享库格式
- 库名规则:libxxx.so
- 不需要使用ar指令,gcc/g++会默认生成动态库
gcc -shared -o libmyc.so *.o
如何使用动态库
我们将形成的动态库与静态库放到一起,然后编译一下,会发现编译成功,但是可执行程序不能正常运行,如果我们加以一个-static的选项,强制使用动态库链接,发现程序可以正常执行,这说明当静态库与动态库同时存在时,编译优先使用动态库
那为什么使用静态库程序就可以运行,使用动态库就不可以呢?
【解释】:静态库在编译时就将代码加载到文件中了,运行时就与静态库没有关系了,我们通过-I -L等选项提供的路径告诉的是编译器,但是没有告诉操作系统我们的库在哪里,所以可以编译成功但是不能执行,动态库使用需要在运行时将库找到并加载
解决方法:
1.拷贝.so文件到系统共享库路径下, 一般指/usr/lib(不推荐,使用多了会造成污染)
2.在系统共享库路径下创建动态库的软链接
3.命令行导入环境变量:在LD_LIBRARY_PATH环境变量后加入动态库的绝对路径
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/zyq/mydir/dir/mylib/lib
ps.这种方法重启xshell就失效了
4.修改.bashrc文件,加上动态库的绝对路径,让环境变量永久生效
5.在/etc/ld.so.conf.d目录下配置文件,并加载
以root身份进入/etc/ld.so.conf.d目录中,创建一个以.conf为后缀的文件,将动态库的路径保存到该文件中,并利用 ldconfig 指令让配置文件生效