文章目录
- 动态库
- 生成动态库
- 使用动态库
- 现象事实
- 使用外部库
- 动态库怎么被加载的
- 进程地址空间的第二讲
- 关于地址
- 1.程序没有加载前的地址(程序)
- 2.程序加载后的地址(进程)
- 3.动态库的地址
动态库
生成动态库
shared
: 表示生成共享库格式
fPIC
:产生位置无关码(position independent code)
库名规则:libxxx.so
myprintf.h
#pragma once
#include <stdio.h>
void print();
myprintf.c
#include "myprintf.h"
void print()
{
printf("hello print!\n");
printf("hello print!\n");
printf("hello print!\n");
}
mylog.h
#pragma once
#include <stdio.h>
void log(const char*);
mylog.c
#include "mylog.h"
void log(const char*msg)
{
printf("hello %s\n",msg);
}
动静态库都要先形成.o
文件,gcc -c
不指定名字,默认生成同名 .o
文件。
可执行权限x
,本质就是该文件是否会以可执行文件的形式加载到内存里。静态库不需要加载。
main.c
#include "myprintf.h"
#include "mylog.h"
int main()
{
print();
Log("linux");
return 0;
}
使用动态库
编译选项
l:链接动态库,只要库名即可(去掉lib以及版本号)
L:链接库所在的路径.
命令行上的路径是告诉编译器的,
动态库的路径也得告诉系统–加载器
加载也需要路径,系统会去特定的路径下寻找
解决加载找不到路径的方法:
- 拷贝到系统默认的库路径下
/lib64
/usr/lib64
(最常用)【直接安装到系统里】 - 在系统默认的库路径下
/lib64
/usr/lib64
建立软链接
-
将自己的库所在的路径,添加到系统的环境变量
LD_LIBRARY_PATH
中重启
XShell
对应配置的环境变量就没了(可以加到环境变量的配置文件中)
/etc/ld.so.conf.d
建立自己动态库路径的配置文件,然后重新ldconfig
即可
这个方法是永久有效的。重启XShell
也会存在。
findway.conf
/home/lll/linux_code/lesson24/test/mylib/lib
现象事实
1.动态库在进程运行的时候是要被加载的。(静态库不用)
2.常见的动态库被所有的(动态链接的)可执行程序都要使用。
动态库–共享库
所以,动态库在系统中加载之后,会被所有进程共享。
main.c
#include "mymath.h"
#include "myprintf.h"
#include "mylog.h"
int main()
{
int n=div(10,0);
printf("10/0=%d,myerror=%d\n",n,myerrno);
print();
Log("linux");
return 0;
}
所需要的代码已经拷贝到可执行程序了,所以静态库删了也不影响程序运行。
动态库删除了 两份代码都跑不了了
main.c
和 test.c
#include "myprintf.h"
#include "mylog.h"
int main()
{
print();
Log("linux");
return 0;
}
一个共享库会被两个不相关的代码使用。
一个共享库挂了,那么和这个共享库相关的代码都跑不了了。
使用外部库
系统中其实有很多库,它们通常由一组互相关联的用来完成某项常见工作的函数构成。
比如用来处理屏幕显示情况的函数(ncurses
库)
-lm
表示要链接libm.so
或者libm.a
库文件
动态库怎么被加载的
进程地址空间的第二讲
什么是虚拟地址?什么是物理地址?
CPU读到的指令里面用的是什么地址?
gcc -fPIC
--与位置无关码
关于地址
1.程序没有加载前的地址(程序)
程序编译好之后,内部有地址的概念吗? 有!!!
可执行程序分成很多段!(代码段、数据段)
平坦模式–编译器也要考虑操作系统!!!
已经是虚拟地址了!-- 逻辑地址!(段地址+偏移量)
2.程序加载后的地址(进程)
test.c
#include <stdio.h>
int a=10;
int b=20;
int main()
{
printf("Hello linux\n");
int x=30;
int y=40;
int z=x+y;
printf("ret=%d\n",z);
return 0;
}
把二进制程序反汇编出来了。
左边一列就是地址。每条指令都有自己的长度。
地址可以不出现。
程序入口+每条指令的长度就可以让代码运行了,
call指令可以计算出偏移量来找到对应的代码。
在运行之前,CPU中的寄存器提前内置了指令集(精简指令集|复杂指令集)
3.动态库的地址
静态库为什么不谈加载?不谈与位置无关?
1.静态库会直接把对应的方法程序拷贝到可执行程序里,所以不需要加载。
2.静态库与位置有关!
因为静态库程序是直接拷贝到可执行文件里的,
可执行文件在程序地址空间中是直接绝对编址,有绝对地址,
所以地址在虚拟地址中是确定的!