|
西虹网
西虹网 原标题:Linux 上静态链接库工作原理 | Linux 中国红帽认证一直是行业的佼佼者,在业内好评如潮,备受大众所青睐。 西虹网
西虹网 西虹网
西虹网 西虹网
西虹网 导读:学习如何用静态链接库将多个 C 目标文件结合到一个单个的可执行文件之中。 西虹网
西虹网 西虹网
西虹网 本文字数:4023,阅读时长大约: 5分钟 西虹网
西虹网 西虹网
西虹网 学习如何用静态链接库将多个 C 目标文件结合到一个单个的可执行文件之中。 西虹网
西虹网 西虹网
西虹网 使用 C 编写的应用程序时,通常有多个源码文件,但最终你需要编译成单个的可执行文件。 西虹网
西虹网 西虹网
西虹网 你可以通过两种方式来完成这项工作:通过创建一个 静态 (static) 库 或 一个 动态 (dynamic) 库(也被称为 共享 (shared) 库)。从创建和链接的方式来看,它们是两种不同类型的库。选择使用哪种方式取决于你的的具体场景。 西虹网
西虹网 西虹网
西虹网 在 上一篇文章 linux.cn 中,我演示了如何创建一个动态链接的可执行文件,这是一种更通用的方法。在这篇文章中,我将说明如何创建一个静态链接的可执行文件。 西虹网
西虹网 西虹网
西虹网 使用静态库链接器 西虹网
西虹网 西虹网
西虹网 链接器 (linker) 是一个命令,它将一个程序的多个部分结合在一起,并为它们重新组织内存分配。 西虹网
西虹网 西虹网
西虹网 链接器的功能包括: 西虹网
西虹网 西虹网
西虹网 ? 整合一个程序的所有的部分 西虹网
西虹网 西虹网
西虹网 ? 计算出一个新的内存组织结构,以便所有的部分组合在一起 西虹网
西虹网 西虹网
西虹网 ? 恢复内存地址,以便程序可以在新的内存组织结构下运行 西虹网
西虹网 西虹网
西虹网 ? 解析符号引用 西虹网
西虹网 西虹网
西虹网 链接器通过这些功能,创建了一个名称为可执行文件的一个可运行程序。 西虹网
西虹网 西虹网
西虹网 静态库是通过复制一个程序中的所有依赖库模块到最终的可执行镜像来创建的。链接器将链接静态库作为编译过程的最后一步。可执行文件是通过解析外部引用、将库例程与程序代码结合在一起来创建的。 西虹网
西虹网 西虹网
西虹网 创建目标文件 西虹网
西虹网 西虹网
西虹网 intadd(inta,intb); 西虹网
西虹网 西虹网
西虹网 intsub(inta,intb); 西虹网
西虹网 西虹网
西虹网 intmult(inta,intb); 西虹网
西虹网 西虹网
西虹网 intdivi(inta,intb); 西虹网
西虹网 西虹网
西虹网 使用这些函数定义来创建 add.c 、 sub.c 、 mult.c 和 divi.c 文件。我将把所有的代码都放置到一个代码块中,请将其分为四个文件,如注释所示: 西虹网
西虹网 西虹网
西虹网 // add.c 西虹网
西虹网 西虹网
西虹网 intadd(inta,intb){ 西虹网
西虹网 西虹网
西虹网 return(a+b); 西虹网
西虹网 西虹网
西虹网 } 西虹网
西虹网 西虹网
西虹网 //sub.c 西虹网
西虹网 西虹网
西虹网 intsub(inta,intb){ 西虹网
西虹网 西虹网
西虹网 return(a-b); 西虹网
西虹网 西虹网
西虹网 } 西虹网
西虹网 西虹网
西虹网 //mult.c 西虹网
西虹网 西虹网
西虹网 intmult(inta,intb){ 西虹网
西虹网 西虹网
西虹网 return(a*b); 西虹网
西虹网 西虹网
西虹网 } 西虹网
西虹网 西虹网
西虹网 //divi.c 西虹网
西虹网 西虹网
西虹网 intdivi(inta,intb){ 西虹网
西虹网 西虹网
西虹网 return(a/b); 西虹网
西虹网 西虹网
西虹网 } 西虹网
西虹网 西虹网
西虹网 现在,使用 GCC 来生成目标文件 add.o 、 sub.o 、 mult.o 和 divi.o : 西虹网
西虹网 西虹网
西虹网 (LCTT 校注:关于“ 目标文件 (object file) ”,有时候也被称作“对象文件”,对此,存在一些译法混乱情形,称之为“目标文件”的译法比较流行,本文采用此译法。) 西虹网
西虹网 西虹网
西虹网 $ gcc-c add.c sub.c mult.c divi.c 西虹网
西虹网 西虹网
西虹网 -c 选项跳过链接步骤,而只创建目标文件。 西虹网
西虹网 西虹网
西虹网 创建一个名称为 libmymath.a 的静态库,接下来,移除目标文件,因为它们不再被需要。(注意,使用一个 trash 命令比使用一个 rm 命令更安全。) 西虹网
西虹网 西虹网
西虹网 $ ar rs libmymath.a add.o sub.o mult.o divi.o 西虹网
西虹网 西虹网
西虹网 $ trash *.o 西虹网
西虹网 西虹网
西虹网 $ ls 西虹网
西虹网 西虹网
西虹网 add.c divi.c libmymath.a mult.c mymath.h sub.c 西虹网
西虹网 西虹网
西虹网 现在,你已经创建了一个名称为 libmymath 的简单数学示例库,你可以在 C 代码中使用它。当然,也有非常复杂的 C 库,这就是他们这些开发者来生成最终产品的工艺流程,你和我可以安装这些库并在 C 代码中使用。 西虹网
西虹网 西虹网
西虹网 接下来,在一些自定义代码中使用你的数学库,然后链接它。 西虹网
西虹网 西虹网
西虹网 创建一个静态链接的应用程序 西虹网
西虹网 西虹网
西虹网 假设你已经为数学运算编写了一个命令。创建一个名称为 mathDemo.c 的文件,并将这些代码复制粘贴至其中: 西虹网
西虹网 西虹网
西虹网 #include<mymath.h> 西虹网
西虹网 西虹网
西虹网 #include<stdio.h> 西虹网
西虹网 西虹网
西虹网 #include<stdlib.h> 西虹网
西虹网 西虹网
西虹网 intmain 西虹网
西虹网 西虹网
西虹网 { 西虹网
西虹网 西虹网
西虹网 intx,y; 西虹网
西虹网 西虹网
西虹网 printf("Enter two numbers 西虹网
西虹网 西虹网
西虹网 "); 西虹网
西虹网 西虹网
西虹网 scanf("%d%d",&x,&y); 西虹网
西虹网 西虹网
西虹网 printf(" 西虹网
西虹网 西虹网
西虹网 %d + %d=%d",x,y,add(x,y)); 西虹网
西虹网 西虹网
西虹网 printf(" 西虹网
西虹网 西虹网
西虹网 %d - %d=%d",x,y,sub(x,y)); 西虹网
西虹网 西虹网
西虹网 printf(" 西虹网
西虹网 西虹网
西虹网 %d * %d=%d",x,y,mult(x,y)); 西虹网
西虹网 西虹网
西虹网 if(y==0){ 西虹网
西虹网 西虹网
西虹网 printf(" 西虹网
西虹网 西虹网
西虹网 Denominator is zero so can't perform division 西虹网
西虹网 西虹网
西虹网 "); 西虹网
西虹网 西虹网
西虹网 exit(0); 西虹网
西虹网 西虹网
西虹网 }else{ 西虹网
西虹网 西虹网
西虹网 printf(" 西虹网
西虹网 西虹网
西虹网 %d / %d=%d 西虹网
西虹网 西虹网
西虹网 ",x,y,divi(x,y)); 西虹网
西虹网 西虹网
西虹网 return0; 西虹网
西虹网 西虹网
西虹网 } 西虹网
西虹网 西虹网
西虹网 } 西虹网
西虹网 西虹网
西虹网 注意:第一行是一个 include 语句,通过名称来引用你自己的 libmymath 库。 西虹网
西虹网 西虹网
西虹网 针对 mathDemo.c 创建一个名称为 mathDemo.o 的对象文件: 西虹网
西虹网 西虹网
西虹网 $ gcc-I .-c mathDemo.c 西虹网
西虹网 西虹网
西虹网 -I 选项告诉 GCC 搜索在其后列出的头文件。在这个实例中,你通过单个点( . )来指定当前目录。 西虹网
西虹网 西虹网
西虹网 链接 mathDemo.o 和 libmymath.a 来生成最终的可执行文件。这里有两种方法来向 GCC 告知这一点。 西虹网
西虹网 西虹网
西虹网 你可以指向文件: 西虹网
西虹网 西虹网
西虹网 $ gcc-static-o mathDemo mathDemo.o libmymath.a 西虹网
西虹网 西虹网
西虹网 或者,你可以具体指定库的路径及名称: 西虹网
西虹网 西虹网
西虹网 $ gcc-static-o mathDemo -L .mathDemo.o -lmymath 西虹网
西虹网 西虹网
西虹网 在后面的那个示例中, -lmymath 选项告诉链接器来链接对象文件 mathDemo.o 和对象文件 libmymath.a 来生成最终的可执行文件。 -L 选项指示链接器在下面的参数中查找库(类似于你使用 -I 所做的工作)。 西虹网
西虹网 西虹网
西虹网 分析结果 西虹网
西虹网 西虹网
西虹网 使用 file 命令来验证它是静态链接的: 西虹网
西虹网 西虹网
西虹网 $ filemathDemo 西虹网
西虹网 西虹网
西虹网 mathDemo:ELF 64-bit LSB executable,x86-64... 西虹网
西虹网 西虹网
西虹网 statically linked,withdebug_info,notstripped 西虹网
西虹网 西虹网
西虹网 使用 ldd 命令,你将会看到该可执行文件不是动态链接的: 西虹网
西虹网 西虹网
西虹网 $ lddhttp://news.sohu.com/a/mathDemo 西虹网
西虹网 西虹网
西虹网 nota dynamic executable 西虹网
西虹网 西虹网
西虹网 你也可以查看 mathDemo 可执行文件的大小: 西虹网
西虹网 西虹网
西虹网 $ du-h http://news.sohu.com/a/mathDemo 西虹网
西虹网 西虹网
西虹网 932Khttp://news.sohu.com/a/mathDemo 西虹网
西虹网 西虹网
西虹网 在我 前一篇文章 linux.cn 的示例中,动态链接的可执行文件只占有 24K 大小。 西虹网
西虹网 西虹网
西虹网 运行该命令来看看它的工作内容: 西虹网
西虹网 西虹网
西虹网 $ http://news.sohu.com/a/mathDemo 西虹网
西虹网 西虹网
西虹网 Entertwo numbers 西虹网
西虹网 西虹网
西虹网 10 西虹网
西虹网 西虹网
西虹网 5 西虹网
西虹网 西虹网
西虹网 10+5=15 西虹网
西虹网 西虹网
西虹网 10-5=5 西虹网
西虹网 西虹网
西虹网 10*5=50 西虹网
西虹网 西虹网
西虹网 10/5=2 西虹网
西虹网 西虹网
西虹网 看起来令人满意! 西虹网
西虹网 西虹网
西虹网 何时使用静态链接 西虹网
西虹网 西虹网
西虹网 动态链接可执行文件通常优于静态链接可执行文件,因为动态链接会保持应用程序的组件模块化。假如一个库接收到一次关键安全更新,那么它可以很容易地修补,因为它存在于应用程序的外部。 西虹网
西虹网 西虹网
西虹网 当你使用静态链接时,库的代码会“隐藏”在你创建的可执行文件之中,意味着在库每次更新时(相信我,你会有更好的东西),仅有的一种修补方法是重新编译和发布一个新的可执行文件。 西虹网
西虹网 西虹网
西虹网 不过,如果一个库的代码,要么存在于它正在使用的具有相同代码的可执行文件中,要么存在于不会接收到任何更新的专用嵌入式设备中,那么静态连接将是一种可接受的选项。 西虹网
西虹网 西虹网
西虹网 via: https://opensource.com/article/22/6/static-linking-linux 西虹网
西虹网 西虹网
西虹网 作者: Jayashree Huttanagoudar 选题: lkxed 译者: robsean 校对: turbokernel 西虹网
西虹网 西虹网
西虹网 本文由 LCTT 原创编译, Linux中国 荣誉推出 西虹网
西虹网 西虹网
西虹网 LCTT 译者 :郑 西虹网
西虹网 西虹网
西虹网 西虹网
西虹网 西虹网
西虹网 翻译: 105.0篇 西虹网
西虹网 西虹网
西虹网 | 西虹网
西虹网 西虹网
西虹网 贡献: 1315天 西虹网
西虹网 西虹网
西虹网 2018-12-03 西虹网
西虹网 西虹网
西虹网 → 西虹网
西虹网 西虹网
西虹网 2022-07-09 西虹网
西虹网 西虹网
西虹网 https://linux.cn/lctt/robsean 西虹网
西虹网 西虹网
西虹网 欢迎遵照 CC-BY-SA 协议规定转载, 西虹网
西虹网 西虹网
西虹网 如需转载,请在文章下留言 “ 转载:公众号名称”, 西虹网
西虹网 西虹网
西虹网 我们将为您添加白名单,授权“ 转载文章时可以修改”。 返回搜狐,查看更多 西虹网
西虹网 西虹网
西虹网 责任编辑: |
|