• linux动态链接库


    前言

    静态链接库会编译进可执行文件,并被加载到内存,会造成空间浪费

    静态链接库对程序的更新、部署、发布带来麻烦。如果静态库更新了,使用它的应用程序都需要重新编译、发布给用户(对于玩家来说,可能是一个很小的改动,却导致整个程序重新下载,全量更新)

    动态库在程序编译时并不会被链接到目标代码中,而是在执行文件中记录对动态库的引用,在程序运行时才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题。动态库在程序运行时才被载入,也解决了静态库对程序的更新、部署和发布带来的麻烦,用户只需要更新动态库即可,增量更新。

    Linux下动态库文件的文件名形如 libxxx.so,其中so是 Shared Object 的缩写,即可以共享的目标文件。

    特点

    • 动态库把对一些库函数的链接载入推迟到程序运行的时期
    • 可以实现进程之间的资源共享。(因此动态库也称为共享库)
    • 将一些程序升级变得简单。
    • 甚至可以真正做到链接载入完全由程序员在程序代码中控制(显示调用)

    生成动态链接库

    1. 编写源文件
    2. 将一个或几个源文件编译链接,生成共享库。
    3. 通过 -L<path> -lxxx 的gcc选项链接生成的libxxx.so。
    4. 把 libxxx.so 放入链接库的标准路径,或指定 LD_LIBRARY_PATH,才能运行链接了libxxx.so的程序。

    例子

    源文件

    add.c

    int add(int a, int b)
    {
            return a + b;
    }

    subtract.c

    int subtract(int a, int b)
    {
            return a - b;
    }

    编译

    gcc -fPIC -c add.c
    gcc -fPIC -c subtract.c

    其中,PIC是 Position Independent Code 的缩写,表示要生成位置无关的代码,这是动态库需要的特性

    链接

    gcc -shared -o libmymath.so subtract.o add.o

    -shared是链接选项,告诉gcc生成动态库而不是可执行文件

    这两步可以合并成一个命令:

    gcc -o libmymath.so -fPIC -shared subtract.c add.c

    编写头文件

    #ifndef _MYMATH_H_
    #define _MYMATH_H_
    
    int add(int, int);
    int subtract(int, int);
    
    #endif

    使用链接库

    main.c

    #include <stdio.h>
    #include "mymath.h"
    
    
    int main()
    {
            printf("%d, %d
    ", add(2, 3), subtract(9, 8));
    
            return 0;
    }

    链接

    gcc main.c -L. -lmymath

    如果同一目录下同时存在同名的动态库和静态库,比如 libmymath.so 和 libmymath.a 都在当前路径下,则gcc会优先链接动态库。

    运行

    当执行 ./a.out,发现程序报错

    ./a.out: error while loading shared libraries: libmymath.so: cannot open shared object file: No such file or directory

    这涉及到程序如何定位共享库文件

    1. 当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径。此时就需要系统动态载入器(dynamic linker/loader)
    2. 对于elf格式的可执行程序,是由ld-linux.so*来完成的,它先后搜索elf文件的 DT_RPATH段 -- 环境变量LD_LIBRARY_PATH -- /etc/ld.so.cache文件列表 -- /lib/,/usr/lib 目录找到库文件后将其载入内存。

    /etc/ld.so.cache 是 ldconfig 程序读取 /etc/ld.so.conf 文件生成的

    所以,我们想让程序找到自己写的动态链接库,有如下方法:

    • 指定 LD_LIBRARY_PATH 环境变量为 libmymath.so 文件所在的目录
    • 编辑/etc/ld.so.conf文件,加入库文件所在目录的路径; 同时,运行ldconfig ,该命令会重建/etc/ld.so.cache文件
    • 把 libmymath.so 拷贝到/lib或者/usr/lib下,那么ld默认能够找到,无需其他操作

    我们可以执行:

    LD_LIBRARY_PATH=. ./a.out

    Makefile

    .PHONY: all
    
    all: build target
    
    build: libmymath.so
    libmymath.so: add.o subtract.o
            gcc -o $@ -shared $^
    add.o: add.c
            gcc -c -fPIC $<
    subtract.o: subtract.c
            gcc -c -fPIC $<
    
    target: a.out
    a.out: main.c
            gcc main.c -L. -lmymath
    
    .PHONY: clean
    clean:
            rm *.o a.out libmymath.so
  • 相关阅读:
    js点击重置按钮重置表单
    Flash文件在asp页面无法播放,网页上面的Flash文件在火狐浏览器不播放
    更新域名解析以后,IP在cmd中ping不正确,清理DNS缓存
    简单PHP会话(session)说明
    delphi 事件和属性的绑定
    读书笔记(乡土中国)
    读书笔记(支付战争)
    读书笔记(从0到1)
    读书笔记(创业维艰)
    读书笔记(三体)
  • 原文地址:https://www.cnblogs.com/zuofaqi/p/10440754.html
Copyright © 2020-2023  润新知