Linux中的动态函数库和静态函数库的比较

简介:

  库函数既提高了代码的利用率,又屏蔽了函数内部实现的细节,给不同开发者提供了统一的接口。从实现来看,库函数可以分为动态函数库和静态函数库。同一组函数,可以根据需要封装成静态库和动态库。那么生成静态库和动态库有什么区别?静态库和动态库对函数的实现上各有些什么要求?两者对内存各有什么影响呢?下面就带着这些问题一起开探讨。

静态库和动态库生成方式的区别
为了简化,下面以一个只有一个函数的库的实现来说明。库函数的代码demo.c如下:
/*******************************************************************/
int cal(int a, int b)
{
        return (a^(a << b)) + (b << a);
}

main.c中的代码如下:
[root@localhost mylib]# cat main.c 
#include<stdio.h>
#include "demo.h"

int main(void)
{
        printf("Call cal(7,8) = %08x\n", cal(7,8));
}
[root@localhost mylib]# cat demo.h
int cal(int, int);
如果需要生成动态库,则需要用到下面的Makefile:
MYLIB := libdemo.so
BIN := test
CFLAG := -Wall -I../ -I./ -DTEST=1
LIBFLAG := -L./ -rpath=/home/xqch/workspace/mylib ./ -ldemo

all: $(MYLIB) $(BIN)

$(BIN): main.o 
        gcc $(CFLAG) -L/home/xqch/workspace/mylib -ldemo -o $@  $^

$(MYLIB): demo.o
        ld -shared -fpic -rpath=/home/xqch/workspace/mylib -o $@ $^

%.o:%.c
        gcc $(CFLAG) -c -o $@ $<

.PHONY: install clean

install:
        cp $(MYLIB) /usr/lib
        cp $(MYLIB) /lib

clean:
        rm -rf *.o $(BIN) $(MYLIB)
而生成静态库的过程如下:
[xqch@localhost mylib]$ cat Makefile
MYLIB := libdemo.a
BIN := main
CFLAG := -Wall -I../ -I./ -DTEST

all: $(MYLIB) $(BIN)

$(BIN): main.o 
        gcc $(CFLAG) -o $@  $^ $(MYLIB)

$(MYLIB): demo.o
        ar -rcv $@ $^

%.o:%.c
        gcc $(CFLAG) -c -o $@ $<


.PHONY: clean
clean:
        rm -rf *.o $(BIN) $(MYLIB)

静态库和动态库生成的二进制代码的区别
基于上面的两个Makefile我们可以对比下它们的区别:
[xqch@localhost mylib]$ ls -alrt main
-rwxrwxr-x. 1 xqch xqch 7696 Oct 26 21:21 main
dynamic:
[xqch@localhost mylib]$ ls -alrt test
-rwxrwxr-x. 1 xqch xqch 7602 Oct 25 19:32 test
可以看到静态库生成的可执行文件比需要链接动态库生成的可执行文件大.通过反汇编,我们可以看到差异就在于对库函数的调用方式不同:
static:
08048724 <cal>:
 8048724:   55                      push   %ebp
 8048725:   89 e5                   mov    %esp,%ebp                                                                                                  
 8048727:   53                      push   %ebx
 8048728:   83 ec 04                sub    $0x4,%esp
 804872b:   a1 30 a0 04 08          mov    0x804a030,%eax
 8048730:   83 c0 01                add    $0x1,%eax
 8048733:   a3 30 a0 04 08          mov    %eax,0x804a030
 8048738:   a1 3c a0 04 08          mov    0x804a03c,%eax
 804873d:   83 c0 01                add    $0x1,%eax
 8048740:   a3 3c a0 04 08          mov    %eax,0x804a03c
 8048745:   a1 38 a0 04 08          mov    0x804a038,%eax
 804874a:   83 c0 01                add    $0x1,%eax
 804874d:   a3 38 a0 04 08          mov    %eax,0x804a038
 8048752:   8b 0d 38 a0 04 08       mov    0x804a038,%ecx

dynamic:
080485a0 <cal@plt>:                                                                                                                                                    
 80485a0:   ff 25 2c a0 04 08       jmp    *0x804a02c
 80485a6:   68 40 00 00 00          push   $0x40
 80485ab:   e9 60 ff ff ff          jmp    8048510 <_init+0x2c>

静态库和动态库对代码的要求
两者共同点是如果需要对多线程代码的支持,代码里不能出现全局变量和动态变量和静态变量(函数内部和外部的),因为它们最后都是放在.bss或者.data段,而同进程的不同线程间共享同一个数据段,某个线程调用使用那些变量函数后,后面的调用函数看到就是改变的值。

静态库和动态库对内存的影响
静态程序占用内存较多,动态程序反之。因为动态程序是在执行时连接,添加被调用的动态函数的地址到.got.plt(process link table)中去。




















本文转自存储之厨51CTO博客,原文链接:http://blog.51cto.com/xiamachao/1712108 ,如需转载请自行联系原作者

相关文章
|
16天前
|
Linux
【Linux】System V信号量详解以及semget()、semctl()和semop()函数讲解
System V信号量的概念及其在Linux中的使用,包括 `semget()`、`semctl()`和 `semop()`函数的具体使用方法。通过实际代码示例,演示了如何创建、初始化和使用信号量进行进程间同步。掌握这些知识,可以有效解决多进程编程中的同步问题,提高程序的可靠性和稳定性。
65 19
|
18天前
|
Linux Android开发 开发者
linux m、mm、mmm函数和make的区别
通过理解和合理使用这些命令,可以更高效地进行项目构建和管理,特别是在复杂的 Android 开发环境中。
52 18
|
1月前
|
存储 编译器 Linux
动态链接的魔法:Linux下动态链接库机制探讨
本文将深入探讨Linux系统中的动态链接库机制,这其中包括但不限于全局符号介入、延迟绑定以及地址无关代码等内容。
466 22
|
5月前
|
安全 Linux vr&ar
Linux的动态库和静态库
Linux的动态库和静态库
|
26天前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
94 13
|
3月前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
123 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
4月前
|
Linux Shell
Linux系统编程:掌握popen函数的使用
记得在使用完 `popen`打开的流后,总是使用 `pclose`来正确关闭它,并回收资源。这种做法符合良好的编程习惯,有助于保持程序的健壮性和稳定性。
191 6
|
4月前
|
Linux Shell
Linux系统编程:掌握popen函数的使用
记得在使用完 `popen`打开的流后,总是使用 `pclose`来正确关闭它,并回收资源。这种做法符合良好的编程习惯,有助于保持程序的健壮性和稳定性。
203 3
|
4月前
|
Linux
在Linux内核中根据函数指针输出函数名称
在Linux内核中根据函数指针输出函数名称
|
5月前
|
Linux PHP
Linux CentOS 宝塔 Suhosin禁用php5.6版本eval函数详细图文教程
【8月更文挑战第27天】本文介绍两种禁用PHP执行的方法:使用`PHP_diseval_extension`禁用和通过`suhosin`禁用。由于`suhosin`不支持PHP8,仅适用于PHP7及以下版本,若服务器安装了PHP5.6,则需对应安装`suhosin-0.9.38`版本。文章提供了详细的安装步骤,并强调了宝塔环境下与普通环境下的PHP路径差异。安装完成后,在`php.ini`中添加`suhosin.so`扩展并设置`executor.disable_eval = on`以禁用执行功能。最后通过测试代码验证是否成功禁用,并重启`php-fpm`服务生效。
78 2