Chinaunix首页 | 论坛 | 博客
  • 博客访问: 16422
  • 博文数量: 20
  • 博客积分: 165
  • 博客等级: 入伍新兵
  • 技术积分: 120
  • 用 户 组: 普通用户
  • 注册时间: 2012-06-26 00:19
文章分类

全部博文(20)

文章存档

2012年(20)

我的朋友

分类:

2012-08-02 16:07:16

在演示示例之前,我们先要明白以下几个概念:

1、静态库与动态库的区别:

       根据代码被载入的时间不同,linux下库分为两种:静态库和动态库(也叫共享库)。静态库,在编译时,已经被载入到可执行程序中,静态库成为可执行文件的一部分,因此可可执行程序文件比较大。动态库,可执行程序在执行时,才被引用到内存,因此可执行程序文件小。动态库,一个显著特点就是:当多个程序调用同个动态库时,内存中只有一个动态库实例。

2、库命名规范

                  a)静态库以.a 为后缀,动态库以.so为后缀

                  b)静态库名字一般是libxxx.a,其中xxx 是库的名字;动态库的名字一般是libxxx.so.major.minor 其中xxx是库名,majar 是主版本号,minor是副版本号

3、通过ldd查看程序所依赖的共享库

                      查看vim所依赖的共享库:ldd /usr/bin/vim 

4、程序查找动态库的路径

     /lib 和 /usr/lib 及 /etc/ld.so.conf配置的路径下

有了上面的简单介绍,下面,我们开始给出代码示例了:

1、库源文件:demo.c

  1. #include<stdio.h>
  2.   
  3. int add(int a, int b)
  4. {
  5.         return a+b;
  6. }
  7. int sub(int a, int b)
  8. {
  9.         return a-b;
  10. }
  11. void showmsg(const char * msg){
  12.         printf("%s \n",msg);
  13. }
  14. void show(int num)
  15. {
  16.         printf("The result is %d \n",num);
  17. }

2、库头文件: demo.h

  1. #ifndef DEMO_H
  2. #define DEMO_H
  3. extern int add(int a, int b);
  4. extern int sub(int a, int b);
  5. extern void showmsg(const char* msg);
  6. extern void show(int num);
  7. #endif

3、调用库源文件:main.c


  1. #include "demo.h"
  2.   
  3. int main(void){
  4.         int a = 3;
  5.         int b = 6;
  6.         showmsg("3+6:");
  7.         show(add(a,b));
  8.         showmsg("3-6:");
  9.         show(sub(a,b));
  10.         return 0;
  11. }

 4、编译源文件          


  1. [root@localhost demo]# gcc -c demo.c

  1. [root@localhost demo]# gcc -c main.c

5、编译可执行程序:

  1. [root@localhost demo]# gcc -o demo demo.o main.o

 6、查看可执行文件demo并执行


  1. [root@localhost demo]# ls -lh

    1. 总计 28K
    2. -rwxr-xr-x 1 root root 5.2K 02-24 10:36 demo
    3. -rw-r--r-- 1 root root 212 02-24 10:06 demo.c
    4. -rw-r--r-- 1 root root 134 02-24 09:55 demo.h
    5. -rw-r--r-- 1 root root 1000 02-24 10:10 demo.o
    6. -rw-r--r-- 1 root root 142 02-24 10:07 main.c
    7. -rw-r--r-- 1 root root 1.1K 02-24 10:36 main.o


点击(此处)折叠或打开

  1. [root@localhost ~]# ./demo
  2. 3+6:
  3. The result is 9
  4. 3-6:
  5. The result is -3

通过上面的基本,我们的可执行文件demo已经跑起来了,下面,我们主要介绍怎么把demo.c封装成库,供其他代码调用,以提高代码的可复用性

静态库:

主要通过ar 把demo.o打包成静态库并查看相关文件


  1. [root@localhost demo]# ar rcs libdemo.a demo.o

  2. [root@localhost demo]# ls -lh

  3. 总计 24K
  4. [plain] view plaincopy
  5. -rw-r--r-- 1 root root 212 02-24 10:06 demo.c
  6. -rw-r--r-- 1 root root 134 02-24 09:55 demo.h
  7. -rw-r--r-- 1 root root 1000 02-24 10:10 demo.o
  8. -rw-r--r-- 1 root root 1.2K 02-24 10:40 libdemo.a
  9. -rw-r--r-- 1 root root 142 02-24 10:07 main.c
  10. -rw-r--r-- 1 root root 1.1K 02-24 10:36 main.o

ar命令类似于tar命令,起打包的作用。选项r表示将后面的文件列表添加到文件包,如果文件包不存在就创建,
如果文件包中已存在就替换。s是专用于生成静态库的,表示为静态库创建索引,这个索引被链接器使用。

引入静态库,编译可执行文件


  1. [root@localhost demo]# gcc -o demo main.c -static -L . -l demo

注意:gcc生产目标可执行文件,用-l 指定静态库文件时,会自动在静态库名前加lib,在其后加.a 。因此,在引入libdemo.a 静态库时,只用写 demo 即可。-L . 告诉编辑器在当前目录查找函数库。【可以用nm查看目标代码,函数库和可执行程序中具有哪些函数】

查看生成文件demo,删除静态库libdemo.a ,并执行demo


  1. [root@localhost demo]# ls -lh
  2. 总计 568K
  3. -rwxr-xr-x 1 root root 537K 02-24 10:44 demo
  4. -rw-r--r-- 1 root root 212 02-24 10:06 demo.c
  5. -rw-r--r-- 1 root root 134 02-24 09:55 demo.h
  6. -rw-r--r-- 1 root root 1000 02-24 10:10 demo.o
  7. -rw-r--r-- 1 root root 1.2K 02-24 10:40 libdemo.a
  8. -rw-r--r-- 1 root root 142 02-24 10:07 main.c
  9. -rw-r--r-- 1 root root 1.1K 02-24 10:36 main.o

  10. [root@localhost demo]# rm -rf libdemo.a

  11. [root@localhost demo]# ./demo
  12. 3+6:
  13. The result is 9
  14. 3-6:
  15. The result is -3

通过上面的演示,我们可以很清楚地看到,引导引入静态库之后,可执行程序就不依赖原有静态库了,这是因为,可执行程序中已经包含了静态库。


动态库:

通过gcc生产静态库libdemo.so文件并查看相关文件



  1. [root@localhost demo]# gcc -shared -fPIC -o libdemo.so demo.o

  2. [root@localhost demo]# ls -lh
  3. 总计 28K
  4. -rw-r--r-- 1 root root 212 02-24 10:06 demo.c
  5. -rw-r--r-- 1 root root 134 02-24 09:55 demo.h
  6. -rw-r--r-- 1 root root 1000 02-24 10:10 demo.o
  7. -rwxr-xr-x 1 root root 4.3K 02-24 10:50 libdemo.so
  8. -rw-r--r-- 1 root root 142 02-24 10:07 main.c
  9. -rw-r--r-- 1 root root 1.1K 02-24 10:36 main.o


-f后面跟一些编译选项,PIC表示与位置无关代码【position independent code】

引入动态库libdemo.so,生成可执行文件demo并执行

  1. [root@localhost demo]# gcc -o demo main.c -L . -l demo

注意:-l demo 表示链接libdemo.so ,-L . 表示函数库可能在当前目录
  1. [root@localhost demo]# ls -lh
  2. 总计 36K
  3. -rwxr-xr-x 1 root root 5.4K 02-24 10:52 demo
  4. -rw-r--r-- 1 root root 212 02-24 10:06 demo.c
  5. -rw-r--r-- 1 root root 134 02-24 09:55 demo.h
  6. -rw-r--r-- 1 root root 1000 02-24 10:10 demo.o
  7. -rwxr-xr-x 1 root root 4.3K 02-24 10:50 libdemo.so
  8. -rw-r--r-- 1 root root 142 02-24 10:07 main.c
  9. -rw-r--r-- 1 root root 1.1K 02-24 10:36 main.o

  10. [root@localhost demo]# ./demo
  11. ./demo: error while loading shared libraries: libdemo.so: cannot open shared object file: No such file or directory

 

为什么,无法成功执行呢?查看可执行程序demo所依赖的动态库


  1. [root@localhost demo]# ldd demo
  2.         linux-gate.so.1 => (0x0022b000)
  3.         libdemo.so => not found
  4.         libc.so.6 => /lib/libc.so.6 (0x0022c000)
  5.         /lib/ld-linux.so.2 (0x0019c000)

从提示中,我们可以很清楚地看到,是libdemo.so 没有找到。怎么可以让可执行文件找到该动态库呢?

a)将动态库转移到系统缺省库路径下并执行

  1. [root@localhost demo]# mv libdemo.so /usr/lib
  2. [root@localhost demo]# ./demo
  3. 3+6:
  4. The result is 9
  5. 3-6:
  6. The result is -3

  7. b)设置加载库环境变量LD_LIBRARY_PATH并执行

  8. [root@localhost demo]# export LD_LIBRARY_PATH=$(pwd)
  9. [root@localhost demo]# ./demo
  10. 3+6:
  11. The result is 9
  12. 3-6:
  13. The result is -3


c)通过ldconfig 将指定目录下的动态库添加到系统共享中,也就是在缓存文件/etc/ld.so.cache中追加指定目录下的共享库

点击(此处)折叠或打开

  1. [root@localhost demo]# ldconfig /root/code/c/demo
  2. [root@localhost demo]# ./demo
  3. 3+6:
  4. The result is 9
  5. 3-6:
  6. The result is -3



附带几个参考资料网址:

gcc中文手册:

gcc官网手册:

本文参考【http://blog.csdn.net/love__coder/article/details/7288049

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