美文网首页代码改变世界程序员coding
Linux 静态库 和 动态库的使用

Linux 静态库 和 动态库的使用

作者: LGmark | 来源:发表于2016-11-11 18:04 被阅读1585次

    静态库

    1、概念

    静态库 是在可执行程序运行之前就已经加入到执行代码中,成为执行程序的一部分;静态库的后缀一般是 .a作为后缀。

    2、创建静态库

    创建一个静态库,或者是要将目标代码加入到已经存在的静态库中,可以使用如下命令:
    ar rcs libxxx.a hello.o
    ar 是GNU 归档工具,rcs 表示(replace and create)

    3、应用程序中使用静态库

    使用gcc 的 -l 选项来指定静态库,使用 -L 选项来指定库文件的搜索路径。
    样例
    如果我们使用 目录/home/username/publiclibabc.a 静态库,则需指定静态库的目录 -L/home/username/public (注意 -L 后面是没有空格的),指定静态库 -labc

    注意:
    因为linux的gcc 默认链接动态库,但动态库不存在时,才链接静态库,若是需要强制指定静态库需要指定选项 -static

    4、静态库链接时搜索路径顺序:

    • ld回去找GCC命令中的参数-L
    • 再去找GCC的环境变量LIBRARY_PATH
    • 再找内定目录/lib /usr/lib /usr/local/lib 这是当初compiler gcc时写在程序内的动态链接时、执行时搜索路径顺序

    共享库

    1、概念

    共享库 是在程序执行期间需要调用到共享库的时候才加载到内存里面,可以被多个程序共享使用;每个共享库都有三个文件名:real namesonamelinker name

    //real name
    -rwxr-xr-x 1 root root  11511640  libavcodec.so.57.24.102
    //soname
    lrwxrwxrwx 1 root root   libavcodec.so.57 -> libavcodec.so.57.24.102
    //linker name
    lrwxrwxrwx 1 root root   libavcodec.so -> libavcodec.so.57.24.102
    

    real name:真正的库文件,包含库文件的完整版本号
    soname:符号链接的名字,只包含共享库的主版本号(主版本号相同,函数的接口是一致的);因此应用程序的.dynamic段只记录共享库的soname,只要soname一致,这个共享库就可以用。
    linker name:在编译链接时使用,gcc 的-L选项应该指定linker name所在目录

    2、创建动态库

    简单的创建动态库使用如下命令:
    gcc -shared -fPIC abc.c -o libabc.so

    3、加载共享库

    链接路径
    连接时找不到某一个函数,出现xxxxx undefined,应该就是连接时找不到相应的动态库,连接时动态库的路径如下:

    • 默认路径是:/lib, /usr/lib/, /usr/local/lib
    • -L: 指定连接时动态库的路径
    • LD_LIBRARY_PATH:指定连接路径

    运行路径
    运行应用程序时出现 error while loading shared libraries,则是加载时找不到相应的动态库

    • ELF可执行文件中动态段中DT_RPATH所指定的路径。这实际上是通过一种不算很常用,却比较实用的方法所设置的:编译目标代码时,可以对gcc加入链接参数-Wl,-rpath指定动态库搜索路径;
    • 环境变量LD_LIBRARY_PATH指定的动态库搜索路径;
    • /etc/ld.so.cache中所缓存的动态库路径(如果支持ld.so.cache的话)。这可以通过修改配置文件/etc/ld.so.conf中指定的动态库搜索路径来改变;
    • 默认的动态库搜索路径/lib;
    • 默认的动态库搜索路径/usr/lib。

    样例

    1、创建一个目录 calc

    mkdir /home/username/calc

    2、创建1个c文件和1个.h,实现加减乘除

    文件 calc.c

    int add(int a, int b)
    {
        return a+b;
    }
    
    int sub(int a, int b)
    {
        return a-b;
    }
    
    int mul(int a, int b)
    {
        return a*b;
    }
    
    int dive(int a, int b)
    {
        return a/b;
    }
    

    calc.h

    #ifndef CALC_H_
    #define CALC_H_
    
    int add(int a, int b);
    int sub(int a, int b);
    int dive(int a, int b);
    int mul(int a, int b);
    
    #endif
    

    3、制作静态库

        gcc -c calc.c -o calc.o
        ar rcs libcalc.a calc.o
    

    4、制作共享库

        gcc -c -fPIC calc.c
        gcc -shared -Wl,-soname,libcalc.so.1 -o libcalc.so.1.10 calc.o
    

    5、设置共享库加载路径

    • 打开共享库路径配置文件:sudo vi /etc/ld.so.conf
    • 最后一行添加mycal路径:/home/username/calc
    • 更新共享库加载路径:sudo ldconfig -v
    • 此时可以看到自动创建出来了soname libcalc.so.1
    • 手动添加link name:ln -s libcalc.so.1.10 libcalc.so

    6、测试

    编写测试文件main.c,分别去链接静态库和共享库,进行测试
    文件 main.c

    #include <stdio.h>
    #include "common.h"
    int main(void)
    {
        printf("%d\n", add(5, 3));
        return 0;
    }
    

    链接动态库: gcc main.c -o main -Wl,-rpath=./ -lcalc

    相关文章

      网友评论

        本文标题:Linux 静态库 和 动态库的使用

        本文链接:https://www.haomeiwen.com/subject/nymfpttx.html