【Linux】详解动态库链接和加载&&对可执行程序底层的理解

这篇具有很好参考价值的文章主要介绍了【Linux】详解动态库链接和加载&&对可执行程序底层的理解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、动静态库链接的几种情况 

  1. 如果我们同时提供动态库和静态库,gcc默认使用的是动态库。如果我们非要使用静态库,要加-static选项。
  2. 如果我们只提供静态库,那可执行程序没办法,只能对该库进行静态链接,但程序不一定整体式静态链接的。
  3. 如果我们只提供了动态库而我们要进行静态链接会发生链接错误,程序此时默认只能进行动态链接。

二、理解动态库加载

         我们的动态库默认就是一个磁盘级别的文件。当我们的程序开始运行时,当程序运行到需要用到库中的实现方法时,库的代码和数据就会被加载到物理内存当中。库的实现方法一定是要跟程序运行起来所形成的进程产生关联的,动态库加载后,会被映射到该进程的地址空间中,准确来说,是先在页表中填写好对应虚拟地址和物理地址之间的映射关系,才被映射到进程地址空间中的共享区中

        如果此时另一个进程也要加载该动态库,只需要填写它的页表的映射关系即可,不需要再从磁盘中加载一份动态库代码和数据,如果所需库不在内存中才需要加载。这样就保证了一个动态库最多只在内存中存在一份,大大节省了内存开销。这里的本质就是说其实所有系统进程中公共的代码和数据,只需要存在一份

【Linux】详解动态库链接和加载&&对可执行程序底层的理解,后端,服务器,linux

三、可执行程序的理解

3.1、可执行程序中区域的划分

        可执行程序本身是有自己的格式信息的。我们的可执行程序在被加载到内存中之前,程序当中本身就有地址,可执行程序的每一行都是被编址的。我们的可执行程序在没有加载之前,也已经基本被按照类别(比如权限,访问属性等),已经将可执行程序划分成了各个区域。

【Linux】详解动态库链接和加载&&对可执行程序底层的理解,后端,服务器,linux

text (或 code):

  • 这部分包含了程序的机器代码,即CPU执行的指令。
  • 通常,text (或 code)的大小表示了程序中的指令数量。

data:

  • 这部分包含了程序中已经初始化的全局变量和静态变量的值。
  • data段的大小表示了程序中已初始化数据的大小。

bss:

  • 这部分用于存储未初始化的全局变量和静态变量。
  • 与 data不同,bss段在程序加载到内存时并不包含实际的数据值,而是只预留了足够的空间。这些变量的初始值通常是0。

dec (decimal):

  • 这通常表示某个段或整个程序大小的十进制表示。
  • 当你看到dec 值时,它可能是text、data、bss或整个程序大小的十进制表示。

hex (hexadecimal):

  • 这表示某个段或整个程序大小的十六进制表示。
  • 与 dec类似,hex值可能是 text、data、bss或整个程序大小的十六进制表示。

        可执行程序中除了上述说到的信息外,可执行程序的头部信息(表头)包含了关于程序执行所必需的一系列元数据和结构信息, 头部信息中就保存了main函数的起始地址,所以我们的可执行程序本身就知道要从哪里开始执行。

3.2、可执行程序的编址

        首先在这里需要跟大家明确一个概念,我们进程地址空间中的很多地址数据,都是从可执行程序中来的。将我们可执行程序中的每一行都以绝对编址的方式进行编址,每一行就对应一个地址,这就相当于我们进程地址空间中的虚拟地址。也就是说,虚拟地址需要我们的操作系统、编译器和计算机体系结构共同配合才能形成。当我们的静态库被我们的可执行程序加载时,静态库的代码就要被写到我们可执行程序text部分,静态库代码在text部分的绝对编址是确定的,当然静态库数据的编址也是确定的。

3.3、理解动态库动态链接和加载

        在进程在被创建的时候是要先创建PCB,初始化它对应的进程地址空间,然后再将磁盘中的数据加载到内存的。为了初始化进程地址空间,操作系统读取可执行程序的表头。在磁盘中存放着的可执行程序的表头中就包含了关于程序执行所必需的一系列元数据和结构信息,操作系统通过读取表头中的信息初始化对应地址空间中的正文代码,已初始化数据和未初始化数据,所以我们也就能理解了为什么不同可执行程序加载完进程地址空间中有数据的地址范围不一样了。

        当可执行程序的代码和数据加载到内存中时,因为可执行程序的每一行对应一个虚拟地址,加载到内存中又有了一个实际的物理地址,拿着物理地址和虚拟地址操作系统就可以填写页表对应的映射关系了。当这个进程要被CPU调度执行时,CPU的pc指针就保存了main函数的入口地址(pc指针内保存的是虚拟地址),CPU内部可以帮我们读取页表的内容将虚拟地址转换为物理地址,CPU去到相应的物理地址取到指令放到CPU内部的指令寄存器中,通过解析指令完成工作或是指明下一个虚拟地址,再让CPU解析虚拟地址找到物理地址中的内容,这样周而复始,我们的程序就跑起来了。

【Linux】详解动态库链接和加载&&对可执行程序底层的理解,后端,服务器,linux

        现在假设我们的可执行程序调用了某一个动态库,在我们程序的就会有这个动态库的调用信息(比如说_start(这里的_start可以看成库名,最后会被转换成库在共享区中的地址)+0x10,print,就是指我们的可执行程序调用了动态库中相对动态库首地址偏移量为0x10处的print函数),可执行程序的表头会记录调用了这个动态库。 我们调用的动态库也是要被加载到内存中的,并被映射到进程地址空间的共享区中。当我们的程序执行到动态库调用处,就会根据动态库首地址加偏移量找到页表中在内存中的物理地址,进而就能调用动态库中的方法了。所以库中代码和数据的访问,都是可以通过库在地址空间上的起始地址加上我们程序内部的偏移量就可以访问

【Linux】详解动态库链接和加载&&对可执行程序底层的理解,后端,服务器,linux文章来源地址https://www.toymoban.com/news/detail-851588.html

到了这里,关于【Linux】详解动态库链接和加载&&对可执行程序底层的理解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 动态链接库dll详解

        DLL就是整个Windows操作系统的基础。动态链接库不能直接运行,也不能接收消息他们是一些独立的文件。     Windows API中的所有函数都包含在DLL中。     其中有三个最重要的DLL     kernel32.dll ,它包含用于管理内存、线程和进程的各个函数;     User32.dll ,它包含用于执行

    2024年02月06日
    浏览(38)
  • 嵌入式IDE(2):KEIL中SCF分散加载链接文件详解和实例分析

    在上一篇文章IAR中ICF链接文件详解和实例分析中,我通过I.MX RT1170的SDK中的内存映射关系,分析了IAR中的ICF链接文件的语法。对于MCU编程所使用的IDE来说,IAR和Keil用得比较多,所以这一篇文章就来分析一下Keil的分散文件 .scf ( scatter file )。 和上一篇文章一样,同样使用I.MX R

    2024年02月09日
    浏览(47)
  • 在程序中链接静态库 和 动态库

    mkdir shareLib mkdir staticLib 把这篇文章  生成的libcalc.so放入shareLib、libcalc.a放入staticLib 一、在程序中链接静态库  CMakeLists.txt CMakeLists.txt   (也可以写成这样)  二、在程序中链接动态库 CMakeLists.txt CMakeLists.txt   (也可以写成这样)  知识点:

    2024年01月17日
    浏览(47)
  • linux 动态链接库(.so)的生成和引用

    一.简介 动态链接库:在Linux系统中,动态链接库(Dynamic Linking Library)是一种在运行时链接的共享库。相比于静态链接库,动态链接库可以在程序运行时加载,而不需要在编译时链接到程序中,这样可以减小可执行程序的大小,也方便了库的管理和更新。 动态链接库有两个主

    2024年02月14日
    浏览(41)
  • linux下g++链接动态库和静态库

    头文件的作用: include的作用就是复制内容到当前文件 井号开头的就是预处理指令,由预处理器处理,预处理阶段不关心代码,只处理预处理指令。 头文件主要 一是为了解决代码都写在一个文件太大了,二是把变量,结构体,函数声明这些固定的放在一起 函数只要声明了,

    2024年02月09日
    浏览(47)
  • C# Assembly 反射动态加载程序集(动态加载Dll)Demo

    No1、本Demo 定义了一个接口IserviceToolFrame,接口中有一个方法Run。 No2、在另外两个工程中,分别定义两个类serviceToolCatComplete、serviceToolDogComplete实现接口IserviceToolFrame。 No3、控制台程序通过动态加载Dll的方式去调用IserviceToolFrame的实例,输出不同的内容。代码如下: 动态加载

    2024年02月15日
    浏览(53)
  • Linux下Centos7 gcc/g++、动态库/静态库(动态/静态链接)

    gcc是对c语言代码进行编译链接,而g++是对c++代码进行编译链接,接下来我们只对gcc进行讲解,g++的使用方法跟gcc是一样的。 编译链接的四个步骤: 1:预处理 2:编译 3:汇编 4:链接 注:这些在后面都会着重讲解 我们先在Date.c 源文件里面写一些c语言代码,我们知道,c语言代码需

    2024年02月05日
    浏览(46)
  • .net Assembly.Load重复加载程序集造成执行异常

    最近ET做热更重载dll的时候,返回登陆会重新检测新的dll,首次登录之前已经Assembly.Load()过一次dll,第二次返回登陆再次load dll到内存中,Invoke执行方法的时候,异常了,有些方法执行了,有些未执行,于是查资料,看到些老资料说Assembly.Load重复加载同名dll不会有问题,而却现

    2024年02月07日
    浏览(59)
  • 【看表情包学Linux】软硬链接 | 软连接数 | 创建软硬链接 | 动静态库 | 生成静态库 | 生成动态库

       🤣  爆笑 教程  👉 《看表情包学Linux》👈   猛戳订阅     🔥 💭 写在前面: 上一章我们讲解了 inode,为文件系统收了尾,这几章我们充分地讲解完了文件系统的知识点,现在我们开始开始学习软硬链接了。如果没有文件系统的铺垫,想直接理解软硬链接难免有些困

    2024年02月14日
    浏览(43)
  • 程序员自我修养阅读笔记——Widnows下的动态链接

      Linux下的共享库为so文件为ELF格式,Windows下的共享库为dll文件PE格式。   windows下采用dll共享对象让程序更加模块化方便升级,大多数情况为 .dll 文件,也可以是``.ocx,.CPL```文件。   早期的windows中的进程并没有独立的地址空间,32bit的windows开始进程才有独立的地址空间

    2024年02月04日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包