在我过往的文章中,我曾详细探讨过这一议题,以下便是其中摘录的一部分内容关于capx。
当我们使用capx配置好的vim环境时,可以输入以下代码:
// 文件名 t.c
#include <stdio.h>
int main()
printf("hello embedTime ");
return 0;
上述代码引入了stdio头文件,调用了printf库函数,因此编译时必然涉及capx链接库。在Linux系统中,存在两种类型的链接库:一种是通常所说的“静态链接库(static library)”,另一种则被称为“动态链接库(shared library)”。
动态链接是一种被广泛应用的技术,动态链接库的字面意思是“共享的库”。确实如此,当使用动态链接库的程序加载时,Linux内核会检查程序所依赖的库是否已经在内存中。如果已在,则内核不会重新加载库,而是直接执行程序。因此,多个程序可以共享同一个库,这在实际上可以节省资源。
对于静态链接库,程序在链接时会将其作为程序的一部分,因此,与动态链接方式相比,最终生成的可执行程序体积会更大一些。
接下来,我们来编译这个程序:
# gcc t.c -o shared.out
上述编译命令采用了动态链接的方式。通过在gcc命令后附加-stactic参数,可以以静态链接方式编译程序:
# gcc t.c -static -o static.out
现在,让我们对比一下这两种链接方式生成的可执行程序的大小:
# ls -ahl
total 888K
drwxr-xr-x 3 root root 4.0K Dec 17 22:40 .
drwxr-xr-x 8 root root 4.0K Dec 11 10:28 ..
drwxr-xr-x 2 root root 4.0K Dec 17 22:39 his-
-rwxr-xr-x 1 root root 8.4K Dec 17 22:40 shared.out
-rwxr-xr-x 1 root root 857K Dec 17 22:40 static.out
-rw-r--r-- 1 root root 76 Dec 17 21:37 t.c
显而易见,使用静态链接方式生成的可执行程序,其体积比使用动态链接方式生成的可执行程序大出百倍之多。虽然几百KB对于大多数Linux主机来说可能不算什么,但在嵌入式系统中,资源通常非常有限,因此,简单地使用静态链接就显得过于奢侈。
使用静态链接也有其优点,生成的可执行程序可以脱离库独立运行,而使用动态链接的可执行程序则不能脱离库独立运行。
静态链接和动态链接的可执行程序,在执行过程中有哪些不同之处呢?
上面我们已经讨论了Linux中程序的两种链接方式。既然可执行程序的体积差异如此之大,它们的执行过程也应该有所不同。确实如此,现在让我们一起来分析一下。
在Linux中,我们可以使用strace命令来分析程序的执行过程。
首先,我们来分析shared.out程序,输入strace ./shared.out,会发现一大堆输出信息:
(此处省略大量输出信息,详细内容可通过man命令查询相关函数的手册)
这些输出信息即为Linux执行程序的过程。每个函数都可以通过man命令查询其手册。其中几个主要的过程包括:
加载库到内存,执行程序,最后调用系统调用exit结束程序。
现在,我们再来看看静态链接的程序static.out,同样使用strace命令查看:
(此处省略输出信息,详细内容请参考man手册)
因为链接时,编译器直接将静态库作为程序的一部分,所以相比于动态链接的程序,这里少了很多将库映射到内存的操作。
至此,动态链接和静态链接程序执行时的不同之处已经清晰明了。
欢迎在评论区一起讨论,提出质疑。我的文章均为原创,每日浅显易懂地介绍C语言、Linux等嵌入式开发知识。喜欢我的文章,请关注我,以便获取最新更新和过往文章。