我们分享的关于图书馆的基本信息 以前的职位 .在本文中,我们将学习如何在Linux上创建共享库。
在此之前,我们需要了解如何将程序加载到内存中,以及该过程中涉及的各种(基本)步骤。
让我们看看C语言中典型的“Hello World”程序。下面给出了简单的Hello World程序屏幕图像。
我们正在使用命令“编译代码” gcc-o示例共享。C “当我们编译代码时,编译器不会解析函数的实现 printf() .它只验证语法检查。工具链在我们的应用程序中留下一个存根,由动态链接器填充。由于printf是标准函数,编译器会隐式调用其共享库。下面是更多细节。
我们正在使用 ldd 列出程序二进制映像的依赖项。在屏幕图像中,我们可以看到我们的示例程序依赖于三个二进制文件:, linux vdso。所以1. , libc。所以6. 和 /lib64/ld-linux-x86-64。所以2. .
VDSO文件是系统调用接口和其他一些东西的快速实现,这不是我们的重点(在一些较旧的系统上,您可能会在*.vsdo.*的liue中看到不同的文件名)。忽略此文件。我们对另外两份文件感兴趣。
档案 libc。所以6. 是C语言实现的各种标准函数。这就是我们看到的文件 printf 我们需要的定义 你好,世界 它是运行Hello World程序需要加载到内存中的共享库。
第三个文件是/lib64/ld-linux-x86-64。所以2实际上是在调用应用程序时运行的可执行文件。当我们在bash终端上调用程序时,通常bash会自行分叉,并用要运行的程序的映像(所谓的fork-exec对)替换其地址空间。内核验证libc是否正确。所以。6存在于记忆中。如果没有,它将把文件加载到内存中,并重新定位libc。所以6个符号。然后,它调用动态链接器(/lib64/ld-linux-x86-64.so.2)来解析应用程序代码的未解析符号(本例中为printf)。然后控制权转移到我们的程序 主要的 (我在这个过程中故意省略了很多细节,我们的重点是理解基本细节)。
创建我们自己的共享库:
让我们在Linux上使用简单的共享库。创建一个文件 图书馆C 包含以下内容。
文件库。c定义了一个函数 符号 我们的应用程序代码将使用它。编译文件库。c文件使用以下命令。
gcc-shared-fPIC-o libliblibrary。图书馆也是如此。C
旗帜 -分享 指示编译器我们正在构建一个共享库。旗帜 -fPIC 是生成独立于位置的代码(暂时忽略)。该命令生成一个共享库 图书馆。所以 在当前工作目录中。我们已经准备好使用我们的共享对象文件(Linux中的共享库名称)。
创建另一个文件 应用C 包含以下内容。
在文件中 应用C 我们正在调用共享库中定义的函数signum。编译应用程序。c文件使用以下命令。
gcc应用程序。c-L/home/geetanjali/coding/-library-o示例
旗帜 -图书馆 指示编译器查找当前代码中不可用的符号定义(本例中为signum函数)。选择 -L 提示编译器在目录中查找任何共享库(仅在链接时间内)。该命令生成名为“的可执行文件” 样品 “.
如果调用可执行文件,动态链接器将无法找到所需的共享库。默认情况下,它不会查看当前工作目录。必须明确指示工具链提供正确的路径。动态链接器搜索LD_LIBRARY_PATH中可用的标准路径,并在系统缓存中搜索(有关详细信息,请浏览该命令) ldconfig ).我们必须将工作目录添加到LD_LIBRARY_PATH环境变量中。下面的命令也执行相同的操作。
导出LD_LIBRARY_PATH=/home/geetanjali/coding/:$LD_LIBRARY_PATH
现在可以调用我们的可执行文件,如图所示。
/样品
我的系统上的输出示例如下所示。
注: 道路 /home/geetanjali/编码/ 正在我的机器上运行目录路径。在上述命令中使用工作目录路径的任何地方,都需要使用它。
请继续关注,我们甚至还没有探索三分之一的共享库概念。更高级的概念将在后面的文章中介绍。
练习:
它就像一篇文章。除非你练习和做一些研究,否则你不会得到很多。
1.创建类似的示例,并在共享库中编写您的函数。在另一个应用程序中调用该函数。
2.是否有其他工具可以列出依赖库?
3.什么是位置独立代码(PIC)?
4.在当前上下文中,什么是系统缓存?目录/etc/ld是如何运行的。所以conf.d/*是否与当前上下文相关?
— 文基 。如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请发表评论。