说明:使用动静态库,一般直接安装即可,其他使用方法了解即可
静态库
静态库(Static Library)是一种将代码和数据打包成一个单独的文件的库文件,主要用于编译时的链接,而不是运行时。静态库通常以 .a
(在Unix和Linux系统中)或 .lib
(在Windows系统中)为后缀。
创建静态库
假设有两个源文件 foo.c
和 bar.c
,可以使用以下命令创建一个静态库,库名规则:libxxx.a:
gcc -c foo.c bar.c
ar rc libfoobar.a foo.o bar.o
使用静态库
在编译使用这个库的程序时,需要指定静态库文件:
gcc -o myprogram myprogram.c -I . -L . -lfoobar
其中
-I .
表示在当前目录中查找头文件
-L .
表示在当前目录中查找库文件,
-lfoobar
表示链接名为libfoobar.a
的静态库。
直接编译很麻烦有什么方法可以避免这么繁琐的操作吗
安装静态库
什么是安装静态库,听起来很高级。其实就是将库文件和头文件放到系统默认搜索路径下。
头文件默认搜索路径在 /usr/include
库文件默认搜索路径在 /lib64
编译时只需要指定库名字就可以
建立软连接
删除连接后,无法编译
动态库
动态库(Dynamic Library)是一种可以在运行时被程序加载和使用的库文件。与静态库不同,动态库在程序执行时才被加载到内存中,允许多个程序共享同一份库代码,从而减少内存占用和磁盘空间。
创建动态库
假设有两个源文件 dyfunc.c 和 log.c,可以使用以下命令创建一个静态库:
gcc -fPIC -c log.c dyfunc.c
gcc -shared -o libdylib.so log.o dyfunc.o
shared: 表示生成共享库格式
fPIC:产生位置无关码(position independent code)
库名规则:libxxx.so
使用动态库
和静态库一样:
gcc -o test main.c -I ./lib/include/ -L ./lib/mylib/ -ldylib
为了编译更简洁可以使用下面方法
安装动态库
头文件默认搜索路径在 /usr/include
库文件默认搜索路径在 /lib64
将静态库也一起使用:,编译测试
建立软连接
和静态库一样,就不赘述了
运行动态库
如果将默认路径下的库文件删除,文件运行时会找不到动态库文件,为什么?
编译指令只是编译器在编译阶段使用动态库,在程序运行时,系统不知道动态库在哪 。所以要让系统直到库的位置才能解决问题。
上面的两个方法安装或者建立软连接后,系统可以找到,文件可以运行。如果编译后要运行,但是已经将默认路径下的库文件删除,可以使用以下方法
更改环境变量 LD_LIBRARY_PATH
LD_LIBRARY_PATH=$LD_LIBRARY_PAHT:xxx(库路径)
ldconfig 配置/etc/ld.so.conf.d/,ldconfig更新
在/etc/ld.so.conf.d目录下创建一个文件,文件写入库所在目录。
最后,ldconfig 更新设置即可
总结
说了这么多方法,其实实际应用都是直接安装库,将库放到共享库目录下。其他方法了解即可
原理
首先明确一个问题,程序的逻辑地址是在什么时候就有的?编译结束时就已经存在还是在程序运行时才有的。大家看一下汇编代码就知道了,汇编都有逻辑地址,所以逻辑地址是在编译后就确认的。
当程序运行时,操作系统创建PCB,进程内核数据结构保存了程序入口地址entry,CPU的PC从这个地址开始执行,CPU从虚拟内存中找数据,通过页表找到物理地址。这时因为程序未加载到内存,会触发缺页中断,将部分使用的数据加载到主存。CPU获取并执行下一条指令的地址,程序就这样执行下去,直到结束。
,
动态库存储在共享区,有几个原理的问题。
1.动态库也会编译一次,像程序一样被加载到主存,如果多个程序使用同一个动态库,加入动态库中有全局变量这些东西,为什么不会出问题?
写时拷贝,当某个进程要修改数据,会触发写时拷贝,使得每一个进程数据相互独立
2.一个进程可能会使用多个动态库,每次库的加载顺序和位置都会变化,它是如何调用库的?
CPU执行到调用动态库的操作时,因为动态库编译时采用的时相对编址,这就是动态库编译时要用这个选项的原因 :fPIC(生成位置无关码)。相对编址在编译的时候,所有的地址代表的是相对首地址的偏移量。而进程内部保存了所有调用的动态库的首地址_start,只需要将_start+相对地址就可以找到动态库中的数据在进程地址空间的地址,然后通过页表映射找到物理地址。