#导入Word文档图片# Linux下动态库与静态库的运用

GCC编译器的常用选项

1.1 gcc基本用法

使用GCC编译器的时候,我们必须给出一系列必要的调用参数和文件名称。GCC编译器的调用参数大约有100多个,这里只介绍其中最基本、最常用的参数。

GCC最基本的用法∶

gcc [参数] [文件名称]

1.2 常用的参数

-c 只编译:不链接成为可执行文件,编译器只是由输入的.c等源代码文件生成.o为后缀的目标文件,通常用于编译不包含主程序的子程序文件。

-o output_filename:确定输出文件的名称为output_filename,同时这个名称不能和源文件同名。如果不给出这个选项,gcc就给出预设的可执行文件a.out。

-g:产生符号调试工具(GNU的gdb)所必要的符号信息,要想对源代码进行调试,我们就必须加入这个选项。

-O:对程序进行优化编译、链接,采用这个选项,整个源代码会在编译、链接过程中进行优化处理,这样产生的可执行文件的执行效率可以提高,但是,编译、链接的速度就相应地要慢一些。

-O2:比-O更好的优化编译、链接,当然整个编译、链接过程会更慢。

-E:仅执行编译预处理;

-S:将C代码转换为汇编代码;

示例:

# gcc test.c -o app

1.3 编译时指定库与头文件路径

-L:指定动态库路径。

示例:gcc test.c -o app -L/usr/lib

-I:指定头文件存放的路径。

示例:gcc test.c -o app -I/usr/include

-l: 指定库名称。

示例:gcc test.c -o app -lpthread

二、动态库与静态库的介绍

我们通常把一些公用函数制作成函数库,供其它程序使用。函数库分为静态库和动态库两种。

通常情况下,对函数库的链接是放在编译时期(compile time)完成的。所有相关的对象文件(object file)与牵涉到的函数库(library)被链接合成一个可执行文件(executable file)。程序在运行时,与函数库再无瓜葛,因为所有需要的函数已拷贝到相应目录下下。所以这些函数库被成为静态库(static libaray),通常文件名为“libxxx.a”的形式。

两句话介绍解释:

静态库:在编译的时候加载生成目标文件,在运行时不用加载库,在运行时对库没有依赖性。

动态库:在目标文件运行时加载,对库有依赖性。

三、动态库的创建与调用

3.1 生成和使用动态库的步骤

linux下动态库文件的文件名形如 libxxx.so,其中so是 Shared Object 的缩写,即可以共享的目标文件。

在链接动态库生成可执行文件时,并不会把动态库的代码复制到执行文件中,而是在执行文件中记录对动态库的引用。

程序执行时,再去加载动态库文件。如果动态库已经加载,则不必重复加载,从而能节省内存空间。

Linux下生成和使用动态库的步骤如下:

1. 编写源文件。

2. 将一个或几个源文件编译链接,生成共享库。

3. 通过 -L<path> -lxxx 的gcc选项链接生成的libxxx.so。

4. 把libxxx.so放入链接库的标准路径,或指定 LD_LIBRARY_PATH,才能运行链接了libxxx.so的程序。

3.2 编译生成共享库的命令格式

gcc -fPIC -shared -o <库文件名称>.so 源文件名称.c

示例:

gcc -fPIC -shared -o libabc.so abc.c

执行上面代码之后我们会得到libabc.so。

生成共享库之后可以通过file命令查看共享库的信息。

[wbyq@wbyq linux-share-dir]$ file sum/libsum.so

sum/libsum.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, not stripped

实际上上述过程分为编译和链接两步, -fPIC是编译选项,PIC表示要生成位置无关的代码,这是动态库需要的特性; -shared是链接选项,告诉gcc生成动态库而不是可执行文件。

上述的一行命令等同于:

gcc -c -fPIC abc.c

gcc -shared -o libabc.so abc.o

3.3 调用动态库的例子

gcc test.c -L ./ -labc 生成a.out,其中-labc表示要链接libabc.so。

-L ./表示指定搜索要链接的库文件时包含的路径。

注意,如果同一目录下同时存在同名的动态库和静态库,比如 libmax.so 和 libmax.a 都在当前路径下,则gcc会优先链接动态库。

执行程序:

运行 ./a.out 会得到以下的错误提示。

./a.out: error while loading shared libraries: libabc.so: cannot open shared object file: No such file or directory

找不到libabc.so,Linux是通过 /etc/ld.so.cache 文件搜寻要链接的动态库的。

而 /etc/ld.so.cache 是 ldconfig 程序读取 /etc/ld.so.conf 文件生成的。

(注意, /etc/ld.so.conf 中并不必包含 /lib 和 /usr/lib,ldconfig程序会自动搜索这两个目录)

如果我们把 libabc.so 所在的路径添加到 /etc/ld.so.conf 中,再以root权限运行 ldconfig 程序,更新 /etc/ld.so.cache ,a.out运行时,就可以找到 libabc.so。

但作为一个简单的测试例子,让我们改动系统的东西,似乎不太合适。

还有另一种简单的方法,就是为a.out指定 LD_LIBRARY_PATH。

LD_LIBRARY_PATH=. ./a.out

程序就能正常运行了。LD_LIBRARY_PATH=. 是告诉 a.out,先在当前路径寻找链接的动态库。

或者直接将xx.so拷贝到/lib下也可以。

3.4 查看系统环境变量

设置系统环境变量: export <环境变名称>=环境变量的值

查看本地所有的环境变量: env

查看shell所有的环境变量: set

查看本地所有环境变量: export

四、静态库的创建与调用

4.1 静态库介绍

Linux上的静态库,其实是目标文件的归档文件。

在Linux上创建静态库的步骤如下:

  1. 写源文件,通过 gcc -c xxx.c 生成目标文件。
  2. 用 ar 归档目标文件,生成静态库。
  3. 配合静态库,写一个使用静态库中函数的头文件。
  4. 使用静态库时,在源码中包含对应的头文件,链接时记得链接自己的库。

4.2 创建静态库

我们使用 ar 将目标文件归档:

ar crv libmylib.a my_print.o my_math.o

我们就得到了libmylib.a,这就是我们需要的静态库。

上述命令中 crv 是 ar的命令选项:

c 如果需要生成新的库文件,不要警告

r 代替库中现有的文件或者插入新的文件

v 输出详细信息

通过 ar t libmylib.a 可以查看 libmylib.a 中包含的目标文件。

注意:我们要生成的库的文件名必须形如 libxxx.a ,这样我们在链接这个库时,就可以用 -lxxx。

反过来讲,当我们告诉编译器 -lxxx时,编译器就会在指定的目录中搜索 libxxx.a 或是 libxxx.so。

4.3 调用静态库

执行程序:

执行: gcc test.c -L. -lmylib

将会生成a.out,通过 ./a.out 可以运行该程序。说明我们的静态库能正常工作。

上面的命令中 -L. 告诉 gcc 搜索链接库时包含当前路径, -lmylib 告诉 gcc 生成可执行程序时要链接 libmylib.a。

注意: 当同一个目录下,静态库与动态库重名时,优先使用动态库。

例如: libsum.a libsum.so 优先使用libsum.so

发表评论

相关文章