高级C/C++编译技术之读书笔记(四)之定位库文件

本节思维导图1.linux库命名规则(1)静态库:lib+<libraryname>.+a(2)动态库:lib+<<libraryname>+.so

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

                                                                                    高级C/C++编译技术之读书笔记(四)之定位库文件

  最近有幸阅读了《高级C/C++编译技术》深受启发,该书深入浅出地讲解了构建过程(编译、链接)中的各种细节,从多个角度展示了程序与库文件或代码的集成方法,提出了面向代码复用和系统集成的软件架构设计方法,以及系统开发过程中疑难问题的解决方案。

  以下将回头记录下其中的关键要点,以便后面查阅。

本节思维导图

高级C/C++编译技术之读书笔记(四)之定位库文件

1. linux库命名规则

(1)静态库:lib+<library name>. + a

(2)动态库:lib+<<library name> + .so + <library version information>

(3)动态库的版本信息

  dynamic libaray version information = <M>.<m>.<p>

  M:主版本号

  m:次版本号

  p:补丁(很小的代码改动)版本号

(4)动态库的soname

  soname = lib+<libaray name>+.so+M

  动态库的soname通常由连接器嵌入二进制文件的专有ELF字段中,通常用特定的连接器选项,将表示库soname的字符串传递给链接器

g++ -shared <list of object files> -Wl, -soname, libfoo.so.1 -o libfoo.so.1.0.0

注意:(1)-Wl选项告诉编译器将后面的参数传递给链接器

   (2)凡是间接调用链接器时,我们需要在链接器参数前追加“Wl,”

2. 构建过程中库文件定位规则

  在Linux中用-L和-l选项来指定构建过程中库文件路径

(1)将完整的库文件路径分成两个部分:目录路径和库文件名

(2)将目录路径添加到-L连接器选项后面,并传递给链接器

(3)将库文件名添加到-l参数后面,并传递给连接器

g++ main.o -L../sharedlib -lwokingdemo -o demo

在使用g++命令行一次性完整编译链接两个过程时,应在在链接器前添加-Wl,

g++ -Wall -fPIC main.cpp -Wl, -L../sharedlib -Wl, -lworkingdeno -o demo

3. 运行时动态库文件定位规则

  对于经验不足的linux软件工程师经常会遇到找到不动态库的情况而不知所措,主要是对以下内容不够了解。

  动态库运行时搜索算法由一组规则约束,按照优先级从高到低列出

(1)预加载库

  毫无疑问,预加载库应该拥有最高的搜索优先级,装载器会首先加载这些库,然后才开始搜索其它库,有两种方法可以指定预加载库

a:通过设置LD_PRELOAD环境变量

export LD_PRELOAD=/home/fate/shareddir/libtest.so:$LD_PRELOAD

b:通过修改、etc/ld.so.preload文件

指定预加载库并不符合标准的设计规范。相反,该方案仅用于特殊情况,比如设计压力测试、诊断已经对原始代码的紧急补丁等

(2)rpath

  rpath和runpath都可供我们使用,但是runpath在运行时搜索优先级列表中赋予了更高的优先级,只有在runpath缺失的情况下,rpath才是linux装载器剩余的搜索路径信息中具有最高优先级的。

  但如果ELF二进制文件的runpath(DT_RUNPATH)字段是非空的,那么rpath会被忽略

g++ -Wl, -R/home/fate/shared/ -ltestlibrary

  或者,也可以用LD_RUN_PATH环境变量来设置rpath

export LD_RUN_PATH=/home/fate/shared:$LD_RUN_PATH

(3)LD_LIBARAY_PATH

  从库搜索概念发展初期开始,开发人员就希望可以使用一种临时应急的有效机制来验证它们的设计,通过特定的环境变量(LD_LIBRARY_PATH)就能解决我们遇到的问题,当没有rpath时,该路径就是路径搜索信息中优先级最高的

export LD_LIBRARY_PATH=/home/fate/shared/:$LD_LIBRARY_PATH

注意:该机制只应用于实验目的,软件产品的产品版本不应该依赖于这种机制

 (4)runpath

  设置runpath的方法和设置rpath的方法非常相似,为了传递-R或-rpath链接器选项,需要使用额外的–enable-new-dtags链接选项

g++ -Wl,-R/home/fate/shared/ -Wl, --enable-new-dtags -ltestlibrary

(5)ldconfig缓存

  一种标准的代码部署过程是基于运行linux的ldconfig工具,ldconfig会将指定的目录路径插入动态库搜索列表中,该列表维护在文件/etc/ld.so.conf中。同样地,系统会扫描新加入的目录路径,其结果是将发现的库文件名添加到库文件名列表中,该表维护在/etc/ld.so.cache文件中

4. 默认库文件路径

  /lib和/usr/lib是linux操作系统保存动态库的两个默认路径

5. 优先级方案小节

  总的来说,优先级方案可以归纳为以下两种版本:

(1)如果指定了RUNPATH(即LD_RUNPATH字段非空)

  a. LD_LIBRARY_PATH

  b. runpath(LD_RUNPATH)

  c. ld.so.cache

  d. 默认路径

(2)如果没有指定runpath

  a. 被加载库的RPATh,然后是二进制文件的RPATH,直到可执行文件或者动态库将这些库全部加载完毕为止

  b. LD_LIBRAYR_PATH

  c. ld.so.cache

  d. 默认路径

6.示例:动态库的创建和函数调用

linux_so.h

#pragma once

#ifdef __cplusplus
extern "C"
{
#endif
void fun();
#ifdef __cplusplus
}
#endif

linux_so.c

#include "linux_so.h"

#include <iostream>
using namespace std;

void fun()
{
    cout << "print fun" << endl;
}

main.c

#include "stdio.h"

#include "linux_so.h"

int main()
{
    fun();
    return 0;
}

编译、链接

g++ -Wall -g -o0 -fPIC -shared linux_so.c -o liblinux_so.so

 g++ -Wall -g -o0 -fPIC main.c -Wl,-L./ -Wl,-llinux_so -o out

  export LD_LIBRARY_PATH=/home/fate/sharedir/dlltest/:$LD_LIBRAYR_PATH

 输出

高级C/C++编译技术之读书笔记(四)之定位库文件

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/120107.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 小米6X 解BL锁教程 申请BootLoader解锁教程[通俗易懂]

    小米6X 解BL锁教程 申请BootLoader解锁教程[通俗易懂]小米6X线刷兼救砖_解账户锁_纯净刷机包_教程一、准备工作1、注册小米账号:点击注册(已有小米账号请忽视)2、在手机中登陆【小米账号】3、下载并解压【小米解锁工具】或点击这里下载安装二、开始解锁1打开【小米解锁官网】:http://www.miui.com/unlock/,点击【立即解锁】,输入【小米账号】,点击【立即登录】,填写好上诉信息后,点击【立即申请】,输入【短…

    2022年5月18日
    60
  • css transition ease,css3 transition属性「建议收藏」

    css transition ease,css3 transition属性「建议收藏」最近打算学习css3知识,觉得css3写出来的效果好炫好酷,之前一直想要学习来着。可能之前的决心,毅力,耐心不够,所以想要重整起来,放下浮躁的心态,一步一个脚印,踏踏实实的来学习。首先学习的是css3transition属性,该属性的定义为从一个属性值平滑过渡到另一个属性值。格式为:transition:,或transition-property:transition-duration:tr…

    2022年7月14日
    18
  • java8 stream流操作的flatMap(流的扁平化)

    java8 stream流操作的flatMap(流的扁平化)flatMap的用法和含义住要通过一个案例来讲解,案例:对给定单词列表["Hello","World"],你想返回列表["H","e","l","o","W","r","d"]第一种方式String[]words=newString[]{"Hello","World&quot

    2022年6月2日
    43
  • 3D编程软件(3d动画需要编程吗)

    本篇文章中,我们学习了UnityShader的基本写法框架,以及学习了Shader中Properties(属性)的详细写法,光照、材质与颜色的具体写法。写了6个Shader作为本文Shader讲解的实战内容,最后创建了一个逼真的暴风雪场景进行了Shader的测试。依旧是国际惯例先上本文配套程序的截图。先是一张远眺图:

    2022年4月11日
    37
  • 潜意识的牢笼——为什么这件事情这么难

    潜意识的牢笼——为什么这件事情这么难

    2021年8月26日
    62
  • callable线程使用_java线程结束用什么方法

    callable线程使用_java线程结束用什么方法接着上一篇继续并发包的学习,本篇说明的是Callable和Future,它俩很有意思的,一个产生结果,一个拿到结果。Callable接口类似于Runnable,从名字就可以看出来了,但是Runnable不会返回结果,并且无法抛出返回结果的异常,而Callable功能更强大一些,被线程执行后,可以返回值,这个返回值可以被Future拿到,也就是说,Future可以拿到异步执行任务的返

    2025年8月21日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号