LD_LIBRARY_PATH和LIBRARY_PATH的区别

先来看看程序编译和链接的过程:

编译过程又可以分成两个阶段:编译和汇编。

编译

编译是指编译器读取源程序(字符流),对之进行词法和语法的分析,将高级语言指令转换为功能等效的汇编代码。

源文件的编译过程包含两个主要阶段:

第一个阶段是预处理阶段,在正式的编译阶段之前进行。预处理阶段将根据已放置在文件中的预处理指令来修改源文件的内容。

主要是以下几方面的处理:

  1. 宏定义指令,如 #define a b 对于这种伪指令,预编译所要做的是将程序中的所有a用b替换,但作为字符串常量的 a则不被替换。还有 #undef,则将取消对某个宏的定义,使以后该串的出现不再被替换。
  2. 条件编译指令,如#ifdef,#ifndef,#else,#elif,#endif等。 这些伪指令的引入使得程序员可以通过定义不同的宏来决定编译程序对哪些代码进行处理。预编译程序将根据有关的文件,将那些不必要的代码过滤掉
  3. 头文件包含指令,如#include "FileName"或者#include 等。 该指令将头文件中的定义统统都加入到它所产生的输出文件中,以供编译程序对之进行处理。
  4. 特殊符号,预编译程序可以识别一些特殊的符号。 例如在源程序中出现的LINE标识将被解释为当前行号(十进制数),FILE则被解释为当前被编译的C源程序的名称。预编译程序对于在源程序中出现的这些串将用合适的值进行替换。

头文件的目的主要是为了使某些定义可以供多个不同的C源程序使用,这涉及到头文件的定位即搜索路径问题。头文件搜索规则如下:

  1. 所有header file的搜寻会从-I开始
  2. 然后找环境变量 C_INCLUDE_PATH,CPLUS_INCLUDE_PATH,OBJC_INCLUDE_PATH指定的路径
  3. 再找默认目录(/usr/include、/usr/local/include、/usr/lib/gcc-lib/i386-linux/2.95.2/include......)

第二个阶段编译、优化阶段,编译程序所要作得工作就是通过词法分析和语法分析,在确认所有的指令都符合语法规则之后,将其翻译成等价的中间代码表示或汇编代码。

汇编

汇编实际上指汇编器(as)把汇编语言代码翻译成目标机器指令的过程。目标文件中所存放的也就是与源程序等效的目标的机器语言代码。目标文件由段组成。通常一个目标文件中至少有两个段:

  • 代码段:该段中所包含的主要是程序的指令。该段一般是可读和可执行的,但一般却不可写。
  • 数据段:主要存放程序中要用到的各种全局变量或静态的数据。一般数据段都是可读,可写,可执行的。

目标文件(Executable and Linkable Format)

  1. 可重定位(Relocatable)文件:由编译器和汇编器生成,可以与其他可重定位目标文件合并创建一个可执行或共享的目标文件;
  2. 共享(Shared)目标文件:一类特殊的可重定位目标文件,可以在链接(静态共享库)时加入目标文件或加载时或运行时(动态共享库)被动态的加载到内存并执行;
  3. 可执行(Executable)文件:由链接器生成,可以直接通过加载器加载到内存中充当进程执行的文件。

静态库与动态库

静态库(static library)就是将相关的目标模块打包形成的单独的文件。使用ar命令。

静态库的优点在于:

  • 程序员不需要显式的指定所有需要链接的目标模块,因为指定是一个耗时且容易出错的过程;
  • 链接时,连接程序只从静态库中拷贝被程序引用的目标模块,这样就减小了可执行文件在磁盘和内存中的大小。

动态库(dynamic library)是一种特殊的目标模块,它可以在运行时被加载到任意的内存地址,或者是与任意的程序进行链接。

动态库的优点在于:

  • 更新动态库,无需重新链接;对于大系统,重新链接是一个非常耗时的过程;
  • 运行中可供多个程序使用,内存中只需要有一份,节省内存。

链接过程

链接器主要是将有关的目标文件彼此相连接生成可加载、可执行的目标文件。链接器的核心工作就是符号表解析和重定位。

链接的时机:

  1. 编译时,就是源代码被编译成机器代码时(静态链接器负责);
  2. 加载时,也就是程序被加载到内存时(加载器负责);
  3. 运行时,由应用程序来实施(动态链接器负责)。

链接的作用(软件复用):

  1. 使得分离编译成为可能;
  2. 动态绑定(binding):使定义、实现、使用分离

 静态库搜索路径(由静态链接器负责)

  1. gcc先从-L寻找;
  2. 再找环境变量LIBRARY_PATH指定的搜索路径;
  3. 再找内定目录 /lib /usr/lib /usr/local/lib 这是当初compile gcc时写在程序内的。

动态库搜索路径(由动态链接器负责)

  1. 编译目标代码时指定的动态库搜索路径-L;
  2. 环境变量LD_LIBRARY_PATH指定的动态库搜索路径;
  3. 配置文件/etc/ld.so.conf中指定的动态库搜索路径;
  4. 默认的动态库搜索路径/lib /usr/lib/ /usr/local/lib

静态链接(编译时)

链接器将函数的代码从其所在地(目标文件或静态链接库中)拷贝到最终的可执行程序中。这样该程序在被执行时这些代码将被装入到该进程的虚拟地址空间中。静态链接库实际上是一个目标文件的集合,其中的每个文件含有库中的一个或者一组相关函数的代码。

为创建可执行文件,链接器必须要完成的主要任务:

  1. 符号解析:把目标文件中符号的定义和引用联系起来;
  2. 重定位:把符号定义和内存地址对应起来,然后修改所有对符号的引用。

动态链接(加载、运行时)

在此种方式下,函数的定义在动态链接库或共享对象的目标文件中。在编译的链接阶段,动态链接库只提供符号表和其他少量信息用于保证所有符号引用都有定义,保证编译顺利通过。动态链接器(ld-linux.so)链接程序在运行过程中根据记录的共享对象的符号定义来动态加载共享库,然后完成重定位。在此可执行文件被执行时,动态链接库的全部内容将被映射到运行时相应进程的虚地址空间。动态链接程序将根据可执行程序中记录的信息找到相应的函数代码。  

根据链接的时机可知

LIBRARY_PATH环境变量用于在程序编译期间查找动态链接库时指定查找共享库的路径,例如,指定gcc编译需要用到的动态链接库的目录。设置方法如下(其中,LIBDIR1和LIBDIR2为两个库目录):

export LIBRARY_PATH=LIBDIR1:LIBDIR2:$LIBRARY_PATH

LD_LIBRARY_PATH环境变量用于在程序加载运行期间查找动态链接库时指定除了系统默认路径之外的其他路径,注意,LD_LIBRARY_PATH中指定的路径会在系统默认路径之前进行查找。设置方法如下(其中,LIBDIR1和LIBDIR2为两个库目录):

export LD_LIBRARY_PATH=LIBDIR1:LIBDIR2:$LD_LIBRARY_PATH

举个例子,我们开发一个程序,经常会需要使用某个或某些动态链接库,为了保证程序的可移植性,可以先将这些编译好的动态链接库放在自己指定的目录下,然后按照上述方式将这些目录加入到LD_LIBRARY_PATH环境变量中,这样自己的程序就可以动态链接后加载库文件运行了。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小樱的经验随笔

【Python Learning第一篇】Linux命令学习及Vim命令的使用

学了两天,终于把基本命令学完了,掌握以后可以当半个程序员了♪(^∇^*) 此文是一篇备忘录或者查询笔记,如果哪位大佬看上了并且非常嫌弃的话,还请大佬不吝赐教,多...

37510
来自专栏北京马哥教育

25个shell脚本代码分享,日常工作够用了

引言 自己写了一下小的shell实例,虽然很小,但所有的大的程序都是由小的模块堆积起来的。 程序员一定要懂得一种脚本的书写,而我,只会在linux下工作,所以...

39911
来自专栏零基础使用Django2.0.1打造在线教育网站

利用Flask搭建微电影视频网站(五):访问控制器

努力与运动兼备~~~有任何问题可以加我好友或者关注微信公众号,欢迎交流,我们一起进步!

2412
来自专栏用户2442861的专栏

Ubuntu下如何解压缩zip,tar,tar.gz,tar.bz2文件

http://blog.csdn.net/zhongnanjun_3/article/details/6312678

5232
来自专栏JarvanMo的IT专栏

Node.js文件路径的坑

没错,我想读取system-config.json中的配置。刚开始,无论如何也读不到,连个错误信息也没有。调试了一番,终于出了一个错误信息: no such ...

1614
来自专栏hbbliyong

错误提示之(MVC3.0):HTTP 404。您正在查找的资源(或者它的一个依赖项)可能已被移除,或其名称已更改,或暂时不可用。请检查以下 URL 并确保其拼写正确 MVC误设起始页

MVC3.0框架开发项目: 有时在程序运行的时候会出现“HTTP 404。您正在查找的资源(或者它的一个依赖项)可能已被移除,或其名称已更改,或暂时不可用。请检...

3876
来自专栏mySoul

node web模块 (服务器端和客户端)

web服务器指网站服务器,指驻留在因特网上的某种程序,web浏览器的基本功能,提供信息浏览服务

1457
来自专栏linux系统运维

vim的介绍以及使用

1203
来自专栏大史住在大前端

express中间件系统的基本实现

一直觉得express的中间件系统这种流式处理非常形象,就好像加工流水线一样,每个环节都在针对同一个产品的不同部分完成自己的工作,最后得到一个成品。今天就来实现...

1575
来自专栏开发技术

详细的最新版fastdfs单机版搭建

  目前项目是tomcat单机部署的,图片、视频也是上传到tomcat目录下,关键是此项目的主要内容还就是针对图片、视频的,这让我非常担忧;文件服务器的应用是必...

5031

扫码关注云+社区