成都建设规划网站,英文 wap网站,怎样建设企业网站 用于宣传,网址域名大全目录 概述#xff1a;
静态库#xff1a;
静态库概述#xff1a;
静态库的制作
共享库#xff08;动态库#xff09;
共享库概述
动态库制作
动态库临时生效
动态库长期生效
动态库的升级
位置无关代码 概述#xff1a;
库文件一般就是编译好的二进制文件
静态库
静态库概述
静态库的制作
共享库动态库
共享库概述
动态库制作
动态库临时生效
动态库长期生效
动态库的升级
位置无关代码 概述
库文件一般就是编译好的二进制文件用于在链接阶段同目标代码一块生成可执行文件或者运行可执行文件的时候被加载以遍调用库文件中的某段代码。 动态链接都是索引的.so文件静态链接都是压缩打包的.a文件。
库文件和可执行文件相比
相同点两者都是编译好的二进制文件不同点库文件没法直接执行直观上看他的源代码中没有main函数而只是一些函数模块的定义和实现没有运行的入口主函数所以库文件没法直接执行。
我们的程序开发无论是运行的时候还是编译链接的时候一般都需要借助一些库来实现他们的功能而很少直接通过程序的源代码生成完全独立的可执行文件。
静态库
静态库概述 静态库实际上就是一些目标文件的一般是以.o结尾的集合静态库一般是以.a结尾只用于链接生成可执行文件阶段。 具体来说以c程序为例子一般我们编译程序源代码的时候过程大致是 以.c为后缀的源文件经过编译生成.o文件的目标文件以.o为后缀的目标文件经过链接生成最终的可执行文件。 我们可以在链接的时候直接链接.o的目标文件也可以将这些.o文件打包集中起来统一链接,而生成的打包集成了所有.o文件也就是静态库。 静态库只在程序连接的时候时候连接器会将程序中使用到函数的代码从库文件中拷贝到应用程序中一旦链接完成生成可执行文件之后执行程序的时候就不再需要静态库了。 由于每一个静态库的应用程序都是需要拷贝所用到的函数的代码所以静态库链接生成可执行文件会比较大多个程序运行的时候占用的内存空间比较大每个程序在内存中都有一份复制的静态库代码但是由于运行的时候不用从外部动态加载额外的库了速度会比共享库快。 静态库的制作 实例假设在实际工作中设计了两个算法但是需要卖给其他公司使用为了保护公司的知识产权是不能将源代码交给其他公司的这样我们可以将两个算法封装或者打包到一个静态库中。 假设实现这两个算法的函数为func1()和func()2。 新建一个头文件hello.h在hello.h中对两个函数进行声明 编写一个简单的程序“hello.c” 将hello.c编译生成.o文件 gcc -c hello.c -o hello.o使用ar命令ar是archive的意思将hello.o文件打包成一个静态库文件libhello.a ar rcs libhello.a hello.o 注意 如果需要将多个.o文件打包成文件库则在命令行后边填写所有.o文件的名字即可生成的库的名字必须是libxxx.a格式注意这里是尽量最好使用lib开头的格式因为其他格式的编译方式是不一样的 编译参数:rcs r表明将模块加入到静态库中c表示创建静态库s表示产生索引 使用nm命令查看库文件中包含的符号nm libhello.a 使用 ar -t 命令查看静态库是由那些.o文件组成的ar -t libhello.a 编写一个带有主函数的程序main.c并且在main.c中调用静态库中的func1和func2函数 现在所有文件下都在同一个目录下没法直接体现出来静态库的作用。 在IO_file_test目录下新建一个static_lib_test目录进行测试将文件移动到下边设备树结构。这里是一个比较常用的目录结构但是为了方便测试三个文件都放在一个文件目录下即可 解释 include目录下是.h文件 lib里边是链接的静态库文件 src里边是.c文件 编译 gcc main.c -L../lib -lhello -I../include -o main 编译解释 -L指向的是链接的静态库路径 -l小L是静态库的命称去掉lib之后的 -I大i链接存放.h文件的路径 编译现象 在静态库的概述中会标红的地方提到了一旦链接完成生成可执行文件之后执行程序的时候就不再需要静态库了所以这时删除掉libhello.a文件后程序仍然可以执行。 共享库动态库
共享库概述 共享库也叫做动态库。 静态库缺点 内存消耗大假设一个静态库的大小为1M,当两千个程序都用到这库将消耗掉2G内存当静态库中的代码优化的时候所有调用该静态库的程序需要重新编译这样太过与麻烦。 动态库特点 动态库在程序编译的时候并不会被链接到目标代码当中而是在程序运行的时候才被载入。不同的应用程序如果调用相同的库那么在内存中里只需要有一份共享库的实例规避了空间浪费问题。动态库在程序运行的时候才能被载入也解决了静态库对程序的更新部署和发布页带来的麻烦。用户只需要更新动态库即可增量更新。 动态库制作
参照静态库目录下创建三个文件如下内容和静态库的也相同 编译链接生成.o文件 将编译好生成好的hello.o编译编译生成动态库gcc -shared -fPIC -o libhello.so hello.o
注意
-shared表明是使用的共享库-fPIC表明生成与位置无关的代码、动态库后缀为.so动态库格式libxxx.so如果还有其他链接的.o文件直接在hello.o后边加上用空格隔开 使用nm命令查看一个库文件中包含的符号 nm libhello.so 对照静态库测试目录制作动态库目录格式 将上边共享库目录的文件对应拷贝到共享库测试目录里边如下 进行编译gcc main.c -L../lib -lhello -I../include -o main 但是如果直接执行的话编译器会爆出一个错误。
错误的主要意思是在加载的时候打不开动态库文件但是注意动态库在在程序执行的时候会被加载。
这是因为在Linux中启动一个ELF格式的二进制可执行文件会自动启动和运行一个program loader程序加载器用来加载一些库。对于Linux系统这个loader的名字是ld-linux.so.X(X是版本号)。这个loader启动后会load所有的其他本程序的要使用的共享函数库。动态库与静态库不同在执行文件的阶段需要加载动态库文件而加载的动态库文件需要在指定位置或者添加在环境变量中才能正确的加载动态库文件。
动态链接库的查找先后顺序
LD_LIBRARY_PATH环境变量中的路径/etc/ld.so.cache缓存文件/usr/lib和/lib
动态库临时生效
可以临时将libhello.so所在的路径追加到环境变量LD_LIBRARY_PATH中
export LD_LIBRARY_PATH$LD_LIBRARY_PATH:/home/book/Desktop/IO_file_test/shared_lib_test/lib
冒号后边跟是自己的动态库路径。
修改完成之后我们可以使用echo $LD_LIBRARY_PATH查看环境变量被修改的值 注意 在终端使用expert命令来修改当前环境变量的值只是对当前会话临时生效如果切换到一个新的会话窗口或者新的终端关闭当前会话窗口都会失效。 动态库长期生效
修改系统启动配置文件将export命令添加到启动文件当中
设置环境变量 1.打开 vim ~/.bashrc 文件 2.在文件末尾添加一行 export LIBRARY_PATH$LIBRARY_PATH:库文件的路径如果需要删除环境变量需要在~/.bashrc中删除环境变量后关掉终端重新启动终端才能生效
export LD_LIBRARY_PATH$LD_LIBRARY_PATH:/home/book/Desktop/IO_file_test/shared_lib_test/lib 3.重新加载配置文件 source ~/.bashrc
将动态库文件拷贝到/usr/lib或者/lib目录下一般不采用这个种方式因为这样会污染系统并且不方便项目迁移修改/etc/ld.so.conf文件
动态库的升级
引入
在实际工作当中我们可能经常需要对动态库的板本进行升级假如原来的库为libhello.so那么升级完以后还需要保留每一个旧的板本动态库的名字就不能重复但是程序在加载的时候只加载libhello.so文件解决所以我们可以对每一个板本的动态库文件进行不同的命名然后在新建立软链接链接需要使用的实体库即可。 根据动态的命名规则我们可以将动态库的第一个板本命名为libhello.so.1.0.0,然后创建软连接
ln -s libhello.so.1.0.0 libhello.so 假设我们在原来的库上增加了某些接口我们可以将新库的版本名命名为libhello.so.1.1.0删除原来的软连接文件并重新创建软链接文件到该文件。 位置无关代码 位置无关代码PIC:position-independent code,也被称为地址无关代码是指源代码被编译成二进制文件可以是执行文件也可以是某个库文件编码方式也和位置地址无关。 程序在运行的时候是需要被加载到物理内存上运行的但是操作系统为了方便每个进程进行内存管理使用虚拟内存技术每一个进程运行时都会得到4G的虚拟内存。这个虚拟内存可以认为每个进程任务自己认为自己有4G的空间着只是每个进程认为的但是实际上在虚拟内存对应的物理内存上可能只对应一点点的物理内存实际用了多少内存就会对应多少物理内存。
使用静态库和动态库编译生成的可执行文件在运行时候在内存上的加载方式 如果使用了静态库编译可执行程序每个函数在内存中的位置地址在编译完成以后就已经决定了。
但是共享库动态库是在可执行程序执行的时候加载进去的动态编译后的函数的调用地址是自动计算出来的这就是与位置无关的代码。
下边是找到的一个资料对位置无关代码的验证 在64为机器上可以运行32位的指令。