Linux制作动态链接库

1.什么是动态链接库

动态链接库是程序运行时加载的库,当动态链接库正确安装后,所有的程序都可以使用动态库来运行程序。动态链接库是目标文件的集合,目标文件在动态链接库中的组织方式是按照特殊方式形成的。库中函数和变量的地址是相对地址,不是绝对地址,其真实地址在调用动态库的程序加载时形成。
动态链接库的名称有别名(soname),真名(realname)和链接名(linker name)。别名由一个前缀lib,然后是库的名字,再加上一个后缀“.so”构成。真名是动态链接库的真实名称,一般总是在别名的基础上加上一个小版本号,发布版本等构成。除此之外,还有一个链接名,即程序链接时使用的库的名字在动态链接库安装的时候,总是复制库文件到某个目录下,然后用一个软链接生成别名,在库文件进行更新的时候,仅仅更新软连接即可。

2.为什么要使用动态链接库:

   (1)减小可执行文件大小 .
   (2)实现资源共享 .
   (3)便于维护和升级 . 
   (4)比较安全 .
由于动态链接库函数的共享特性,它们不会被拷贝到可执行文件中。在编译的时候,编译器只会做一些函数名之类的检查。在程序运行的时候,被调用的动态链接库函数被安置在内存的某个地方,所有调用它的程序将指向这个代码段。因此,这些代码必须使用相对地址,而不是绝对地址。在编译的时候,我们需要告诉编译器,这些对象文件是用来做动态链接库的,所以要用地址无关代码( Position Independent Code (PIC) ) .
//filename:fun.c
#include <stdio.h>
void fun(void) {
    printf("XiyouLinuxGroup\n");
}
//filename:main.c
#include <stdio.h>

//声明函数,可以把所有的声明放到一个"*.h"文件中,然后主函数包含它就可以
void fun(void);

int main(void) {
    printf("hello universe\n");
    fun();
    return 0;
}

3.动态链接库的制作

gcc -fpic -shared fun.c -o libfun.so
//生成动态库文件libfun.so
-fpic:编译生成地址无关代码
-share:生成动态链接库

生成动态链接库之后一个很重要的问题就是安装,一般情况下将生成的动态链接库复制到系统默认的动态链接库的搜索路径下,通常有 /lib, /usr/lib, /usr/local/lib, 放到之上任何一个目录下都可以 。

4.动态链接库的配置

动态链接库并不是可以随意地使用,要在运行的程序中使用动态链接库,需要指定系统的动态链接搜索的路径,让系统找到运行所需的动态链接库才可以。系统中的配置文件/etc/ld.so.conf是动态链接库的搜索路径配置文件。在这个文件内,存放着可被Linux共享的动态链接库所在目录的名字(系统目录/lib,/usr/lib除外),多个目录名间以空白字符(空格,换行等)或冒号或逗号分隔。

//查看系统中的动态链接库的配置文件的内容
hp@lenovo 10:28 :~$ cat /etc/ld.so.conf
include /etc/ld.so.conf.d/*.conf
//Debian的配置文件将目录/etc/ld.so.conf.d中的配置文件包含进来,对这个目录下的文件进行查看:

hp@lenovo 10:28 :~$ ls /etc/ld.so.conf.d/
fakeroot-x86_64-linux-gnu.conf  x86_64-linux-gnu.conf
i386-linux-gnu.conf             x86_64-linux-gnu_EGL.conf
libc.conf                       x86_64-linux-gnu_GL.conf

hp@lenovo 10:33 :~$ cat /etc/ld.so.conf.d/i386-linux-gnu.conf 
# Multiarch support
/lib/i386-linux-gnu
/usr/lib/i386-linux-gnu
/lib/i686-linux-gnu
/usr/lib/i686-linux-gnu

从上面的配置文件可以看出,在系统的动态链接库配置中,包含了该动态库/lib/i386-linux-gnu
/usr/lib/i386-linux-gnu
/lib/i686-linux-gnu
/usr/lib/i686-linux-gnu四个目录。

5.动态链接库管理命令

为了让新增加的动态链接库能够被系统共享,需要运行动态链接库的管理命令ldconfig, ldconfig 命令的作用是在系统的默认搜索路径,和动态库配置文件中所列出的目录里搜索动态链接库,创建动态链接装入程序需要的链接和缓存文件。搜索完毕后,将结果写入缓存文件/etc/ld.so.cache中,文件中保存的是已经排好的动态链接库名字列表。ldconfig 命令行的选项及含义如下:

  -c, --format=FORMAT        采用的格式:新、旧或兼容(默认)
  -C CACHE                   使用用户指定的缓存文件代替系统默认的             缓存文件/etc/ld.so.cache                                               

  -f CONF                    使用用户指定的配置文件代替默认文 件/etc/ld.so.conf

  -i, --ignore-aux-cache     忽略辅助缓存文件
  -l                         手动链接单个动态链接库。
  -n                         只在命令行中给出了进程目录,未创建缓冲区,进处理命令行指定的目录,不对系统的默认目录/lib,/usr/lib进行扫描,也不对配置文件/etc/ld.so.conf中所指定的目录进行扫描

  -N                         不要创建缓冲区
  -p, --print-cache          打印缓存文件中共享库的名字
  -r ROOT                   改变当前应用程序的根目录
  -v, --verbose              生成详细消息,打印ldconfig的当前版本号,显示所扫描的每一个目录和动态链接库

  -X                         不更新链接
  -?, --help                 给出该系统求助列表
      --usage                给出简要的用法信息
  -V, --version              打印程序版本号

如果想知道系统中有哪些动态链接库,可以使用ldconfig的-p选项来列出缓存文件中的动态链接库列表。下面的命令表明在系统缓存中共有1596个动态链接库。

hp@lenovo 10:34 :~$ ldconfig -p
在缓冲区“/etc/ld.so.cache”中找到 1596 个库
libzvbi.so.0 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libzvbi.so.0
libzvbi-chains.so.0 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libzvbi-chains.so.0
libzip.so.4 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libzip.so.4
libzephyr.so.4 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libzephyr.so.4
libzeitgeist-2.0.so.0 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libzeitgeist-2.0.so.0
libzeitgeist-1.0.so.1 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libzeitgeist-1.0.so.1
libz.so.1 (libc6,x86-64) => /lib/x86_64-linux-gnu/libz.so.1
libz.so.1 (libc6) => /lib/i386-linux-gnu/libz.so.1
libz.so (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libz.so
libyelp.so.0 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libyelp.so.0
libyaml-0.so.2 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libyaml-0.so.2

当用户的目录并不在系统动态链接库配置文件/etc/ld.so.conf中指定的时候,可以使用ldconfig命令显示指定要扫描的目录,将用户指定目录中的动态链接库放入系统中进行共享。命令格式的形式为:

ldconfig 目录名

这个命令将ldconfig指定的目录名中的动态链接库放入系统的缓存/etc/ld.so.cache中,从而可以被系统共享使用。下面的代码将扫描当前用户的lib目录,将其中的动态链接库加入系统:

ldconfig ~/lib


Note: 如果在运行上述命令后,再次运行ldconfig而没有加参数,系统会将/lib,/usr/lib,及/etc/ld.so.conf中指定目录中的动态库加入缓存,这时候上述代码中的动态链接库可能不会被系统共享了。

6.链接调用动态库

gcc -o main main.c ./libfun.so
//生成可执行文件main
这里写图片描述

gcc -o main main.c -L./ -lfun

-L 指定链接动态链接库的路径
-lfun链接库函数fun,但运行一般会出现如下问题:

这里写图片描述

这是由于程序运行时没有找到动态链接库造成的。程序编译时链接动态链接库和运行时使用动态链接库的概念是不同的,在运行时,程序链接的动态链接库需要在系统目录下才行。有几种办法可以解决此种问题:

将动态链接库的目录放到程序搜索路径中,可以将库的路径加到环境变量LD_LIBRARY_PATH中实现,例如:

export LD_LIBRARY_PATH=/home/hp/LinuxC:$LD_LIBRARY_PATH


将存放库文件libfun.so的路径~/LinuxC加入到搜索路径中,再运行就没有之前的警告了。

这里写图片描述

另一种方法是使用ld-Linux.so.2来加载程序,命令格式为:
/lib/ld-Linux.so.2 –library-path 路径 程序名

加载main程序的命令为:

/lib/ld-Linux.so.2 –library-path ~/LinuxC main

Note:如果系统的搜索路径下同时存在静态链接库和动态链接库,默认情况下会链接动态链接库。如果需要强制链接静态库,需要加上“-static”选项,即上述的编译方式改为如下的方式:
gcc -o main main.c -static -ldl
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值