linux下动态库的生成和链接

linux下动态库的生成和链接(.so)

本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。
windows和linux下都存在库,但不同。
静态库:.a 文件。静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。
动态库:.so,也叫共享库(shared object)。程序运行时的动态链接,多个进程可以链接同一个共享库。动态库在程序编译时并不会被连接到目标代码中,程序运行时被载入,因此在程序运行时还需要动态库存在。
优点:一旦动态库中的函数发生变化,对于可执行程序来说是透明的,可执行程序无需重新编译。这对于程序的发布、维护、更新起到了积极的作用。

当静态库和动态库同名时, gcc命令将优先使用动态库

以后慢慢研究原理,先实现一个最简单的库链接。

LINUX下 so文件即为动态库,类似于windows下的DLL。
作用:1、代码复用,简化代码,节约资源
2、不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例

//test.h
#include <stdio.h>

int a();
int b();

//test.c
#include "test.h"

int a()
{
    printf("hello world\n");
    return 0;
}

int b()
{
    printf("welcome to China\n");
    return 0;
}

//main.c
#include "test.h"
int main()
{
    a();
    b();
    printf("program excute success\n");
    return 0;
}
编译生成 libtest .so 文件,并通过链接库编译生成可执行文件 mm
gcc test.c -fPIC -shared -o libtest.so
gcc main.c -L. -ltest -o mm

-shared:该选项指定生成动态连接库(让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号),不用该标志外部程序无法连接。相当于一个可执行文件
-fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。
-L.:表示要连接的库在当前目录中
-ltest:编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称
LD_LIBRARY_PATH:这个环境变量指示动态连接器可以装载动态库的路径。
当然如果有root权限的话,可以修改/etc/ld.so.conf文件,然后调用 /sbin/ldconfig来达到同样的目的,不过如果没有root权限,那么只能采用输出LD_LIBRARY_PATH的方法了。

执行:./mm
./mm: error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory

执行出错了,原因是操作系统无法找到库。
查看一下依赖的库:ldd mm
ldd mm
 linux-vdso.so.1 =>  (0x00007fffc01ff000)
 libc.so.6 => /lib64/libc.so.6 (0x00007f0592b06000)
 /lib64/ld-linux-x86-64.so.2 (0x00007f05930af000)

 发现libtest.so并没有链接进去
解决方法一:
1、将.so文件放入默认搜索路径中。一般在:/etc/lib/.下
2、在多用户环境下,一般我们不享有默认路径写入的权限。可以通过设置 LD_LIBRARY_PATH 环境变量解决:
export LD_LIBRARY_PATH=.
或者: export LD_LIBRARY_PATH=$(pwd)
这里的意思是将当前文件添加为共享目录。当然,后面的目录可以自己手动输入绝对路径

按照这样设置后,在执行可执行文件时,操作系统会先在LD_LIBRARY_PATH下搜索库文件,搜索不到再去默认路径中继续搜索。
缺点:修改环境变量,会影响所有的可执行程序。如果我们在编译其他程序时,如果我们不小心,很可能导致其他可执行文件无法运行。

解决方法二:提供 -rpath选项(runtime path)
将搜索路径信息写入可执行文件,不需要设置环境变量。
缺点:当库文件移动时,需要重新编译生成可执行文件。
编译命令:
gcc -g -o mm main.c -ltest -L. -Wl,-rpath=.
-Wl(大写的W,小写的l)
-rpath选项是传递给连接器(linker),“.”表示当前目录


ldd mm
 linux-vdso.so.1 =>  (0x00007fffc01ff000)
 libtest.so => /opt/code/xqf/dcs/src/linux_practice/libtest.so (0x00007f0592eac000)
 libc.so.6 => /lib64/libc.so.6 (0x00007f0592b06000)
 /lib64/ld-linux-x86-64.so.2 (0x00007f05930af000)

执行:./mm
hello world
welcome to China
program excute success

成功!!

文件列表:ll
-rwxr-xr-x 1 root root    1936 Apr 20 08:31 libtest.a
-rwxr-xr-x 1 root root    8200 Apr 18 22:21 libxqf.so
-rwxr-xr-x 1 root root     105 Apr 18 22:19 main.c
-rwxr-xr-x 1 root root     136 Apr 18 22:19 test.c
-rwxr-xr-x 1 root root      38 Apr 18 19:41 test.h
-rwxr-xr-x 1 root root    1792 Apr 19 19:30 test.o
-rwxr-xr-x 1 root root   12410 Apr 18 22:24 mm

./mm & 表示在后台执行该可执行文件


几点知识, 参考资料
静态库链接时搜索路径顺序:
1. ld会去找GCC命令中的参数-L
2. 再找gcc的环境变量LIBRARY_PATH
3. 再找内定目录 /lib /usr/lib /usr/local/lib 这是当初compile gcc时写在程序内的

动态链接时、执行时搜索路径顺序:
1.  编译目标代码时指定的动态库搜索路径;
2.  环境变量LD_LIBRARY_PATH指定的动态库搜索路径;
3.  配置文件/etc/ld.so.conf中指定的动态库搜索路径;
4.  默认的动态库搜索路径/lib, /usr/lib, /usr/local/lib

新安装一个库之后如何让系统能够找到它
如果安装在/lib或者/usr/lib下,那么ld默认能够找到,无需其他操作。
如果安装在其他目录,需要将其添加到/etc/ld.so.cache文件中,步骤如下
1.编辑/etc/ld.so.conf文件,加入库文件所在目录的路径
2.运行ldconfig,该命令会重建/etc/ld.so.cache文件


编译生成静态库:
gcc -c test.c    生成 test.o 文件
ar crv libtest.a test.o    创建静态库文件 libtest.a
gcc -o mm main.c -static -L. -ltest    生成可执行文件 mm
执行:./mm
hello world
welcome to China
program excute success

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux中,生成动态链接库的步骤如下:首先,使用gcc命令编译生成地址无关代码,可使用选项-fpic来指定编译生成地址无关代码。其次,使用选项-shared来生成动态链接库文件。例如,可以使用以下命令生成动态链接库文件libfun.so:gcc -fpic -shared fun.c -o libfun.so。 生成动态链接库之后,需要将生成动态链接库文件复制到系统默认的动态链接库搜索路径下。通常,系统默认的动态链接库搜索路径包括/lib、/usr/lib和/usr/local/lib等目录。可以将动态链接库文件放置在任何一个这些目录下。这样,系统在运行程序时就可以正确地找到动态链接库。 如果程序在运行时无法找到动态链接库,可以采取以下几种解决方法之一:将动态链接库的目录加入程序的搜索路径中。可以将动态链接库的路径添加到环境变量LD_LIBRARY_PATH中,以实现动态链接库的搜索。例如,可以使用以下命令将的路径添加到LD_LIBRARY_PATH环境变量中:export LD_LIBRARY_PATH=/path/to/library。这样,程序在运行时就能找到所需的动态链接库。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Linux制作动态链接库](https://blog.csdn.net/Oscer2016/article/details/52048957)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值