linux 静态库、共享库

一、什么是库

 

本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。由于windows和linux的本质不同,因此二者库的二进制是不兼容的。

 

Linux操作系统支持的函数库分为静态库和动态库,动态库又称共享库。Linux系统有几个重要的目录存放相应的函数库,如/lib    /usr/lib。

 

二、静态函数库、动态函数库

 

A.  这类库的名字一般是libxxx.a;利用静态函数库编译成的文件比较大,因为整个函数库的所有数据都被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进可执行文件了。当然这也会称为它的缺点,因为如果静态函数库改变了,那么你的程序必须重新编译,而且体积也较大。

 

B.这类库德名字一般是libxxx.so,动态库又称共享库;相对于静态函数库,动态函数库在编译的时候并没有被编译进目标代码中,你的程序执行到相关函数时才调用函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。而且如果多个应用程序都要使用同一函数库,动态库就非常适合,可以减少应用程序的体积。

 

注意:不管是静态函数库还是动态函数库,都是由*.o目标文件生成。

 

三、函数库的创建

 

A.静态函数库的创建

 

ar -cr  libname.a   test1.o  test2.o

 

ar:静态函数库创建的命令

-c :create的意思

-r :replace的意思,表示当前插入的模块名已经在库中存在,则替换同名的模块。如果若干模块中有一个模块在库中不存在,ar显示一个错误信息,并不替换其他同名的模块。默认的情况下,新的成员增加在库德结尾处。

 

B.动态函数库的创建

 

gcc -shared  -fpic  -o libname.so  test1.c test2.c

 

-fpic:产生代码位置无关代码

-shared :生成共享库

 

四、静态库和动态库的使用 

 

案例:

 

add.c

#include <stdio.h>

 

int add(int a,int b)

{

return a + b;

}

sub.c

#include <stdio.h>

 

int sub(int a,int b)

{

return a - b;

}

 

head.h

 

#ifndef _HEAD_H_

#define _HEAD_H_

extern int add(int a,int b);

extern int sub(int a,int b);

#endif

main.c

#include <stdio.h>

 

int main(int argc,char *argv[])

{

int a,b;

 

if(argc < 3)

{

fprintf(stderr,"Usage : %s argv[1] argv[2].\n",argv[0]);

return -1;

}

 

a = atoi(argv[1]);

b = atoi(argv[2]);

 

printf("a + b = %d\n",add(a,b));

printf("a - b = %d\n",sub(a,b));

 

return 0;

}

生成静态库

生成动态库:

使用生成的生成的库:

其中

-L 指定函数库查找的位置,注意L后面还有'.',表示在当前目录下查找

-l则指定函数库名,其中的lib和.a(.so)省略。

 

注意:-L是指定查找位置,-l指定需要操作的库名。

 

从上面的运行结果中,我们可以看到:

 

A.当动态库和静态库同时存在的时候,gcc默认使用的是动态库。如果强制使用静态库则需要加-static选项支持。

B.动态库生成的可执行文件,test1不能正常的运行。

C.链接静态库的可执行程序明显比链接动态库的可执行文件大。

 

五、让链接动态库的可执行程序正常运行。

 

当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路劲。此时就需要系统动态载入器(dynamic  linker/loader)。

 

对于elf格式的可执行程序,是由ld-linux.so*来完成的,它先后搜索elf文件的DT_RPATH段---环境变量LD_LIBRARY_PATH、/etc/ld.so.cache文件列表、/usr/lib、/lib目录找到库文件后将其载入内存。

 

A.一种最直接的方法,就是把生成的动态库拷贝到/usr/lib或/lib中去。

B.使用LD_LIBRARY_PATH环境变量,这个环境变量在ubuntu操作系统中默认没有,需要手动添加

C.动态在安装在其他目录下,如果想操作系统能找到它,可以通过一下步骤

 

<1>新建并编辑/etc/ld.so.conf.d/my.conf文件,加入库所在目录的路径

<2>执行ldconfig命令更新ld.so.cache文件

此时,在执行链接动态库的可执行文件则可以正常运行。

 

六、查看库中的符号

 

A.nm命令可以打印出库中涉及到的所有符号。库既可以是静态库也可以是动态的。

 

常见的三种符号:

<1>在库中被调用,但没有在库中定义(表明需要其他库支持),用U表示

<2>在库中定义的函数,用T表示

<3>“弱态”符号,他们虽然在库中被定义,但是可能被其他库中同名的符号覆盖,用W表示。

B.ldd命令可以查看一个可执行程序依赖的共享库

七、动态加载库

 

用gcc -shared生成的我们称为动态库(共享库),其中动态库在运行的过程中有两种方式

 

A.动态链接

 

这种方式下,可执行程序只是做一个动态的链接,当需要用到动态库中的函数时,有加载器隐士的加载。

 

B.动态加载

 

这种方式下,在可执行程序的内部,我们可以用dlopen()这样的函数,手动进行加载,dlsym()函数找到我们想要调用函数的入口地址,然后进行调用。这种方式,在写插件程序中得到广泛应用。

 

相关的API:

<1>dlopen()打开一个新的动态库,并把它装入内存。该函数主要用来记载库中的符号,这些符号在编译的时候是不知道的。

 

dlopen()函数需要两个参数:一个文件名和一个标志。

 

A.文件名是我们之前接触过的动态库的名字,如果它是一个绝对路径,如:/home/cyg/worddir/libname.so,此时dlopen直接到指定的路径下打开动态库。

如果没有指定路径,仅仅指定了一个动态库的名字,此时dlopen将它先后搜索elf文件的DT_RPATH段、环境变量LD_LIBRARY_PATH、/etc/ld.so.cache文件列表、/lib、/usr/lib目录找到库文件后将其载入内存。

 

B.标志指明是否立刻计算库的依赖性。

常常一个库中还依赖别的库,就是这个函数实现的时候,调用了别的库函数。不是在这个库中实现的函数我们称为位定义的符号。

 

如果将标志 设置为RTLD_NOW的话,则会在dlopen函数返回前,将这些未定义的符号解析出来。如果设置为RTLD_LAZY,则会在需要的时候才会去解析。

 

返回值:dlopen()函数会返回一个句柄作为dlsym()函数的第一个参数,以获得符号在库中的地址。使用这个地址,就可以获得库中特定函数的指针,并且调用装载库中的相应函数。

 

<2>dlerror()

 

当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。

 

<3>void *dlsym(void *handle,char *symbol);

 

dlsym根据动态链接库操作句柄(handle)与符号(symbol),返回符号对应的函数的执行代码地址。由此地址,可以带参数执行相应的函数。

 

如程序代码 :int (*add)(int x,int y);//函数指针

 

handle = dlopen("xxx.so",RTLD_LAZY);//打开共享库

add = dlsym(handle,"add");//获取add函数在共享库的地址

value = add(12,34);//调用add函数

 

<4>int dlclose(void *handle);

dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。

 

案例:

#include <stdio.h>

#include <string.h>

#include <errno.h>

#include <dlfcn.h>

 

int test_dl(char *pso,char *pfu)

{

void *handle;

int (*ptest)(int x,int y);

 

if((handle = dlopen(pso,RTLD_LAZY)) == NULL)

{

printf("%s.\n",dlerror());

return -1;

}

 

if((ptest = dlsym(handle,pfu)) == NULL)

{

printf("%s.\n",dlerror());

return -1;

}

 

printf("ptest complete : %d.\n",ptest(12,13));

 

dlclose(handle);

 

return 0;

}

 

int main(int argc,char *argv[])

{

char buf[100];

char *pso,*pfun;

 

printf("Input xxx.so:function_name.\n");

while(1)

{

printf(">");

fgets(buf,sizeof(buf),stdin);

buf[strlen(buf)-1] = 0;

 

pso = strdup(strtok(buf,":"));

pfun = strdup(strtok(NULL,":"));

 

test_dl(pso,pfun);

}

 

return 0;

}

 

运行结果:

 

时间: 2024-09-24 11:34:00

linux 静态库、共享库的相关文章

Linux下动态共享库 连接和加载路径

1. 连接时找不到某一个函数,出现" xxxxx undefined",应该就是连接时找不到相应的动态库,连接时动态库的路径如下: 1> 默认路径是:/lib, /usr/lib/, /usr/local/lib 2> -L: 指定连接时动态库的路径 3> LD_LIBRARY_PATH: 指定连接路径 2. 运行应用程序时出现"error<wbr>while loading shared libraries",则是加载时找不到相应的动

linux系统 动态共享库-动态共享库加载到内存中,怎样才能保证只有一份副本

问题描述 动态共享库加载到内存中,怎样才能保证只有一份副本 这几天一直在看关于动态共享库的知识,但看到一个地方,就不懂了,在网上搜索了一下!也没有找到答案!希望有哪位高手,帮小弟解答一下,小弟不胜感激! 问题:动态共享库,顾名思义,可以在多个进程间,进行共享!在系统中只保存一份副本,现在假设Process A已经将Lib A Load到物理内存,但当同样共享Lib A的Process B开始运行时,它是如何知道Lib A已经被加载到内存中,且如何找到这块物理内存?

Linux静态库和共享库【转】

转自:http://www.cnblogs.com/zlcxbb/p/6806269.html 1.什么是静态库 静态库类似windows中的静态lib 关于windows中的静态lib,可参考 Windows动态链接库DLL  特点:包含函数代码声明和实现,链接后所有代码都嵌入到宿主程序中. 只在编译时使用,执行时不再需要该静态库. 2.静态库编写示例如下:addvec.c void addvec(int* x, int* y, int*z, int n) { int i=0; for(; i

静态库和共享库制作

1静态库和共享库 *本节就如何创建和使用程序库进行论述.所谓"程序库",简单说,就是包含了数据 和执行码的文件.其不能单独执行,可以作为其它执行程序的一部分来完成某些功能.库的 存在,可以使得程序模块化,可以加快程序的再编译,可以实现代码重用,可以使得程序便 于升级.程序库可分静态库(static library)和共享库(shared object).   A:静态库 是在可执行程序运行前就已经加入到执行码中,成为执行程序的一部分:共享库,是在 执行程序启动时加载到执行程序中,可以被

Linux系统共享库编程

一.说明 类似Windows系统中的动态链接库,Linux中也有相应的共享库用以支持代码的复用.Windows中为*.dll,而Linux中为*.so.下面详细介绍如何创建.使用Linux的共享库. 二.创建共享库 在mytestso.c文件中,代码如下: #include <stdio.h> #include <stdlib.h> int GetMax(int a, int b) { if (a >= b) return a; return b; } int GetInt(

关于Linux静态库和动态库的分析

原文:http://linux.chinaunix.net/techdoc/net/2009/02/04/1060670.shtml 1.什么是库 在windows平台和linux平台下都大量存在着库.本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的本质不同,因此二者库的二进制是不兼容的. 本文仅限于介绍linux下的库.2.库的种类linux下的库有两种:静态库和共享库(动态库). 二者的不同点在于代码被载入的时刻不同.静态库的代码在编译

Linux下,动态库和静态库之间是否能够相互转化?

问题描述 Linux下,动态库和静态库之间是否能够相互转化? Linux下,动态库和静态库之间是否能够相互转化呢?现在我有一些动态共享库.so,但发布程序的时候总得在目标服务器上安装这些库,程序才能运行,我想把它们转化为静态库.a,能做到么?有这样的工具吗?谢谢大家. 解决方案 通过makefile编译的时候,生成一份动态,一份静态 解决方案二: 我有动态库文件so,但是没有源码.我现在希望做的是:动态库.so转化为静态库.a.大家帮帮忙啊.

C语言的静态库与共享库

1库的概念 2静态库 2-1 静态库的概念 2-2 静态库的创建 2-2-1 静态库创建的命令 2-2-2 静态库创建的准备工作 2-2-3 创建静态库的例子 2-3 静态库的使用 2-3-1 静态库使用的命令 2-3-2 静态库使用的例子 3共享库动态链接库 3-1 共享库的概念 3-2 共享库的创建 3-2-1 共享库的创建命令 3-2-2 共享库的创建例子 3-3 共享库的使用 3-3-1 共享库的使用命令 3-3-2 共享库的使用例子 4不使用库的方法 1.库的概念 函数库是由系统建立的

Linux静态库和动态库的编写和使用

Linux静态库和动态库的编写和使用 库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行.库分静态库和动态库两种.   1  静态库和动态库的区别 1.1. 静态函数库    (1)静态函数库的名字一般是lib[name].a (2)利用静态函数库编译成的文件比较大,因为整个函数库的所有数据都会被整合进目标代码中,它的优点是编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进去了.这给它带来的缺点为如果静态函数库改变了,那么你的程序必须重新编译. 1.2. 动态