【文章摘要】
在实际的软件开发项目中,不是每一行代码都需要我们亲自写。在我们的软件产品中,有一些代码(尤其是函数)的出现频率很高,它们可以被当作公共代码来反复使用。为了避免重复劳动,我们就把这些公共代码编译为库文件,供需要的程序调用。在Linux中,库分为静态库和动态库两种。

目录

  • 目录
  • 一静态库和动态库简介
  • 二静态库生成示例
    • 单个文件生成静态库示例
    • 多个文件生成静态库示例
  • 三动态库生成示例
    • 单个文件生成动态库示例
    • 多个文件生成动态库示例
  • 四总结
  • 参考文献

本文对静态库和动态库进行了详细的介绍,并用实际的C代码演示了这两种库的生成过程。

一、静态库和动态库简介

众所周知,程序一般需要经过预处理、编译、汇编和链接这几个步骤才能变成可执行的程序。在实际的软件开发中,对于一些需要被许多模块反复使用的公共代码,我们就将它们编译为库文件。

库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。Linux支持的库分为静态库和动态库,动态库又称共享库。一般说来,Linux中的一些重要的库是存放在lib目录下的。

静态库文件的后缀为.a,在Linux下一般命名为libxxx.a。在链接步骤中,连接器将从静态库文件中取得所需的代码,复制到生成的可执行文件中。因此,整个库中的所有函数都被编译进了目标代码中。

动态库文件的后缀为.so,在Linux下一般命名为libxxx.so。相对于静态库,动态库在编译的时候并没有被编译进目标代码中,而是程序执行到相关函数时才调用库中对应的函数。

可以看到,静态库的优点是编译后的执行程序不需要外部的函数库支持,缺点是如果静态函数库改变了,那么你的程序必须重新编译;而动态库在多个应用程序都要使用同一函数库的时候就非常适合,但前提是程序的运行环境中必须提供相应的库。

不管是静态库,还是动态库,都是由*.o目标文件生成的。

二、静态库生成示例

1.单个文件生成静态库示例

我们编写如下简单的三个程序文件:test.h、test.c和main.c,在main.c中要调用test.c中实现的函数test。
test.h文件内容:

#include <stdio.h>void test();

test.c文件内容:

#include "test.h"void test()
{printf("this is in test......\n");
}

main.c文件内容:

#include "test.h"int main()
{test();return 0;
}

将此三个文件上传到Linux机器上,编译生成静态库文件,之后调用库文件的整个过程如下所示:

~/zhouzhaoxiong/zzx/mytest/a/single> ll
-rw------- 1 zhou dba 53 Nov  4 16:04 main.c
-rw------- 1 zhou dba 80 Nov  4 16:04 test.c
-rw------- 1 zhou dba 36 Nov  4 16:04 test.h
~/zhouzhaoxiong/zzx/mytest/a/single> gcc -c test.c
~/zhouzhaoxiong/zzx/mytest/a/single> ll
-rw------- 1 zhou dba   53 Nov  4 16:04 main.c
-rw------- 1 zhou dba   80 Nov  4 16:04 test.c
-rw------- 1 zhou dba   36 Nov  4 16:04 test.h
-rw-rw-rw- 1 zhou dba 1624 Nov  4 16:06 test.o
~/zhouzhaoxiong/zzx/mytest/a/single> ar -r libtest.a test.o
ar: creating libtest.a
~/zhouzhaoxiong/zzx/mytest/a/single> ll
-rw------- 1 zhou dba   53 Nov  4 16:04 main.c
-rw-rw-rw- 1 zhou dba 1766 Nov  4 16:06 libtest.a
-rw------- 1 zhou dba   80 Nov  4 16:04 test.c
-rw------- 1 zhou dba   36 Nov  4 16:04 test.h
-rw-rw-rw- 1 zhou dba 1624 Nov  4 16:06 test.o
~/zhouzhaoxiong/zzx/mytest/a/single> gcc -o test main.c libtest.a
~/zhouzhaoxiong/zzx/mytest/a/single> ll
-rw------- 1 zhou dba    52 Nov  4 16:09 main.c
-rwxrwxrwx 1 zhou dba 11876 Nov  4 16:09 test
-rw-rw-rw- 1 zhou dba  1766 Nov  4 16:06 libtest.a
-rw------- 1 zhou dba    80 Nov  4 16:04 test.c
-rw------- 1 zhou dba    36 Nov  4 16:04 test.h
-rw-rw-rw- 1 zhou dba  1624 Nov  4 16:06 test.o
~/zhouzhaoxiong/zzx/mytest/a/single> ./test
this is in test......

我们可以看到,生成库文件的命令是“ar -r libtest.a test.o”,而将静态库文件编译进代码的命令是“gcc -o test main.c libtest.a”。
这样生成了静态库文件libtest.a之后,如果还有其他程序要调用test.c中实现的函数,只需要将test.h和libtest.a拷贝到对应的代码工程中,然后执行类似“gcc -o test main.c libtest.a”这样的命令即可。

2.多个文件生成静态库示例

我们编写如下简单的五个程序文件:test.h、test_1.c、test_2.c、test_3.c和main.c,在main.c中要调用test_1.c、test_2.c、test_3.c中实现的函数test_1、test_2、test_3。
test.h文件内容:

#include <stdio.h>void test_1();
void test_2();
void test_3();

test_1.c文件内容:

#include "test.h"void test_1()
{printf("this is in test_1......\n");
}

test_2.c文件内容:

#include "test.h"void test_2()
{printf("this is in test_2......\n");
}

test_3.c文件内容:

#include "test.h"void test_3()
{printf("this is in test_3......\n");
}

main.c文件内容:

#include "test.h"int main()
{test_1();test_2();test_3();return 0;
}

将此五个文件上传到Linux机器上,编译生成静态库文件,之后调用库文件的整个过程如下所示:

~/zhouzhaoxiong/zzx/mytest/a/more> ll
-rw------- 1 zxin10 dba 96 Nov  4 16:11 main.c
-rw------- 1 zxin10 dba 70 Nov  4 16:04 test.h
-rw------- 1 zxin10 dba 84 Nov  4 16:04 test_1.c
-rw------- 1 zxin10 dba 84 Nov  4 16:04 test_2.c
-rw------- 1 zxin10 dba 84 Nov  4 16:04 test_3.c
~/zhouzhaoxiong/zzx/mytest/a/more> gcc -c test_1.c test_2.c test_3.c
~/zhouzhaoxiong/zzx/mytest/a/more> ll
-rw------- 1 zxin10 dba   96 Nov  4 16:11 main.c
-rw------- 1 zxin10 dba   70 Nov  4 16:04 test.h
-rw------- 1 zxin10 dba   84 Nov  4 16:04 test_1.c
-rw-rw-rw- 1 zxin10 dba 1624 Nov  4 16:15 test_1.o
-rw------- 1 zxin10 dba   84 Nov  4 16:04 test_2.c
-rw-rw-rw- 1 zxin10 dba 1624 Nov  4 16:15 test_2.o
-rw------- 1 zxin10 dba   84 Nov  4 16:04 test_3.c
-rw-rw-rw- 1 zxin10 dba 1624 Nov  4 16:15 test_3.o
~/zhouzhaoxiong/zzx/mytest/a/more> ar -r libtest.a test_1.o test_2.o test_3.o
ar: creating libtest.a
~/zhouzhaoxiong/zzx/mytest/a/more> ll
-rw------- 1 zxin10 dba   96 Nov  4 16:11 main.c
-rw-rw-rw- 1 zxin10 dba 5158 Nov  4 16:15 libtest.a
-rw------- 1 zxin10 dba   70 Nov  4 16:04 test.h
-rw------- 1 zxin10 dba   84 Nov  4 16:04 test_1.c
-rw-rw-rw- 1 zxin10 dba 1624 Nov  4 16:15 test_1.o
-rw------- 1 zxin10 dba   84 Nov  4 16:04 test_2.c
-rw-rw-rw- 1 zxin10 dba 1624 Nov  4 16:15 test_2.o
-rw------- 1 zxin10 dba   84 Nov  4 16:04 test_3.c
-rw-rw-rw- 1 zxin10 dba 1624 Nov  4 16:15 test_3.o
~/zhouzhaoxiong/zzx/mytest/a/more> gcc -o test main.c libtest.a
~/zhouzhaoxiong/zzx/mytest/a/more> ll
-rw------- 1 zxin10 dba    96 Nov  4 16:11 main.c
-rwxrwxrwx 1 zxin10 dba 12008 Nov  4 16:16 test
-rw-rw-rw- 1 zxin10 dba  5158 Nov  4 16:15 libtest.a
-rw------- 1 zxin10 dba    70 Nov  4 16:04 test.h
-rw------- 1 zxin10 dba    84 Nov  4 16:04 test_1.c
-rw-rw-rw- 1 zxin10 dba  1624 Nov  4 16:15 test_1.o
-rw------- 1 zxin10 dba    84 Nov  4 16:04 test_2.c
-rw-rw-rw- 1 zxin10 dba  1624 Nov  4 16:15 test_2.o
-rw------- 1 zxin10 dba    84 Nov  4 16:04 test_3.c
-rw-rw-rw- 1 zxin10 dba  1624 Nov  4 16:15 test_3.o
~/zhouzhaoxiong/zzx/mytest/a/more> ./test
this is in test_1......
this is in test_2......
this is in test_3......

我们可以看到,生成静态库文件的命令是“ar -r libtest.a test_1.o test_2.o test_3.o”,而将静态库文件编译进代码的命令是“gcc -o test main.c libtest.a”。
这样生成了静态库文件libtest.a之后,如果还有其他程序要调用test_1.c、test_2.c、test_3.c中实现的函数,只需要将test.h和libtest.a拷贝到对应的代码工程中,然后执行类似“gcc -o test main.c libtest.a”这样的命令即可。

三、动态库生成示例

1.单个文件生成动态库示例

我们编写如下简单的三个程序文件:so_test.h、test_a.c和test.c,在test.c中要调用test_a.c中实现的函数test_a。
so_test.h文件内容:

#include <stdio.h>void test_a();

test_a.c文件内容:

#include "so_test.h"void test_a()
{printf("this is in test_a...\n");
}

test.c文件内容:

#include "so_test.h"int main()
{test_a();return 0;
}

将此三个文件上传到Linux机器上,编译生成动态库文件,之后调用库文件的整个过程如下所示:

~/zhouzhaoxiong/zzx/mylib/so> ll
-rw------- 1 zxin10 dba  95 Nov  4 17:37 so_test.h
-rw------- 1 zxin10 dba 109 Nov  4 17:37 test.c
-rw------- 1 zxin10 dba  84 Nov  4 10:57 test_a.c
~/zhouzhaoxiong/zzx/mylib/so> gcc test_a.c -fPIC -shared -o libtest.so
~/zhouzhaoxiong/zzx/mylib/so> ll
-rwxrwxrwx 1 zxin10 dba 8181 Nov  4 17:43 libtest.so
-rw------- 1 zxin10 dba   95 Nov  4 17:37 so_test.h
-rw------- 1 zxin10 dba  109 Nov  4 17:37 test.c
-rw------- 1 zxin10 dba   84 Nov  4 10:57 test_a.c
~/zhouzhaoxiong/zzx/mylib/so> gcc test.c -L. -ltest -o test
~/zhouzhaoxiong/zzx/mylib/so> ll
-rwxrwxrwx 1 zxin10 dba  8181 Nov  4 17:43 libtest.so
-rw------- 1 zxin10 dba    95 Nov  4 17:37 so_test.h
-rwxrwxrwx 1 zxin10 dba 11805 Nov  4 17:44 test
-rw------- 1 zxin10 dba   109 Nov  4 17:37 test.c
-rw------- 1 zxin10 dba    84 Nov  4 10:57 test_a.c
~/zhouzhaoxiong/zzx/mylib/so> ./test
this is in test_a...

注意,“./test”命令执行成功的前提是在环境变量中添加了.so文件所在的路径,这个路径可以在“.bash_profile”文件的“LD_LIBRARY_PATH”变量的值中添加。

我们可以看到,生成动态库文件的命令是“gcc test_a.c -fPIC -shared -o libtest.so”,而将动态库文件编译进代码的命令是“gcc test.c -L. -ltest -o test”(-L.表示当前路径)。

这样生成了动态库文件libtest.so之后,如果还有其他程序要调用test_a.c中实现的函数,只需要将so_test.h和libtest.so拷贝到对应的代码工程中,然后执行类似“gcc test.c -L. -ltest -o test”这样的命令即可(前提是libtest.so所在的路径在环境变量中设置正确)。

2.多个文件生成动态库示例

我们编写如下简单的五个程序文件:so_test.h、test_a.c、test_b.c、test_c.c和test.c,在test.c中要调用test_a.c、test_b.c、test_c.c中实现的函数test_a、test_b、test_c。
so_test.h文件内容:

#include <stdio.h>void test_a();
void test_b();
void test_c();

test_a.c文件内容:

#include "so_test.h"void test_a()
{printf("this is in test_a...\n");
}

test_b.c文件内容:

#include "so_test.h"void test_b()
{printf("this is in test_b...\n");
}

test_c.c文件内容:

#include "so_test.h"void test_c()
{printf("this is in test_c...\n");
}

test.c文件内容:

#include "so_test.h"int main()
{test_a();test_b();test_c();return 0;
}

将此五个文件上传到Linux机器上,编译生成动态库文件,之后调用库文件的整个过程如下所示:

~/zhouzhaoxiong/zzx/mylib/test_so> ll
-rwxrwxrwx 1 zxin10 dba 8309 Nov  5 09:12 libtest
-rw------- 1 zxin10 dba   70 Nov  5 13:44 so_test.h
-rw------- 1 zxin10 dba  105 Nov  4 15:25 test.c
-rw------- 1 zxin10 dba   84 Nov  4 15:25 test_a.c
-rw------- 1 zxin10 dba   84 Nov  4 15:25 test_b.c
-rw------- 1 zxin10 dba   84 Nov  4 15:25 test_c.c
~/zhouzhaoxiong/zzx/mylib/test_so> gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so
~/zhouzhaoxiong/zzx/mylib/test_so> gcc test.c -L. -ltest -o test
~/zhouzhaoxiong/zzx/mylib/test_so> ll
-rwxrwxrwx 1 zxin10 dba  8309 Nov  5 13:46 libtest.so
-rw------- 1 zxin10 dba    70 Nov  5 13:44 so_test.h
-rwxrwxrwx 1 zxin10 dba 11883 Nov  5 13:46 test
-rw------- 1 zxin10 dba   105 Nov  4 15:25 test.c
-rw------- 1 zxin10 dba    84 Nov  4 15:25 test_a.c
-rw------- 1 zxin10 dba    84 Nov  4 15:25 test_b.c
-rw------- 1 zxin10 dba    84 Nov  4 15:25 test_c.c
~/zhouzhaoxiong/zzx/mylib/test_so> ./test
this is in test_a...
this is in test_b...
this is in test_c...

注意,“./test”命令执行成功的前提仍然是在环境变量中添加了.so文件所在的路径,这个路径可以在“.bash_profile”文件的“LD_LIBRARY_PATH”变量的值中添加。

我们可以看到,多个文件生成动态库文件的命令是“gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so”,而将动态库文件编译进代码的命令是“gcc test.c -L. -ltest -o test”(-L.表示当前路径)。

这样生成了动态库文件libtest.so之后,如果还有其他程序要调用test_a.c、test_b.c、test_c.c中实现的函数,只需要将so_test.h和libtest.so拷贝到对应的代码工程中,然后执行类似“gcc test.c -L. -ltest -o test”这样的命令即可(前提是libtest.so所在的路径在环境变量中设置正确)。

四、总结

有关生成静态库和动态库的命令,说明如下:

第一,在本文中,我们使用的生成静态库的命令形如“ar -r test.a test.o”,其中,-r是replace的意思,表示如果当前插入的模块名已经在库中存在,则替换同名的模块。我们也可以用形如“ar -cr test.a test.o”的命令来生成静态库,其中-c是create的意思,表示生成。

第二,在本文中,我们使用的生成动态库文件的命令形如“gcc test_a.c -fPIC -shared -o libtest.so”,其中,fPIC表示编译为位置独立的代码,shared表示生成的库为共享库。将动态库文件编译进代码的命令是“gcc test.c -L. -ltest -o test”,-L指定库查找的位置(注意L后面还有’.’),表示在当前目录下查找(如果在当前目录下的lib目录下查找,可以写成-L./lib);-l则指定函数库名,其中的lib和.so省略(如这里的libtest.so就简写为test)。

第三,使用ldd命令可以查看一个可执行程序依赖的共享库,该命令的使用示例如下所示:

~/zhouzhaoxiong/zzx/mylib/test_so> ldd testlinux-vdso.so.1 =>  (0x00007fff1db6e000)libtest.so => /home/zhou/lib/libtest.so (0x00007fdbfff21000)libc.so.6 => /lib64/libc.so.6 (0x00007fdbffb95000)/lib64/ld-linux-x86-64.so.2 (0x00007fdc00124000)

可以看到,可执行文件test依赖于四个共享库,其中libtest.so位于当前用户的lib目录下。

参考文献

linux中.o,.a,.o,.so文件的意义和编程实现


Linux中的静态库和动态库简介及生成过程示例相关推荐

  1. linux 中如何将文件粘贴到usr下的lib内,学会在Linux下GCC生成和使用静态库和动态库...

    一.基本概念1.1什么是库 在windows平台和linux平台下都大量存在着库. 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不同(主 ...

  2. Linux中gcc的编译、静态库和动态库的制作

    欢迎大家关注笔者,你的关注是我持续更博的最大动力 Linux中gcc的编译.静态库.动态库 文章目录: 1 gcc的编译过程 1.1 gcc的编译过程 1.2 gcc的常用参数 2 gcc 静态库的制 ...

  3. 在Linux中创建静态库和动态库 (转)

    我们通常把一些公用函数制作成函数库,供其它程序使用.函数库分为静态库和动态库两种.静态 库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库.动态库在程序编译时并不会被连接到目标代码中,而 ...

  4. 在Linux中创建静态库.a和动态库.so

    转自:http://www.cnblogs.com/laojie4321/archive/2012/03/28/2421056.html 在Linux中创建静态库.a和动态库.so 我们通常把一些公用 ...

  5. linux下终端urvst,Linux中的静态库与动态库

    #什么是库文件? 库文件是事先编译好的方法的合集.比如:我们提前写好一些数据公式的实现,将其打包成库文件,以后使用只需要库文件就可以,不需要重新编写. #Linux系统中: 1.静态库的扩展名为.a: ...

  6. Linux中静态库和动态库(共享库)的区别

    1. 静态库和动态库的制作过程区别 1.1 静态库的制作过程 详见博客:Linux中静态库的制作与使用 1.2 动态库的制作过程 详见博客:Linux中动态库(共享库)的制作与使用 2. 静态库和动态 ...

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

    From: http://hi.baidu.com/bdccutysj/blog/item/5bae7f0202abac7c3912bb15.html 1.什么是库 在windows平台和linux平 ...

  8. Linux下的静态库、动态库和动态加载库

    from: http://www.techug.com/linux-static-lib-dynamic-lib 库的存在极大的提高了C/C++程序的复用性,但是库对于初学者来说有些难以驾驭,本文从L ...

  9. linux下的共享库(动态库)和静态库

    1.什么是库 在windows平台和linux平台下都大量存在着库. 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的本质不同,因此二者库的二进 ...

  10. Linux下制作和使用静态库和动态库

    写在前面: ldd + 可执行文件 可以查看可执行文件所依赖的库 概述: Linux操作系统支持的函数库分为静态库和动态库,动态库又称共享库.linux系统有几个重要的目录存放相应的函数库,如/lib ...

最新文章

  1. 干货|六维力和力矩传感器的技术与应用
  2. 尾递归调用 高阶函数 map filter reduce
  3. IAR FOR ARM 各版本,需要的大家可以收藏了
  4. 文件操作-打开文件方式以及写入和追加数据
  5. java 扫描所有子类_java获取全部子类或接口的全部实现
  6. PHP百度收录量查询接口源码,PHP百度收录量查询接口源码
  7. “关起门来搞开源,做不了开源世界的Leader”
  8. 对Vue生命周期的一些简单见解
  9. mysql 客房_mysql – 酒店客房预订系统的数据库设计
  10. Java集合框架HashMap和ConcurrentHashMap实现分析
  11. electron 多语言_Electron实用技巧electronbuilder中用户协议(license)的使用及多语言支持...
  12. Webstorm全版本汉化包
  13. 【技术分享】select下拉框option默认选中(php模板渲染)
  14. 被遗忘的艺术——图思维方式
  15. Android NFC详解(高级)
  16. WdatePicker日历控件参数配置大全
  17. 爬虫学习笔记(二)http请求详解
  18. 如何解决后台传回的数据不是正常的json数据,例如是个List [ ]
  19. VS CODE 很强大
  20. 深入浅出学习结构方程模型【2应用篇】

热门文章

  1. NSString的长度比较方法(一)
  2. *SQL Server系统表的应用
  3. 数据结构-第10周作业(二叉树的创建和遍历算法)
  4. Entity Framework 代码先行之约定配置
  5. 网站技术架构发展之我见--[引子]
  6. IOS xib 和storyboard的区别
  7. 移动web:tab选项卡
  8. Topcoder SRM 656 (Div.1) 250 RandomPancakeStack - 概率+记忆化搜索
  9. 推荐一款弹出窗口插件 lhgdialog 4.2.0 正式版
  10. OBIEE中设置动态变量为列名