日期:2014-05-16  浏览次数:20725 次

Linux函数库的制作与调用

[注:本文中的操作在ubuntu-10.04.4上进行。]

静态库与动态库

从本质上来说,库是一种可执行代码的二进制形式,可以被操作系统载入内存执行,无论静态库还是动态库,都是由.o文件(目标文件)创建的。

  • 静态库:静态库的代码在编译过程中已经被载入可执行程序,因此程序体积较大。
  • 动态库:不同的应用程序如果调用相同的库,那么在内存里只需要一份该动态库。单独的动态库升级更换不影响其他动态库的正常加载使用,便于升级。

编译多个源文件

1. 新建hello.c:

#include<stdio.h>

void hello()
{
    printf(“Hello world!\n”);
}

执行命令gcc –c hello.c,生成目标文件hello.o。

2. 新建hello.h:

#ifndef _HELLO_
#define _HELLO_
extern voidhello();
#endif //_HELLO_

3. 新建main.c:

#include “hello.h”

int main(intargc, char **argv)
{
    hello();
    return 0;
}
4. 执行命令gcc –c main生成目标文件main.o

5. 将hello.o和main.o联合编译生成可执行文件hello:gcc –o hello hello.o main.o

注:多文件编译生成可执行文件hello的大小为7184B

静态库的生成与引用

1. 执行命令gcc –c hello.c,生成目标文件hello.o;

2. 执行命令ar rcs libhello.a hello.o,生成静态库文件libhello.a;

3. 编译时加载静态文件gcc –o hello main.c –static –L. –lhello,生成可执行文件hello。

注:静态库生成的可执行文件hello的大小为594740B,静态库libhello.a的大小为982B,删除静态库后,hello依然可以执行。可以看出加载静态库的可执行文件比较大。

动态库的生成与引用

1. 执行命令gcc –c hello.c,生成目标文件hello.o;

2. 执行命令gcc –shared –fPIC –o libhello.so hello.o,生成动态库libhello.so;

3. 执行命令gcc –o hello main.c –L. –lhello,生成可执行文件hello。

    此时运行hello:$./hello将报错:

    ./hello: errorwhile loading shared libraries: libhello.so: cannot open shared object file: Nosuch file or director

4. 想要执行hello,需要链接到动态库,方法如下:

    a) 将libhello.so拷贝到目录/usr/lib中;

    b) export LD_LIBRARY_PATH=$(pwd),将libhello.so所在目录(当前目录)加入到LD_LIBRARY_PATH;

    c) chcon –t texrel_shlib_t/usr/lib/libhello.so,分享库的绝对路径;[?此命令作用未明]

注:引用动态库的可执行文件hello大小为7128B,动态库libhello.so的大小为6734B,相比编译多个源文件生成hello大小7184B,可以看出加载动态库不会导致可执行文件变大。为确保hello可以成功执行,必须保证应用程序能够链接到动态库,经验证:只要4.a)或者4.b)有一项完成就行。

链接器如何加载动态库

链接器搜索动态库的顺序:

1. elf文件的DT_RPATH段;

2. 环境变量LD_LIBRARY_PATH;

3. /etc/ld.so.cache文件列表;

4. /lib, /usr/lib目录;

只要找到动态库,就将其载入内存。