linux 下的静态库和动态库

   gcc链接库: gcc的链接库分两种,分别是静态库和动态库。
1. 静态库

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

2. 动态库

    这类库的名字一般是libxxx.so;相对于静态函数库,动态函数库在编译的时候 并没有被编译进目标代码中,你的程序执行到相关函数时才调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。 
linux系统有几个重要的目录存放相应的函数库,如/lib /usr/lib。

关于使用库的问题

     如果库是已经编译好的,那么如何在开发、运行应用程序时使用呢?头文件和库文件所在的路径,必须通过适当的方式通知给编译器、链接器和相关的应用程序。
     对于静态库来说,主要涉及开发工具,如gcc。例如,用gcc编译、链接时,需要通过适当的路径找到头文件和静态库文件;实现的方法有两种:
gcc的命令行参数(-I, -L)
shell的环境变量(C_INCLUDE_PATH, LIBRARY_PATH
     对于共享库来说,程序在运行时,如果用到了动态库,也需要找到对应的动态库文件;实现的方法:
shell的环境变量(LD_LIBRARY_PATH)
1) gcc命令行参数(-I, -L)
     默认情况下,gcc会自动搜索下面的路径:
对头文件:
/usr/local/include/
/usr/include/
对库文件:
/usr/local/lib/
/usr/lib/
     但是由于系统管理员对系统安装路径有不同的配置,或者对于如64位系统等情况,上述路径对于一台具体的计算机来说可能不同。如果开发者还有自己工程所需的头文件和库文件,就要用gcc的-I和-L来指定对应的路径。如果需要链接库,还要用-l选项。
     例如:如果工程涉及到GDBM(GNU DataBase Management)包,需要libgdbm库,而系统中安装GDBM的路径是:
头文件:/opt/gdbm-1.8.3/include
库文件:/opt/gdbm-1.8.3/lib/
     那么,gcc的命令参数是:
$gcc … -I/opt/gdbm-1.8.3/include -L/opt/gdbm-1.8.3/lib –lgdbm
     注意:为保证兼容性,必须坚决杜绝在C/C++源文件的#include语句中或者其他相关语句中使用上述路径。
2) shell环境变量(Environmental Variable)
     除了用命令行参数,还可以用环境变量来指示gcc搜索适当的路径。而由于Shell的不同,环境变量的设置方法也不同。常用的Shell有Bash, Csh和Tcsh。
(1)Bash
     对于Bash来说,除了由系统管理员配置的内容以外,每个用户的用户目录($HOME)下,有个.bash_profile文件。可在该文件内,增加下面的两个语句来设置GDBM头文件路径的环境变量:
C_INCLUDE_PATH=/opt/gdbm-1.8.3/include
export C_INCLUDE_PATH
     类似地,在该文件内用下面的两个语句来设置库文件路径的环境变量:
LIBRARY_PATH=/opt/gdbm-1.8.3/lib
export LIBRARY_PATH
     在.bash_profile中有了上述语句以后,就不用再使用-I和-L来搜索特定包的路径了。但是链接库的时候,还是要用-l选项。
$gcc … –lgdbm
     在Bash下,要检查有什么样的环境变量,可用env命令。
$env
(2)Csh和Tcsh
     如果是Csh或Tcsh,对环境变量的设置方法就不同了。在用户的($HOME)目录下,相关的一些文件如下:
.cshrc 每次进入Csh时的启动(Startup)文件
.tcshrc 每次进入Tcsh时的启动(Startup)文件(在Tcsh下,如果没有这个文件,系统会用.cshrc文件代替)
.login 每次登录Shell时的启动(Startup)文件
     在Csh和Tcsh下,分为Shell变量和环境变量;前者是用来设置Shell本身的,而后者则是供其他程序使用的。一般习惯是:Shell变量在.cshrc中定义,而环境变量则在.login文件中定义。
     定义Shell变量的方法是在.cshrc或.tcshrc中用set语句:
set history = 20
     定义环境变量的方法是在.login文件中用setenv语句。对于上面关于GDBM的例子:
setenv C_INCLUDE_PATH /opt/gdbm-1.8.3/include
setenv LIBRARY_PATH /opt/gdbm-1.8.3/lib
     在Csh和Tcsh下,可以用setenv命令来查看设置了哪些环境变量(如果要看Shell变量,要用set命令)。
注意:
- 设置Shell变量时要用“=”号;
- 设置环境变量时,变量名与实际值(这里是真实路径)之间没有“=”号;
- 不需要export。
3) 使用共享库
     使用共享库的应用程序,要通过环境变量LD_LIBRARY_PATH找到对应的共享库文件。与其他环境变量一样,对LD_LIBRARY_PATH也要根据shell的种类和库文件的实际路径进行设置。但是,必须注意的是,与一般的环境变量不同,LD_LIBRARY_PATH的值,是已经安装了的所有共享库的路径,因此,在Bash下,不能简单地用下面的办法:
LD_LIBRARY_PATH=/opt/gdbm-1.8.3/lib 错误!
export LD_LIBRARY_PATH
     而必须用:
LD_LIBRARY_PATH=/opt/gdbm-1.8.3/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH
     这样,就把其他共享库的路径也一起加入进来了。同样地,在Csh和Tcsh下,
setenv LD_LIBRARY_PATH /opt/gdbm-1.8.3/lib:$LD_LIBRARY_PATH

关于库生成的问题
    我们通常把一些公用函数制作成函数库,供其它程序使用。函数库分为静态库和动态库两种。静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。

(1) 静态库
     简单地说,静态库是一个目标文件的简单集合。因此,首先要解决目标文件。
     第一步:将各函数代码所在的源文件编译成目录文件。
     例如,对于myfunc.c, myproc.c
gcc -c myfunc.c myproc.c
将得到myfunc.o和myproc.o。
     第二步:由ar(archive,归档的意思)把多个目标文件集合起来。
$ar -r libmyjob.a myfunc.o myproc.o
     通常,静态库的命名方式应遵守libXXXXX.a格式。应用程序在使用静态库的时候,通常只需要把命名中的XXXXX部分传递给gcc即可。例如:
$gcc –o mywork –lmyjob …
     意为让gcc(实际上是gcc调用ld)去连接一个名字为libmyjob.a(或者libmyjob.so)的库。如果库的命名不遵循libXXXXX.a的格式就找不到相应文件。
例子:创建静态库
   hello.h为该函数库的头文件。hello.c是函数库的源程序,其中包含公用函数hello,该函数将在屏幕上输出"
hello XXX!"。main.c为 测试 库文件的主程序,在主程序中调用了公用函数hello。
程序1:
//hello.h
#ifndef HELLO_H
#define HELLO_H
void hello(const char *name);
#endif
程序2:
//hello.c
#include <stdio.h>
void hello(const char *name)
{
  printf("hello %s! /n",name);
}
程序3:
//main.c
#include "hello.h"
int main()
{
  hello("everyone");
  return 0;
}

(2)动态库
     共享库的构造复杂一些,通常是一个ELF格式的文件。可以有三种方法生成:
$ld -G
$gcc -shared
$libtool
     用ld最复杂,用gcc -share就简单的多,但是-share并非在任何平台都可以使用。GNU提供了一个更好的工具libtool,专门用来在各种平台上生成各种库。
     用gcc的-shared参数:
gcc –shared –o libmyjob.so myjob.o
     这样,就通过myjob.o生成了共享库文件libmyjob.so。
     特别地,在CYGWIN环境下,仍需要输出符合Windows命名的共享库(动态库),即libXXXXX.dll。如:
gcc –shared –o libmyjob.dll myjob.o


库的查看:使用ldd命令来查看执行文件依赖于哪些库。(ldd+文件名)

eg:

              

ldd mutex  查看可执行程序mutex依赖于动态库libpthread.so



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值