Linux动态库(.so)搜索路径

2023-11-05

Linux动态库(.so)搜索路径    众所周知,Linux动态库的默认搜索路径是/lib和/usr/lib。动态库被创建后,一般都复制到这两个目录中。当程序执行时需要某动态库,并且该 动 态库还未加载到内存中,则系统会自动到这两个默认搜索路径中去查找相应的动态库文件,然后加载该文件到内存中,这样程序就可以使用该动态库中的函数,以及 该动态库的其它资源了。在Linux 中,动态库的搜索路径除了默认的搜索路径外,还可以通过以下三种方法来指定。

方法一:在配置文件/etc/ld.so.conf中指定动态库搜索路径。

可以通过编辑配置文件/etc/ld.so.conf来指定动态库的搜索路径,该文件中每行为一个动态库搜索路径。每次编辑完该文件后,都必须运行命令ldconfig使修改后的配置生效。我们通过例1来说明该方法。

例1:

我们通过以下命令用源程序pos_conf.c(见程序1)来创建动态库 libpos.so,详细创建过程请参考文[1]。

# gcc -c pos_conf.c
         # gcc -shared -fPCI -o libpos.so pos_conf.o
         #

 #include <stdio.h>
          void pos()
          {
                 printf("/root/test/conf/lib\n");
          }
           程序1: pos_conf.c

接着通过以下命令编译main.c(见程序2)生成目标程序pos。

 # gcc -o pos main.c -L. -lpos
          #

 void pos();
         int main()
         {
              pos();
              return 0;
         }
         程序2: main.c

然后把库文件移动到目录/root/test/conf/lib中。

 # mkdir -p /root/test/conf/lib
          # mv libpos.so /root/test/conf/lib
          #

最后编辑配置文件/etc/ld.so.conf,在该文件中追加一行"/root/test/conf/lib"。

运行程序pos试试。

 # ./pos
          ./pos: error while loading shared libraries: libpos.so: cannot open shared object file: No such file or directory
          #

出错了,系统未找到动态库libpos.so。找找原因,原来在编辑完配置文件/etc/ld.so.conf后,没有运行命令ldconfig,所以刚才的修改还未生效。我们运行ldconfig后再试试。

 # ldconfig
          # ./pos
           /root/test/conf/lib 
          #

程序pos运行成功,并且打印出正确结果。

方法二:通过环境变量LD_LIBRARY_PATH指定动态库搜索路径。

通过设定环境变量LD_LIBRARY_PATH也可以指定动态库搜索路径。当通过该环境变量指定多个动态库搜索路径时,路径之间用冒号":"分隔。下面通过例2来说明本方法。

例2:

我们通过以下命令用源程序pos_env.c(见程序3)来创建动态库libpos.so。

 # gcc -c pos_env.c
          # gcc -shared -fPCI -o libpos.so pos_env.o
          #

#include <stdio.h>
         void pos()
         {
               printf("/root/test/env/lib\n");
         }
         程序3: pos_env.c

测试用的可执行文件pos可以使用例1中的得到的目标程序pos,不需要再次编译。因为pos_conf.c中的函数pos和pos_env.c中的函数pos 函数原型一致,且动态库名相同,这就好比修改动态库pos后重新创建该库一样。这也是使用动态库的优点之一。

然后把动态库libpos.so移动到目录/root/test/conf/lib中。

 # mkdir -p /root/test/env/lib
          # mv libpos.so /root/test/env/lib
          #

我们可以使用export来设置该环境变量,在设置该环境变量后所有的命令中,该环境变量都有效。

例如:

 # export LD_LIBRARY_PATH=/root/test/env/lib
          #

但本文为了举例方便,使用另一种设置环境变量的方法,既在命令前加环境变量设置,该环境变量只对该命令有效,当该命令执行完成后,该环境变量就无效了。如下述命令:

# LD_LIBRARY_PATH=/root/test/env/lib ./pos
         /root/test/env/lib
         #

程序pos运行成功,并且打印的结果是"/root/test/env/lib",正是程序pos_env.c中的函数pos的运行结果。因此程序pos搜索到的动态库是/root/test/env/lib/libpos.so。

方法三:在编译目标代码时指定该程序的动态库搜索路径。

还可以在编译目标代码时指定程序的动态库搜索路径。这是通过gcc 的参数"-Wl,-rpath,"指定(如例3所示)。当指定多个动态库搜索路径时,路径之间用冒号":"分隔。

例3:

我们通过以下命令用源程序pos.c(见程序4)来创建动态库libpos.so。

 # gcc -c pos.c
          # gcc -shared -fPCI -o libpos.so pos.o
          #

#include <stdio.h>
         void pos()
         {
               printf("./\n");
         }
         程序4: pos.c

因为我们需要在编译目标代码时指定可执行文件的动态库搜索路径,所以需要用gcc命令重新编译源程序main.c(见程序2)来生成可执行文件pos。

# gcc -o pos main.c -L. -lpos -Wl,-rpath,./
         #

再运行程序pos试试。

 # ./pos
          ./
          #

 

程序pos运行成功,输出的结果正是pos.c中的函数pos的运行结果。因此程序pos搜索到的动态库是./libpos.so。

以上介绍了三种指定动态库搜索路径的方法,加上默认的动态库搜索路径/lib和/usr/lib,共五种动态库的搜索路径,那么它们搜索的先后顺序是什么呢?

在 介绍上述三种方法时,分别创建了动态库./libpos.so、 /root/test/env/lib/libpos.so和/root/test/conf/lib/libpos.so。我们再用源程序 pos_lib.c(见程序5)来创建动态库/lib/libpos.so,用源程序pos_usrlib.c(见程序6)来创建动态库 /usr/lib/libpos.so。

 #include <stdio.h>
          void pos()
          {
                  printf("/lib\n");
          }
           程序5: pos_lib.c

#include <stdio.h>
         void pos()
         {
                printf("/usr/lib\n");
         }
         程序6: pos_usrlib.c

这 样我们得到五个动态库libpos.so,这些动态库的名字相同,且都包含相同函数原型的公用函数pos。但存储的位置不同和公用函数pos 打印的结果不同。每个动态库中的公用函数pos都输出该动态库所存放的位置。这样我们可以通过执行例3中的可执行文件pos得到的结果不同获知其搜索到了 哪个动态库,从而获得第1个动态库搜索顺序,然后删除该动态库,再执行程序pos,获得第2个动态库搜索路径,再删除第2个被搜索到的动态库,如此往复, 将可得到Linux搜索动态库的先后顺序。程序pos执行的输出结果和搜索到的动态库的对应关系如表1所示:

程序pos输出结果 使用的动态库 对应的动态库搜索路径指定方式
./ ./libpos.so 编译目标代码时指定的动态库搜索路径
/root/test/env/lib /root/test/env/lib/libpos.so 环境变量LD_LIBRARY_PATH指定的动态库搜索路径
/root/test/conf/lib /root/test/conf/lib/libpos.so 配置文件/etc/ld.so.conf中指定的动态库搜索路径
/lib /lib/libpos.so 默认的动态库搜索路径/lib
/usr/lib /usr/lib/libpos.so 默认的动态库搜索路径/usr/lib
表1: 程序pos输出结果和动态库的对应关系

创建各个动态库,并放置在相应的目录中。测试环境就准备好了。执行程序pos,并在该命令行中设置环境变量LD_LIBRARY_PATH。

 # LD_LIBRARY_PATH=/root/test/env/lib ./pos
          ./
          #

根据程序pos的输出结果可知,最先搜索的是编译目标代码时指定的动态库搜索路径。然后我们把动态库./libpos.so删除了,再运行上述命令试试。

# rm libpos.so
         rm: remove regular file `libpos.so'? y
         # LD_LIBRARY_PATH=/root/test/env/lib ./pos
         /root/test/env/lib
         #

根据程序pos的输出结果可知,第2个动态库搜索的路径是环境变量LD_LIBRARY_PATH指定的。我们再把/root/test/env/lib/libpos.so删除,运行上述命令。

# rm /root/test/env/lib/libpos.so
         rm: remove regular file `/root/test/env/lib/libpos.so'? y
         # LD_LIBRARY_PATH=/root/test/env/lib ./pos
         /root/test/conf/lib
         #

第3个动态库的搜索路径是配置文件/etc/ld.so.conf指定的路径。删除动态库/root/test/conf/lib/libpos.so后再运行上述命令。

# rm /root/test/conf/lib/libpos.so
         rm: remove regular file `/root/test/conf/lib/libpos.so'? y
         # LD_LIBRARY_PATH=/root/test/env/lib ./pos
         /lib
         #

第4个动态库的搜索路径是默认搜索路径/lib。我们再删除动态库/lib/libpos.so,运行上述命令。

# rm /lib/libpos.so
         rm: remove regular file `/lib/libpos.so'? y
         # LD_LIBRARY_PATH=/root/test/env/lib ./pos
         /usr/lib
         #

最后的动态库搜索路径是默认搜索路径/usr/lib。

综合以上结果可知,动态库的搜索路径搜索的先后顺序是:

1.编译目标代码时指定的动态库搜索路径;

2.环境变量LD_LIBRARY_PATH指定的动态库搜索路径;

3.配置文件/etc/ld.so.conf中指定的动态库搜索路径;

4.默认的动态库搜索路径/lib;

5.默认的动态库搜索路径/usr/lib。

在上述1、2、3指定动态库搜索路径时,都可指定多个动态库搜索路径,其搜索的先后顺序是按指定路径的先后顺序搜索的。对此本文不再举例说明,有兴趣的读者可以参照本文的方法验证。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux动态库(.so)搜索路径 的相关文章

  • 我们真的应该使用 Chef 来管理 sudoers 文件吗?

    这是我的问题 我担心如果 Chef 破坏了 sudoers 文件中的某些内容 可能是 Chef 用户错误地使用了说明书 那么服务器将完全无法访问 我讨厌我们完全失去客户的生产服务器 因为我们弄乱了 sudoers 文件并且无法再通过 ssh
  • 如何在 Bazel 中禁用 C/C++ `-Werror` 构建错误? (又名:如何关闭已由“-Wall -Werror”打开的特定警告)

    我在构建时遇到以下错误 has undefined behavior Werror Wundefined reinterpret cast Bazel 构建从此完全停止clang llvm编译器 Wundefined reinterpret
  • Linux 上的静态 Qt5 构建:部署时如何处理字体?

    我使用这些配置选项创建了 Qt 5 2 0 库的静态版本 Ubuntu 12 04 开源 确认许可 force pkg config 发布 静止的 前缀 home juzzlin qt5 无icu opengl桌面 无油嘴滑舌 辅助功能 n
  • 就分页分段内存而言的程序寿命

    我对 x86 Linux 机器中的分段和分页过程有一个令人困惑的概念 如果有人能澄清从开始到结束所涉及的所有步骤 我们将很高兴 x86 使用分页分段内存技术进行内存管理 任何人都可以解释一下从可执行的 elf 格式文件从硬盘加载到主内存到它
  • 如何在 Ubuntu 中创建公共 HTML 文件夹?

    简单的问题 但由于某种原因我无法在谷歌上找到确切的答案 我在 Slicehost 上安装了全新的 Ubuntu 并且想在我的主目录中为包含一堆静态 HTML 文件的简单网站创建一个公共目录 我该怎么做呢 只是打字的问题吗mkdir publ
  • CMake 链接 glfw3 lib 错误

    我正在使用 CLion 并且正在使用 glfw3 库编写一个程序 http www glfw org docs latest http www glfw org docs latest 我安装并正确执行了库中的所有操作 我有 a 和 h 文
  • 在 Mono 上运行 .Net MVC5 应用程序

    我正在 Windows 上的 Visual Studio 2013 中开发 Net 4 5 1 MVC5 应用程序 现在我想知道 是否可以在Linux Ubuntu 12 04 上运行这个应用程序 可以使用OWIN吗 Owin 可以自托管运
  • 使用包管理器时如何管理 Perl 模块?

    A 最近的问题 https stackoverflow com questions 397817 unable to find perl modules in intrepid ibex ubuntu这让我开始思考 在我尝试过的大多数 Li
  • 如何在 Linux 中使用 C 语言使用共享内存

    我的一个项目有点问题 我一直在试图找到一个有据可查的使用共享内存的例子fork 但没有成功 基本上情况是 当用户启动程序时 我需要在共享内存中存储两个值 当前路径这是一个char and a 文件名这也是char 根据命令参数 启动一个新进
  • C修改printf()输出到文件

    有没有办法修改printf为了将字符串输出到文件而不是控制台 我尝试在互联网上查找一些内容 发现了类似的电话dup dup2 and fflush这可能与此有关 EDIT 也许我不清楚 问题是这是C考试问题 问题如下 解释一个通常将字符串输
  • 使用 python 脚本更改 shell 中的工作目录

    我想实现一个用户态命令 它将采用其参数之一 路径 并将目录更改为该目录 程序完成后 我希望 shell 位于该目录中 所以我想实施cd命令 但需要外部程序 可以在 python 脚本中完成还是我必须编写 bash 包装器 Example t
  • `cosf`、`sinf` 等不在 `std` 中 [重复]

    这个问题在这里已经有答案了 根据这里的讨论 我有报告了一个错误 https bugs launchpad net ubuntu source gcc 8 bug 1831385给 Ubuntu 开发者 编译以下示例 C 程序时 includ
  • 绕过 dev/urandom|random 进行测试

    我想编写一个功能测试用例 用已知的随机数值来测试程序 我已经在单元测试期间用模拟对其进行了测试 但我也希望用于功能测试 当然不是全部 最简单的方法是什么 dev urandom仅覆盖一个进程 有没有办法做类似的事情chroot对于单个文件并
  • 如何在 *nix 中登录时运行脚本?

    我知道我曾经知道如何做到这一点 但是 如何在 unix 中登录时运行脚本 bash 可以 From 维基百科 Bash http en wikipedia org wiki Bash 28Unix shell 29 当 Bash 启动时 它
  • Linux 为一组进程保留一个处理器(动态)

    有没有办法将处理器排除在正常调度之外 也就是说 使用sched setaffinity我可以指示线程应该在哪个处理器上运行 但我正在寻找相反的情况 也就是说 我想从正常调度中排除给定的处理器 以便只有已明确调度的进程才能在那里运行 我还知道
  • linux下如何从文本文件中获取值

    我有一些文本格式的文件 xxx conf 我在这个文件中有一些文本 disablelog 1 当我使用 grep r disablelog oscam conf 输出是 disablelog 1 但我只需要值1 请问你有什么想法吗 一种方法
  • 如何在数据部分(RAM)中保留一定范围的内存并防止同一应用程序使用该内存的堆/堆栈?

    我想在 RAM 中保留 分配一定范围的内存 并且同一应用程序不应覆盖或使用该范围的内存进行堆 堆栈存储 如何在内存中分配一定范围的内存以防止堆栈 堆覆盖 我考虑过向应用程序本身添加 或分配 一个数组并保留内存 但它被编译器优化了 因为它在应
  • 如何使用Android获取Linux内核的版本?

    如何在 Android 应用程序中获取 Linux 内核的版本 不是 100 确定 但我认为调用 uname r 需要 root 访问权限 无论如何 有一种不太肮脏的方法可以做到这一点 那就是 System getProperty os v
  • 使用os.execlp时,为什么`python`需要`python`作为argv[0]

    代码是这样的 os execlp python python child py other args this works os execlp python child py other args this doesn t work 我读过
  • 如何在 Mac OSX Mavericks 中正确运行字符串工具?

    如何在 Mac OSX Mavericks 中正确运行字符串工具 我尝试按照我在网上找到的示例来运行它 strings a UserParser class 但我收到此错误 错误 Applications Xcode app Content

随机推荐

  • 【MySQL】数据处理函数

    函数 文本处理函数 日期和时间处理函数 数值处理函数 函数 SQL支持利用函数来处理数据 但是函数的可移植性不强 如果决定使用函数应该保证做好代码注释 以便以后能确切地知道所编写SQL代码的含义 大多SQL实现支持以下类型的函数 用于处理文
  • com.aspose.words 类LoadOptions

    com aspose words 类LoadOptions java lang Object com aspose words LoadOptions 直接已知子类 HtmlLoadOptions PdfLoadOptions RtfLoa
  • react native 上拖拽元素

    1 给一张效果图 2 具体代码如下 使用的就是react native里面的PanResponder 具体使用看 官网 这里主要两个知识点Animated 和 panResponder 我在componentDidMount初始 panRe
  • 企微外部群Api

    个人微信开发API 文档地址 wkteam gitbook io 所有个人号模块分析 登录模块 登录微控平台 member login 获取微信二维码 user login 执行微信登录 getIPadLoginInfo 获取联系人列表 群
  • Xpath和CSS选择器的使用详解

    Xpath与CSS选择器在爬虫中非常常见 下列我将描述一下它们的使用详情 安装Xpath和CSS选择器 Windows平台 pip install lxml Ubuntu平台 sudo apt get install python3 lxm
  • js的作用域和vue的作用域

    js有两种作用域 全局作用域和局部作用域 1 全局作用域 如果一个变量在所有函数外声明 那么就定义了一个全局作用域 2 局部作用域 有两种 函数作用域和块级作用域 函数作用域顾名思义就是在函数内定义的变量 而块级作用域则是 内let声明的变
  • 【Linux】几种典型的IO模型

    几种典型的IO模型 常见IO场景 输入和输出 读写文件 read write fread fwrite 网络接收与发送 send recv sendto recvfrom 上述两种场景都有一个共同点 就是最终都会和操作系统打交道 IO过程
  • python高级特性总结之切片 迭代 生成器 迭代器

    切片 gt gt gt L list range 100 gt gt gt L 0 1 2 3 99 gt gt gt L 10 0 1 2 3 4 5 6 7 8 9 gt gt gt L 10 90 91 92 93 94 95 96
  • PlantCV 农业自动化中的机器视觉库

    PlantCV 农业自动化中的机器视觉库 2020年下半年 各大互联网巨头纷纷进军社区买菜市场 我身边的朋友同事很多都开始通过新的电商生鲜渠道购买蔬菜 当时我就觉得 大资本即将涌入我们的第一产业 农业 果不其然 2020年12月31号 正值
  • Dell PowerEdge R740xd解析:服务器只看参数那就错了

    昨天写了 Dell PowerEdge R940解析 四路顶配服务器维护平民化 今天继续 对于R7x0这样的2U主力服务器机型 说实话我觉得不是特别好写 一方面不如四路有特点 另外又是互联网等行业消耗最多的 可以说乃服务器厂商必争之地 正如
  • Ubuntu下安装Chrome浏览器

    一 下载包 通过直接下载安装Google Chrome浏览器deb包 打开Ubuntu终端 以下为32位版本 使用下面的命令 wget https dl google com linux direct google chrome stabl
  • 模拟相机视频输入方案-----模拟转MIPI /DVP方案

    技术交流 请加微信video D 概述 由于模拟相机在监控领域的优势 以及模拟相机成本优势 目前模拟相机方案需求还是很多的 具体模拟解码芯片介绍 目前接触的有以下几种 1 Nextchip系列 韩国NEXTCHIP系列 主攻ISP AHD
  • 开发微信公众号支付代码

    一 url传入当前页面url地址或者微信公众平台配置的域名根目录 使用window location href方法获取 二 下面代码请结合微信公众号开发文档 微信公众号开发文档 function test url uni request u
  • 如何在Linux下安装vim编辑器

    目前的Ubuntu版本都安装了vi编辑器 vim编辑器可以看做vi编辑器的升级版 可以识别特殊字符 显示不同颜色 目录 第一步 第二步 第三步 第四步 第一步 在terminal里面输入vi命令后按下tab键可以看到当前vi可以执行的命令
  • 算法的时间及空间复杂度

    简介 java系列技术分享 持续更新中 初衷 一起学习 一起进步 坚持不懈 如果文章内容有误与您的想法不一致 欢迎大家在评论区指正 希望这篇文章对你有所帮助 欢迎点赞 收藏 留言 更多文章请点击 文章目录 一 什么是算法 二 算法初体验 案
  • C++ String替换&分割指定字符串

    C String替换 分割指定字符串 1 C String替换指定字符串 C 的string对象提供了replace方法来实现字符串的替换 本文实现对于将字符串中某个字符串全部替换的功能 string replace all string
  • MOOC清华《程序设计基础》第5章:求n的阶乘(用递推法做)

    使用递推思想 求解正整数的阶乘 本算法的数学模型为 n n 1 n include
  • CCF CSP 202206-3角色授权【70分】

    include
  • ts文件服务器端加密,加密ts文件解密

    EXTM3U EXT X VERSION 3 EXT X MEDIA SEQUENCE 0 EXT X ALLOW CACHE YES EXT X TARGETDURATION 13 EXT X KEY METHOD AES 128 URI
  • Linux动态库(.so)搜索路径

    Linux动态库 so 搜索路径 众所周知 Linux动态库的默认搜索路径是 lib和 usr lib 动态库被创建后 一般都复制到这两个目录中 当程序执行时需要某动态库 并且该 动 态库还未加载到内存中 则系统会自动到这两个默认搜索路径中