• 关于共享库的那些事儿


    关于共享库的那些事儿

    零散的知识点 不断添加

    关于 -fPIC

    -fPIC
        If supported for the target machine, emit position-independent code, suitable for dynamic
        linking and avoiding any limit on the size of the global offset table.  This option makes a
        difference on AArch64, m68k, PowerPC and SPARC.
    
        Position-independent code requires special support, and therefore works only on certain
        machines.
    
        When this flag is set, the macros "__pic__" and "__PIC__" are defined to 2.
    

    pic 就是 position independent code PIC使.so文件的代码段变为真正意义上的共享 如果不加-fPIC,则加载.so文件的代码段时,代码段引用的数据对象需要重定位, 重定位会修改代码段的内容,这就造成每个使用这个.so文件代码段的进程在内核里都会生成这个.so文件代码段的copy.每个copy都不一样,取决于 这个.so文件代码段和数据段内存映射的位置.

    也就是不加fPIC编译出来的so,是要再加载时根据加载到的位置再次重定位的.(因为它里面的代码并不是位置无关代码)
    如果被多个应用程序共同使用,那么它们必须每个程序维护一份.so的代码副本了.(因为.so被每个程序加载的位置都不同,显然这些重定位后的代码也不同,当然不能共享)

    我们总是用fPIC来生成so,也从来不用fPIC来生成.a;fPIC与动态链接可以说基本没有关系,libc.so一样可以不用fPIC编译,只是这样的so必须要在加载到用户程序的地址空间时重定向所有表目.

    不用fPIC编译so并不总是不好.如果你满足以下4个需求/条件:

    1. 该库可能需要经常更新
    2. 该库需要非常高的效率(尤其是有很多全局量的使用时)
    3. 该库并不很大.
    4. 该库基本不需要被多个应用程序共享

    不加fPIC编译的 so文件的优点是加载速度比较快。

    如果用没有加这个参数的编译后的共享库,也可以使用的话,可能是两个原因:

    1. gcc默认开启-fPIC选项
    2. loader使你的代码位置无关

    从GCC来看,shared应该是包含fPIC选项的,但似乎不是所以系统都支持,所以最好显式加上fPIC选项

    -fpic为了节约内存,在GOT里面预留了“短”长度。
    而-fPIC则采用了更大的跳转项

    -- 老徐 gcc编译参数-fPIC的一些问题 http://blog.sina.com.cn/s/blog_54f82cc201011op1.html

    关于链接, 注意顺序

    gcc main.c -L ./ -lcom # 可以编译
    gcc -L ./ -lcom main.c   # 不能编译
    

    关于寻找库

    程序在编译链接时,编译器是按照如下顺序来查找动态链接库(共享库)和静态链接库的:

    1. gcc会先按照-Ldir -Bprefix选项指定的路径查找
    2. 再找gcc的环境变量GCC_EXEC_PREFIX
    3. 再找gcc的环境变量LIBRARY_PATH
    4. 然后查找GCC安装的目录(可以通过gcc -print-search-dirs查询)
    5. 然后查找默认路径/lib
    6. 然后查找默认路径/usr/lib
    7. 最后查找默认路径/usr/local/lib
    8. 在同一个目录下,如果有相同文件名的库(只是后缀不同),那么默认链接的是动态链接库,可以用-static选项显示的指定链接静态库。

    程序运行时动态库的搜索路径搜索的先后顺序是:

    1. 环境变量LD_LIBRARY_PATH指定的动态库搜索路径;
    2. 编译目标代码时指定的动态库搜索路径(指的是用-wl,rpath或-R选项而不是-L);
      example: gcc -Wl,-rpath,/home/arc/test,-rpath,/lib/,-rpath,/usr/lib/,-rpath,/usr/local/lib test.c
    3. 配置文件/etc/ld.so.conf中指定的动态库搜索路径;
    4. 默认的动态库搜索路径/lib;
    5. 默认的动态库搜索路径/usr/lib。

    在上述1、2、3指定动态库搜索路径时,都可指定多个动态库搜索路径,其搜索的先后顺序是按指定路径的先后顺序搜索的

    在这里补充说明下:gcc的-Wl,rpath选项可以设置动态库所在路径,也就是编译生成的该程序在运行时将到-Wl,rpath所指定的路径下去寻找动态库,如果没找到则到其它地方去找,并且这个路径会直接写在elf文件(就是生成的可执行文件)中,这样可以免去设置LD_LIBRARY_PATH。注意,gcc参数设定时-Wl,rpath,/path/to/lib, 中间不能有空格。

    下面对编译时库的查找与运行时库的查找做一个简单的比较

    1. 编译时查找的是静态库或动态库,而运行时,查找的只是动态库。
    2. 编译时可以用-L指定查找路径,或者用环境变量LIBRARY_PATH,而运行时可以用-Wl,rpath或-R选项,或者修改/etc/ld.so.conf文件或者设置环境变量LD_LIBRARY_PATH.
    3. 编译时用的链接器是ld,而运行时用的链接器是/lib/ld-linux.so.2.
    4. 编译时与运行时都会查找默认路径:/lib /usr/lib
    5. 编译时还有一个默认路径:/usr/local/lib,而运行时不会默认找查该路径。

    -- seamus 程序编译运行时头文件或动态链接库的查找 https://blog.csdn.net/dlutxie/article/details/6776936

  • 相关阅读:
    主流数据可视化工具介绍:帆软FineBI
    AngularJS之表格序号
    AngularJS之表格设置样式
    正则点号和问号 +
    中国市场主流商业智能工具的对比
    ssh 认证指定端口
    EL表达式中获取list长度
    java 如何将byte中的有效长度转换为String
    RedHat Enterprise Linux 6.4-x86_64 md5:467B53791903F9A0C477CBB1B24FFD1F
    14.5.5.3 How to Minimize and Handle Deadlocks 如何减少和处理死锁
  • 原文地址:https://www.cnblogs.com/Kimbing-Ng/p/12457548.html
Copyright © 2020-2023  润新知