关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » HTML5 »Linux 中的静态库和动态库简介及生成过程示例

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

    2015-11-07 00:00:00 出处:w3ctech
    分享

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

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

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

    一、静态库和动态库简介

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

    库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。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 test
            linux-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目录下。

    参考资料:

    1. http://blog.chinaunix.net/uid-26833883-id-3219335.html
    2. http://blog.csdn.net/bat603/article/details/1438408
    3. http://blog.sina.com.cn/s/blog_795ed1810101789t.html

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    正版 Windows 11产品密钥怎么查找/查看?

    还有3个月,微软将停止 Windows 10 的更新

    Windows 10 终止支持后,企业为何要立即升级?

    Windows 10 将于 2025年10 月终止技术支持,建议迁移到 Windows 11

    Windows 12 发布推迟,微软正全力筹备Windows 11 25H2更新

    Linux 退出 mail的命令是什么

    Linux 提醒 No space left on device,但我的空间看起来还有不少空余呢

    hiberfil.sys文件可以删除吗?了解该文件并手把手教你删除C盘的hiberfil.sys文件

    Window 10和 Windows 11哪个好?答案是:看你自己的需求

    盗版软件成公司里的“隐形炸弹”?老板们的“法务噩梦” 有救了!

    IT头条

    公安部:我国在售汽车搭载的“智驾”系统都不具备“自动驾驶”功能

    02:03

    液冷服务器概念股走强,博汇、润泽等液冷概念股票大涨

    01:17

    亚太地区的 AI 驱动型医疗保健:2025 年及以后的下一步是什么?

    16:30

    智能手机市场风云:iPhone领跑销量榜,华为缺席引争议

    15:43

    大数据算法和“老师傅”经验叠加 智慧化收储粮食尽显“科技范”

    15:17

    技术热点

    商业智能成CIO优先关注点 技术落地方显成效(1)

    用linux安装MySQL时产生问题破解

    JAVA中关于Map的九大问题

    windows 7旗舰版无法使用远程登录如何开启telnet服务

    Android View 事件分发机制详解

    MySQL用户变量的用法

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。