Linux系统lib文件

  1. 库的定义和种类
    所谓编程库就是指始终可以被多个Linux软件项目重复使用的代码集。库是Linux软件开发所追求的目标 ,C语言就是一个例子,它包含了几百个可以重复使用的例程和调试程序的工具代码,其中包括函数。如果每次编写新程序都要重新写这些函数会感到非常麻烦。使用编程库有两个主要优点,一是可以简化编程,实现代码重复使用;二是可以直接使用许多经过调试的测试和调试工具。
    Linux下的库文件分为共享库和静态库两大类,它们两者的差别仅在程序执行时所需的代码是在运行时动态加载的,还是在编译时静态加载的。
    Linux的库一般在/lib 或/usr/lib 目 录下。lib是库(Library)的英文缩写,它主要存放系统的链接库文件,没有该目录则系统就无法正常运行。/lib目录中存储着程序运行时使用的共 享库。通过共享库,许多程序可以重复使用相同的代码,并且这些库可以存储在一个公共的位置上,因此能减小运行程序的大小。这个目录包含程序在链接时使用的 各种库。

    1. 动态库
      动态库(也叫共用库)是编译好的代码片段,在程序执行时由运行时连接文件(runtime linker)/lib/ld.so加载。这有点类似于windows下的dll文件。在提高效率方面,这样做可以节省系统在以下方面的开销:
      硬件设备:不同的程序可以共享相同的代码。
      内存:内核可以将库文件的拷贝存放在内存里以便进程之间共享。
      时间:只要你不再重新编译库文件,重新生成可执行文件只需处理更少的代码。
      习惯上,动态库以字符串so命名,后面加上版本号。例如:
      libc.so.6 C语言的库文件.千万别给删掉了:)
      libcrypt.so.1 影子口令系统的编码库.
      libncurses.so.4.2 The new curses library routines.
    2. 静态库
      静态库在编译的时候被固定在了可执行文件中,而不是放在系统的某个地方由ld.so加载。这种做法好的一面是可执行文件自己包含了所需的所有库文件,并不 依赖于系统中的其他代码,也不会出现库文件缺失的情况。你可以把这些代码复制给任何人,而它们保证可以工作。不好的一面就是可执行文件不必要的增大了,而 且不同的程序之间不能共享代码。
      习惯上,我们以后缀.a来标记静态库文件。例如:
      libgtk.a GIMP和其他X应用的图形库.
      libcrypt.a 影子口令系统的编码库.
      libvga.a. [S]VGA图形库.
    3. 静态库与动态库的对比
      使用静态库的程序要比使用动态库的程序稍微快一些。我曾见过有人说两者之间启动时间的相差5%的数量级。但是,别忘了,动态库的好处之一是建立在一种假定 条件下,即这些可执行代码已经被加载到了内存中.事实上,对于像libc这样的库文件,确实是一直保存在内存中的。如果你要运行一个使用静态库编译的 netscape,必然要多等上一点时间。因此,对于“哪种库文件更快”这个问题的答案应该是“看情况而定”。但是一般来说,用动态库编译的的程序要更快 一些,因为大部分情况下你所需要的库都已经加载到内存中了。
  2. 重要的文件/可执行文件
    这个程序/lib/ls.so负责为可执行文件连接动态库。它在下面的文件夹里搜索库文件:
    环境变量LD_LIBRARY_PATH中列出的目录,除非该程序设定了sid或者uid,以跳过环境变量。
    文件/etc/ld.so.cache中列出的目录。
    In /usr/lib
    In /lib
    至于为什么ld.so不去搜索/usr/local/lib,自有它的理由,我可以告诉你,但那会折磨死你。有些东西根本就不是要凡人知道的...
    在/etc/ld.so.cache这个文件中包含了一个需要搜索的目录的汇总列表和一个备用库文件的列表。这个文件(/etc/ld.so.cache)是由/sbin/ldconfig创建的。
    /sbin/ldconfig在系统启动时自动运行,也可在编译完成库文件后手动运行(每次安装软件之后都手动运行该文件是个不错的习惯)。 ldconfig生成/etc/ld.so.cache文件,它搜索/lib、/usr/lib以及其他在/etc/ld.so.conf中列出的需要搜 索的目录。
    在配置文件/etc/ld.so.conf中列出了所有ldconfig需要搜索以生成ld.so.cache文件的目录。如果你把库文件放在了不是默认 的文件夹里(比如/home/lib),你应该把这个目录手工添加到ld.so.conf里,然后重新运行ldconfig。
  3. 非常有用的工具
    许多程序都要求你的系统中存在某些动态库以便运行时调用,你如何才能找出哪些动态库是某个程序所需要的呢?这理有两种方法。
    你可以使用strace,例如,先在终端下面用locate命令找出你系统里的xmms,xcalc或者xpaint所在的位置,然后运行以下命令:
    strace -o LOG /usr/X11R6/bin/xcalc
    关闭程序之后你会发现一个叫LOG的文件留了下来。用文本编辑器打开LOG,查找字符串so。你能看到哪些库文件被xcalc调用,还有上面提到的几个文 件比如ld.so.cache或者libc.so。你或许还能看到一些有趣的东西,比如当在一个目录中没有找到某一个库,返回“file not found”,程序会到另一个目录继续搜索该库。就像下面这样:
    open("/usr/local/rvplayer5.0/libXext.so.6", O_RDONLY) = -1 ENOENT (No such
    file or directory)
    open("/usr/X11R6/lib/libXext.so.6", O_RDONLY) = 4
    很明显,libXext.so.6不在/usr/local/rvplayer5.0中,但是随后ld.so在/usr/X11R6/lib中找到了它。幸运的是,还有一种获取这些信息的更方便的方法:
    ldd /usr/X11R6/bin/xcalc (必须使用完整的路径)
    ldd将会返回如下信息:
    libXaw.so.6 => /usr/X11R6/lib/Xaw3d/libXaw.so.6 (0x40020000)
    libXmu.so.6 => /usr/X11R6/lib/libXmu.so.6 (0x40077000)
    libXt.so.6 => /usr/X11R6/lib/libXt.so.6 (0x40089000)
    libSM.so.6 => /usr/X11R6/lib/libSM.so.6 (0x400d3000)
    libICE.so.6 => /usr/X11R6/lib/libICE.so.6 (0x400dd000)
    libXext.so.6 => /usr/X11R6/lib/libXext.so.6 (0x400f3000)
    libX11.so.6 => /usr/X11R6/lib/libX11.so.6 (0x400ff000)
    libm.so.6 => /lib/libm.so.6 (0x401a5000)
    libc.so.6 => /usr/lib/libc.so.6 (0x401c2000)
    /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)呵呵,它甚至把库文件所在的位置都给你找了出来!用着很舒服吧?
  4. 演示
    当你准备写一个“helloworld”那样的小程序然后用gcc编译时,用的是动态库还是静态库呢?除非你给连接器-static选项,gcc使用的是动态库。例如,这是我的演示程序:
    % cat try.c#include<stdio.h>
    int main(void) {
    printf("Hello, world!\n");
    return 0; }

    用gcc编译:
    % gcc try.c

    下面就是ldd大显身手了:
    % ldd a.out

    libc.so.6 => /usr/lib/libc.so.6 (0x40020000)
    /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

    现在我们使用静态库编译:
    % gcc -static try.c

    再用ldd分析这个新的可执行文件:
    % ldd a.out
    not a dynamic executable

    看到了吗?这就是理论的实际运用!

  5. 库的命名和编号
    在Linux下开发应用程序时,绝大多数情况使用的都是C语言,目前Linux下最常用的C语言编译器是GCC,它的全称是GNU Compiler Collection,下文中的库介绍都以它为例。GCC是直接建立在内核基础上的,是Linux操作系统外层的图形界面开发工具(Qt、GTK+)和网络应用开发工具(PHP、Prel、Python)的基础和过渡。掌握了底层开发工具,可以加快和优化外层应用开发,从而达到开发速度和开发质量的和谐统一。

    Glibc 2.3.2 是最新版的GNU C库。它目前不需要修改就可以在GNU Hurd、Linux i386、m68k,以及Alpha系统上执行,并且从2.1版开始加入了对Linux PowerPC、MIPS、Sparc、Sparc 64等系统的支持。

    如果想查看自己Linux计算机的Glibc版本可以使用下面命令:

    rpm -qa|grep glibc
    glibc-common-2.3.2-11.9
    glibc-2.3.2-11.9
    glibc-devel-2.3.2-11.9

    由上可见,Red Hat Linux 9.0使用的Glibc版本是2.3.2。

    1. 库的命名
      库的命名比较简单,第一个特点是所有的库以lib开头,GCC命令在在-l 选项所指定的文件名前会自动加入lib。第二个特点文件名以.a结尾的库是静态库 。第三个特点文件名是.so的库为共享库(共享库是在运行的时候动态加载的 ) 。默认情况下,GCC在链接时优先使用共享库,只有当共享库不存在时才考虑使用静态库。
    2. 库的编号
      库的编号格式如下:
      library_name .major.num .minor_.min .pathch_num
      例如,笔者Red Hat Linux 9.0的GUN数据库是libgdbm.so.0.0.2,详细表述如下:
      library_name是libc.so(标准C库);
      major_num是2(主版本号);
      minor_.min是0(次版本号);
      pathch_num是0(补丁级别号又称发行号)。
      libgdbm.so.0.0.2所在目录是/usr/lib,其大小是24576字节,这是一个ELF (Executable and Linking Format)格式的二进制格式文件,运行时由系统将其装入内存开始执行。ELF有三种主要类型:
      ◆适于连接的可重定位文件(Relocatable File),可与其它目标文件一起创建可执行文件和共享目标文件。
      ◆适于执行的可执行文件(Executable File),用于提供程序的进程映像,加载的内存执行。
      ◆共享目标文件(Shared Object File),连接器可将它与其它可重定位文件和共享目标文件连接成其它的目标文件;动态连接器又可将它与可执行文件和其它共享目标文件结合起来创建一个进程映像。
  6.  库操作命令
    Linux库操作可以使用命令完成,目前常用的命令是ldd和ldconfig。

    1. ldd
      ldd是Library Dependency Display缩写,它的作用是显示一个可执行程序必须使用的共享库 。

      1. 命令格式
        ldd [选项] 文件名
      2.  

        主要参数
        -d 执行重定位并报告丢失的函数。
        -r 执行对函数和数据对象的重定位,并报告丢失的函数和数据对象。

      3.  

        应用实例

        Perl语言是开发者喜欢使用的一种“胶水语言”(能够将许多元素连接在一起,因此它具有极强的适应性),如果需要查询有哪些共享库,则可以首先使用find命令查询这个程序的绝对路径,然后使用ldd命令:

        ldd /usr/bin/perl

        箭头左边的一列显示的是Prel语言所需的.so文件名, 箭头右边的一列显示是库的真实库名称。应用程序链接到库的so名字是到实际库的符号链接。最后的0x40014000是库 libperl.so的加载地址。

    2. ldconfig
      ldconfig 命令的作用是决定位于目录/usr/lib和/lib下的共享库所需的运行链接。这些链接保存在的Libs保存在/et/ld.so.conf文件中。搜 索出可共享的动态链接库(格式如前介绍,lib*.so*),进而创建出动态装入程序(ld.so)所需的链接和缓存文件。缓存文件默认为/etc /ld.so.cache,此文件保存已排好序的动态链接库名字列表。

      1. 命令格式
        ldconfig [选项] [libs]
      2.  

        主要选项
        -v或--verbose ldconfig将显示正在扫描的目录、搜索到的动态链接库,以及它所创建的连接的名字。
        -f CONF 指定动态链接库的配置文件为CONF,系统默认为/etc/ld.so.conf。
        -C CACHE 指定生成的缓存文件为CACHE,系统默认的是/etc/ld.so.cache,文件存放已排好序的可共享的动态链接库的列表。
        -p或--print-cache 让ldconfig打印出当前缓存文件所保存的所有共享库的名字。
        -r ROOT 改变应用程序的根目录为ROOT。
        -n ldconfig仅扫描命令行指定的目录,不扫描默认目录(/lib、/usr/lib),也不扫描配置文件/etc/ld.so.conf所列的目录。

        运行没有选项的ldconfig命令时,用于更新高速缓冲文件。这个命令主要用于高速缓冲DNS服务器(Caching DNS Server)。高速缓冲DNS服务器的原理是提供查询的历史记录,并且利用这些记录来提高查询的效率。当某个查询是第一次被发送到高速缓冲DNS服务器时,高速缓冲DNS服务器就将此查询的整个过程记录下来,在一定的时期内用它来回答所有相同的查询,从而减少整个DNS系统的负担并且提高查询速度。

      3.  

        应用实例
        如果用户想知道系统中有哪些动态链接库,或者想知道系统中有没有某个动态链接库时,可用-p选项让ldconfig输出缓存文件中的动态链接库列表,从而查询得到。

        ldconfig -p
        998 libs found in cache `/etc/ld.so.cache'
        libzvt.so.2 (libc6) => /usr/lib/libzvt.so.2
        libzvt.so (libc6) => /usr/lib/libzvt.so
        ……

        ldconfig命令输出结果表明,在缓存文件/etc/ld.so.cache中找到998个共享库,下一行开始便是一系列共享库的名字及其全名(绝对路径)。因为实际输出结果很多,为节省篇幅以“……”表示省略的部分。

 

发表评论

电子邮件地址不会被公开。

ERROR: si-captcha.php plugin: GD image support not detected in PHP!

Contact your web host and ask them to enable GD image support for PHP.

ERROR: si-captcha.php plugin: imagepng function not detected in PHP!

Contact your web host and ask them to enable imagepng for PHP.