目录
- 一. 软硬链接
- 1. 硬链接
- 2. 软链接
- 3. unlink
- 4. 目录的硬链接
- 二. 动静态库
- 1.1 静态库制作
- 1.2 静态库使用
- 2.1 动态库制作
- 2.2 动态库使用
- 3. 动态链接原理
一. 软硬链接
1. 硬链接
硬链接(hard link) 可以将它理解为原始文件的别名, 和原始文件使用相同的 inode 编号和 data block.(inode 是文件在该磁盘分区内的唯一标识, 记录着文件的属性等内容; data block 是文件的内容)
可以使用 ln 指令为文件创建一个硬链接.
ln log.txt link.hard
当创建一个新的硬链接时, 该文件的硬链接数就会加 1; 删除一个文件时, 该文件的硬链接数就会减 1; 只有硬链接数为 0 时, 才会彻底删除该文件.
实际上, 硬链接文件和原文件是同一个, 所以 inode 和属性会和原文件相同, 并且当一个文件更改内容或属性时, 其他的文件也会随之改变.
- 注:
用户不可以使用硬链接 链接目录, 操作系统禁止这样的行为;
硬链接不能跨分区对文件进行链接.(inode 只在分区内唯一)
2. 软链接
软链接 类似 Windows 系统下的快捷方式, 是一个的全新的文件, 并且文件类型为 ‘l’ (链接属性), 内容仅包括所含链接文件的路径名字.
所以软链接能够链接目录, 也能跨区链接; 但当删除或移动原始文件 或路径失效后, 链接文件也随之失效.
使用 ln -s 选项创建软链接
ln -s log.txt link.soft
软链接的文件属性, inode 和原文件都不相同, 并且 软链接文件会指向 (->) 源文件.
3. unlink
使用 unlink 指令可以删除链接文件, 也可以删除普通文件.(rm 指令类似, rm 指令也可以删除链接文件)
unlink /*file_name*/
4. 目录的硬链接
当新创建一个目录时, 硬链接数默认为 2.
因为一个新创建目录时不只在当前目录下创建了 test_dir 和 inode 的映射关系, 在 test_dir 目录中还会创建隐藏的 . 和 inode 的映射关系, 所以硬链接数会增加.
若在当前目录下再新建一个下级目录, 那么当前目录的硬链接数就会加 1, 因为下级目录中的 **..**也是当前目录的一个硬链接.
而操作系统不允许用户创建目录的硬链接, 是因为操作系统会将用户创建的目录认为是下级目录, 在遍历搜索文件等情况下, 会造成环路问题.
二. 动静态库
静态库是 文件在编译链接时使用静态链接, 把需要的库文件全部拷贝至可执行文件中, 可执行程序在运行时不依赖其他文件; 在 Linux 下后缀为 “.a”, 在 Windows 下后缀为 “.lib”.
动态库也被称为共享库, 可执行程序会在运行时动态链接 动态库, 多个可执行程序可以同时调用动态库; 动态库在 Linux 下后缀为 “.so”,在 Windows 下后缀为 “.dll”.
1.1 静态库制作
静态库就是将实现方法的源文件打包为一个文件.
先将源文件编译为 .o 文件
之后使用 ar 指令打包即可.
//ar [选项] [库名] [依赖文件]
ar -rc libFunc.a Add.o Sub.o // -r replace, -c create // -rc 创建或替换库文件
1.2 静态库使用
由于编译器默认不识别第三方的库文件, 直接编译会报错.
所以编译时需要将库文件的路径和文件名一起作为参数传入 gcc/g++ 中.
-I(大写 i) 表示头文件的路径
-L 表示库文件的路径
-l(小写 L) 表示库文件名
也可以直接将创建的头文件和库文件安装至系统目录中, 但并不推荐, 会污染系统的库目录.
2.1 动态库制作
动态库的制作和静态库类似, 不过动态库编译的源文件需要使用 -fPIC 选项, 表示产生位置无关码.
动态库打包依旧使用 gcc/g++, 使用 -shared 选项即可(表示生成共享库格式).
2.2 动态库使用
但由于动态库是运行时动态链接动态库的, 运行时会找不到动态库; 而静态库是编译时将静态库拷贝至可执行程序中的, 所以运行时不依赖文件.
解决方法:
- 拷贝动态库的软链接或动态库本身 至 /lib64/ 目录下;
- 设置环境变量 LD_LIBRARY_PATH, 可以将第三方动态库路径添加至此环境变量中(临时方案);
// 动态库路径
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/hhhhhan/Program/test1
- 设置配置文件, 在 /etc/ld.so.conf.d/ 目录中的都是动态库配置文件, 可以在该目录创建配置文件 xx.conf (文件中存储动态库的路径), 使用 ldconfig 指令加载配置文件.
echo /home/hhhhhan/Program/test1/ > Test.conf
sudo mv Test.conf /etc/ld.so.conf.d/
sudo ldconfig
3. 动态链接原理
在可执行程序编译完成后, 可执行程序内库函数的地址并不是真正的地址, 而是库函数在动态库中的偏移量(相对地址), 是通过位置无关码 fPIC 生成的.
当可执行程序开始运行时, 若动态库没有在内存中, 操作系统会先将动态库加载至内存中; 然后通过页表建立映射关系, 将动态库加载至共享区中, 获得的动态库起始地址;
当可执行程序调用库函数时, 可执行程序会通过 动态库起始地址 + 偏移量 调用库函数.
动态链接解决了静态库空间浪费的问题, 可执行程序只需要保存库函数的偏移量, 在运行时通过动态库加载至共享区中的虚拟地址和页表的映射, 就可以调用库函数;
使得内存中只需要存在一份动态库, 就可以同时被多个可执行程序使用.