Chinaunix首页 | 论坛 | 博客
  • 博客访问: 46040
  • 博文数量: 10
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 115
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-31 21:36
文章分类
文章存档

2011年(1)

2008年(9)

我的朋友

分类: LINUX

2008-09-22 19:54:34

解读Linux编程库

随着性能的不断提升和逐渐普及,会有越来越多的人在Linux下从事的。这里笔者根据从事Linux应用程序开发的经验,介绍Linux编程库使用的一些基础知识。

库的定义和种类

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

图1

库的命名和编号

在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),连接器可将它与其它可重定位文件和共享目标文件连接成其它的目标文件;动态连接器又可将它与可执行文件和其它共享目标文件结合起来创建一个进程映像。
    
库操作命令

Linux库操作可以使用命令完成,目前常用的命令是ldd和ldconfig。
1.ldd
ldd是Library Dependency Display缩写,它的作用是显示一个可执行程序必须使用的共享库。
(1)命令格式
ldd [选项] 文件名

(2)主要参数
-d  执行重定位并报告丢失的函数。
-r  执行对函数和数据对象的重定位,并报告丢失的函数和数据对象。
(3)应用实例
Perl语言是开发者喜欢使用的一种“胶水语言”(能够将许多元素连接在一起,因此它具有极强的适应性),如果需要查询有哪些共享库,则可以首先使用find命令查询这个程序的绝对路径,然后使用ldd命令:
#find -name perl
ldd  /usr/bin/perl

其结果见图2所示。图2中,箭头左边的一列显示的是Prel语言所需的.so文件名, 箭头右边的一列显示是库的真实库名称。应用程序链接到库的so名字是到实际库的符号链接。以第二行为例,最后的0x40014000是库libperl.so的加载地址。由此可以看到,运行Perl语言需要9个共享库。

图2

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个共享库,下一行开始便是一系列共享库的名字及其全名(绝对路径)。因为实际输出结果很多,为节省篇幅以“……”表示省略的部分。


 
库的升级

Linux系统软件更新很快,新的核心几乎每几个星期就公布一次,其它软件的更新也是非常频繁。多数情况下,盲目跟随潮流的升级并不必要,如果确实需要新版本的特性时再升级。换句话说,不要为了升级而升级。Linux系统中多数软件都是用共享库来编译的,其中包含了在不同程序之间共享的公用子例程。
在运行某个程序时,如果看到如下信息:“Incompatible library version.”则表明需要将该库升级到程序所需要的版本。库是向下兼容的,也就是说,用老版本库编译的程序可以在新安装的版本库上运行,反之则不行。
Linux库函数的升级是一项重要的工作,往往与其它软件包的升级有一定关联作用,所以操作前一定要备份文件。下面看一下如何把Glibc 2.2.4.13升级至2.3.2版本,其过程如下:

1.下载.gz压缩文件并解压
在GUN C网站下载的四个.gz压缩文件,解压至一临时目录中:
cd /usr/caolinux
tar xzvf glibc-2.3.2.tar.gz
cd glibc-2.3.2
tar xzvf ../glibc-linuxthreads-2.3.2.tar.gz
tar xzvf ../glibc-crypt-2.3.2.tar.gz
tar xzvf ../glibc-localedata-2.3.2.tar.gz

2.建立库函数的安装目录
mkdir /usr/higlibc
cd /usr/higlibc 

3.建立编译目录
mkdir cao
cd cao
./configure --enable-add-ons=linuxthreads,crypt,localedata -prefix
=/usr/higlibc

4.编译与安装
make
make check
make install

编译与安装过程根据计算机硬件配置不同,从10分钟到几十分钟不等。

5.改变的链接
ln -s /usr/higlibc/lib/ld-linux.so.2 /lib/ld-linux.so.2

然后,修改/etc/ld.so.conf,加入一行/usr/higlibc/lib,执行下面代码:
ldconfig -v

更新/etc/ld.so.cache的内容,列出每个库的版本号,扫描目录和所要创建及更新的链接。

6.更改GCC设置
cd /usr/lib/gcc-lib
cp -r i386-redhat-linux higlibc

7.更新符号链接
cd /usr/higlibc/include
ln -s /usr/src/linux/include/linux
ln -s /usr/src/linux/include/asm
ln -s /usr/X11R6/include/X11

8.测试
编写一个简单的C程序测试一下,除了头文件只需一条printf语句即可:
#include
int main(void)
{ printf ("Hello , Linux !\n");
 return 0;}

然后用GCC编译一次,当程序出现如下运行结果,则说明已经正确地升级了。
“Hello, Linux !”

以上五部分分别介绍了Linux库的定义属性、“标准”库的命名和编号约定、经常使用的库、与库操作相关命令的作用,以及库升级的步骤,希望能对初学Linux的开发者有所帮助。

阅读(1511) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~