动静态库的文件后缀:
- Linux
- .so(动态库)
- .a(静态库)
- windows:
- .dll
- .lib
库文件实际就是把.o文件打包,库文件的出现提高了i开发的效率
动态库的使用方法:
- 把库安装到系统中
- 使用命令行添加环境变量
- 建立软链接
- 修改bashrc配置文件,使其永久生效
- 新增动态库搜索的配置文件,ldconfig
在使用第三方库时,需要提供一堆头文件和库文件(方法实现和.o文件)
默认使用的是动态库,如果需要使用静态库需要在命令行中添加-static,当没有添加-static且只提供了.a文件时会默认链接静态库,其他库正常动态连接
-static的使用意义是强制性的,将程序进行静态链接就必须要求链接的库必须提供对应的静态库版本
动态库加载的底层了解前首先知道可执行空间与地址空间之间的联系
代码编译后需要运行,需要生成一个它自己的进程,进程有着task_struct结构体。
加载库并不考虑静态库,原因是,静态库在编译期间直接把方法和数据拷贝在了磁盘上。未来加载只需要考虑程序加载即可。
a.out程序在加载时,会先加载到内存,通过页表再映射到地址空间当中。程序如果需要使用到库,那么库会先加载到内存中,再通过页表映射到地址空间中的共享区
动态库的使用整体轮廓就是先加载到内存中然后通过页表映射到地址空间的共享区域。
可执行程序编译后却没有执行,产生的二进制代码是否有地址?
有地址的。二进制文件有自己的固定格式,叫做etf格式。etf格式的头部是可执行程序的属性,可执行程序编译后形成的每一条语句都有自己的地址
elf格式+加载器的配合找到代码各区域的起始区和终止区,找到main函数的入口地址
程序加载到内存中,每一条二进制都有自己的地址,CPU中有一个pc指针,专门存放CPU当前读取的指令,CPU 通过PC指针的提示来读取内存中的数据,而pc指针中存放的是二进制代码的虚拟地址空间,此外每一条指令在拥有虚拟地址的同时也有物理地址,然后通过页表对虚拟地址和物理地址进行映射关系,cpu读取到了pc中的虚拟地址,通过虚拟地址拿去物理地址,然后运行指令
库在加载时都有虚拟的起始地址且库中含有偏移量,偏移量是不会变的,即便在未来两个文件未加载时虚拟地址空间相同的矛盾迎刃而解,操作系统会根据偏移量来映射实际的物理地址来访问该库