当前位置: 首页 > 科技观察

如何在Linux上动态链接模块库_1

时间:2023-03-16 17:58:34 科技观察

当用C编程语言编写应用程序时,您的代码通常有多个代码源文件。最终,这些文件必须编译成单个可执行文件。您可以通过创建静态或动态库(后者也称为共享库)来做到这一点。这两种类型的库在创建和链接方式上有所不同。两者都有缺点和优点,具体取决于您的用例。动态链接是最常用的方法,尤其是在Linux系统上。动态链接使库保持模块化,因此许多应用程序可以共享一个库。应用程序的模块化还允许单独更新它所依赖的共享库。在本文中,我将演示动态链接的工作原理。在后面的文章中,我将演示静态链接。链接器链接器是一个命令,它将程序的几个部分组合起来,并为它们重新组织内存分配。链接器的作用包括:整合一个程序的所有部分,计算出一个新的内存组织结构,使所有部分结合起来,还原内存地址,使程序可以在新的内存组织结构下运行这些功能创建了一个程序,称为可执行文件可以运行。在您可以创建动态链接的可执行文件之前,您需要一些要链接的库和要编译的应用程序。准备好你最喜欢的文本编辑器并继续。创建目标文件首先,使用以下函数签名创建头文件mymath.h:intadd(inta,intb);intsub(inta,intb);intmult(inta,intb);intdivi(inta,intb);使用这些函数定义创建add.c,sub.c,mult.c和divi.c文件。我打算将所有代码放在一个代码块中,请将其分成四个文件,如注释所示://add.cintadd(inta,intb){return(a+b);}//sub.cintsub(inta,intb){return(a-b);}//mult.cintmult(inta,intb){return(a*b);}//divi.cintdivi(inta,intb){return(a/b);}现在,使用GCC创建目标文件add.o,sub.o,mult.o和divi.o:(LCTT校对笔记:关于“目标文件”,有时也叫“objectfile”,这方面翻译有些混乱,这里叫“objectfile”比较通俗,本文用的。)$gcc-cadd.csub.cmult.cdivi.c-c选项跳过链接步骤,只创建目标文件。创建一个共享对象文件,该文件将在最终可执行文件的执行期间链接动态库。仅将动态库的名称放入最终的可执行文件中。实际的链接过程发生在运行时,在此期间可执行文件和库都被放入主内存。除了可共享之外,动态库的另一个优点是它减少了最终可执行文件的大小。构建应用程序的最终可执行文件时,它使用的库仅包括库的名称,而不是库的冗余副本。您可以从现有示例代码创建动态库:$gcc-Wall-fPIC-cadd.csub.cmult.cdivi.c选项-fPIC告诉GCC生成与位置无关的代码position-independentcode(PIC).-Wall选项不是必需的,它与代码的编译方式无关。但是,它是一个有价值的选项,因为它启用了编译器警告,这在故障排除时很有用。使用GCC,创建共享库libmymath.so:$gcc-shared-olibmymath.soadd.osub.omult.odivi.o现在,您已经创建了一个简单的示例数学库libmymath.so,您可以在C代码中使用它。当然,也有非常复杂的C库,这是他们开发人员生产最终产品的过程,你我可以在C代码中安装和使用。接下来,您可以在一些自定义代码中使用您的新数学库,然后链接到它。创建动态链接的可执行文件假定您已经编写了数学运算命令。创建一个名为mathDemo.c的文件并将这些代码复制粘贴到其中:ncludeintmain(){intx,y;printf("请输入两个数\n");scanf("%d%d",&x,&y);printf("\n%d+%d=%d",x,y,添加(x,y));printf("\n%d-%d=%d",x,y,sub(x,y));printf("\n%d*%d=%d",x,y,mult(x,y));if(y==0){printf("\n分母为零所以不能进行除法\n");退出(0);}else{printf("\n%d/%d=%d\n",x,y,divi(x,y));返回0;注意:第一行是include语句,按名称引用您自己的libmymath库。要使用共享库,您必须安装它,如果您没有要使用的库,当您的可执行文件运行并搜索它包含的库??时,它不会找到共享库。如果您需要在不将库安装到已知目录的情况下编译代码,可以使用以下一些方法来覆盖默认值。但是对于一般用途,我们希望库位于已知位置,所以这就是我在这里演示的内容。将文件libmymath.so复制到标准系统目录,例如/usr/lib64,然后运行??ldconfig。ldconfig命令创建所需的链接并缓存在标准库目录中找到的最新共享库。$sudocplibmymath.so/usr/lib64/$sudoldconfigcompileapplication从您的应用程序源代码(mathDemo.c)创建一个名为mathDemo.o的目标文件:$gcc-I。-cmathDemo.c-I选项告诉GCC在它后面列出的目录中搜索头文件(在本例中为mymath.h)。在此示例中,您指定当前目录,用单个点(.)表示。创建一个可执行文件并使用-l选项按名称引用您的共享数学库:$gcc-omathDynamicmathDemo.o-lmymathGCC将找到libmymath.so,因为它存在于默认系统库目录中。使用ldd验证使用的共享库:$lddmathDemolinux-vdso.so.1(0x00007fffe6a30000)libmymath.so=>/usr/lib64/libmymath.so(0x00007fe4d4d33000)libc.so.6=>/lib64/libc.so.6(0x00007fe4d4b29000)/lib64/ld-linux-x86-64.so.2(0x00007fe4d4d4e000)查看mathDemo可执行文件的大小:$du./mathDynamic24./mathDynamic当然是个小应用,它占用的磁盘空间量反映了这一点。相比之下,相同代码的静态链接版本(您将在后面的文章中看到)是932K!$./mathDynamic输入两个数25525+5=3025-5=2025*5=12525/5=5可以使用file命令验证是否动态链接:$file./mathDynamic./mathDynamic:ELF64位LSB可执行文件,x86-64,动态链接,解释器/lib64/ld-linux-x86-64.so.2,带有debug_info,未剥离成功!动态链接因为链接发生在运行时,所以使用共享库会生成轻量级可执行文件。因为它在运行时解析引用,所以需要更多的执行时间。然而,由于绝大多数命令在日常Linux系统和现代硬件上都是动态链接的,因此节省的时间可以忽略不计。其固有的模块化对于开发人员和用户来说都是一项强大的功能。在本文中,我描述了如何创建动态库并将其链接到最终的可执行文件中。在我的下一篇文章中,我将使用相同的源文件代码来创建一个静态链接的可执行文件。