用到动态库的程序运行过程

当我们写好了一段代码然后编译运行后会生成可执行文件,该文件会存在磁盘的当前目录下,而当我们开始运行这段程序时,操作系统(加载器)需要将其从磁盘加载进内存然后执行相关操作,而对于用到动态库的程序,同时也会将动态库加载进内存中。
以下的讲解以Linux操作系统为例。
进程地址空间
在此之前首先我们来认识一下进程地址空间:
首先我们要知道进程地址空间是每一个进程独有的一份虚拟地址空间,并不是物理上的地址空间,地址空间存在的意义就是更好的划分和管理进程数据, 而实际上是采用页表来与物理地址构建联系的。而当CPU处理虚拟地址中的数据时,操作系统的MMU(内存管理单元)主要负责虚拟地址和物理地址之间的转换。

代码段
我们程序其实就是从main函数开始的一个个函数集合。而这一个个函数(不包括变量)其实本质上就是一系列的指令组合,所以函数指令其实就是存储在代码段。而这函数指令是不可修改的,也就是只读权限。
数据段
数据段包括已初始化数据段和未初始化数据段。而初始化数据段又包括全局变量和静态变量,而未初始化数据段也就是未初始化的全局变量和静态变量。其实数据段也叫做全局区和静态区。
堆区(向上增长)
堆区主要负责动态内存分配,如我们C语言的malloc函数和C++的new运算符,都是常见的用来申请堆区空间的,而堆空间要记得使用过后释放,否则会造成内存泄漏的风险,最终导致程序内存不足而卡死。
共享区
共享区属于内存映射段的一种,而内存映射段主要是用于将磁盘文件内容映射到虚拟内存中的,这其中就设计到页表和缺页中断。而我们所说的共享区是主要用来进行共享库加载和进程间通信使用的。其实共享就是多个进程共享的数据,其实就是在内存中其实只有一份,但每个进程的虚拟地址空间都会映射一份。
栈区(向下增长)
栈区用于存储局部变量,函数参数以及函数调用的返回地址信息。而我们每当调用一个函数时,其所用到的这些数据都会存在栈区,而其他的函数指令就存在代码段。
命令行参数和环境变量
- 命令行参数其实就是我们main函数原型的参数:
int main(int argc,const char* agrv[])而我们在运行可执行程序时附带的参数其实都会当作调用main函数的参数传递过去,而argc就是参数数量,argv就是参数内容。如:ls -a -l其实就是就是-a和-l就是参数,而argv[0]就是ls,也就是程序名。
- 环境变量存储量了用户定义的全局设置信息,如:PATH环境变量就定义了系统训中可执行文件的目录,如ls指令其实就是一个可执行程序,而我们自己写的可执行程序需要加上./才可以运行。而ls不需要的原因就是ls程序的所在路径已经设置进了PATH环境变量内部。
内核区
内核区是供给操作系统使用的区域,其中存放的是内核的代码和数据,如系统调用函数和内核全局变量等信息。而且内核区还负责管理进程的PCB。
而内核区的存在就保证了内核不受用户的干扰,也就是当我们调用内核数据时需要访问内核区,然后调用内核区的调用接口从而进行内核数据的访问与接收等。而且每个进程虚拟地址空间的内核区都是独立的(物理上共一份),所以程序间不会进行互相干扰。
程序运行时操作系统的工作
就绪工作
创建进程
操作系统内核会在内存管理中划分专门的区域为该程序创建一个进程PCB,从而对该进程进行管理。而PCB中的部分信息会被直接初始化,如:进程pid、进程状态(就绪态)、进程默认优先级、程序计数器(记录程序的入口地址)。并且会为进程分配一个独立的虚拟地址空间。
资源分配
初始的内存大小分配、CPU调度时间分配(具体时间取决于后期CPU调度时会根据调度算法进行时间分配)。
程序加载
就绪工作做完以后,加载器就会将程序从磁盘加载进内存,也就是创建地址空间。实际上就是通过解析磁盘文件的ELF格式来确定程序的入口和代码段数据段的位置,如果程序链接了动态库的话还会记录所用到的动态库函数在内存中的加载位置。然后开始按照程序文件信息,将程序的代码段、数据段分别加载到分配好的内存区域中。对于共享数据部分会先进行检查内存中是否已经存在,如果存在的话后续就直接页表映射,不存在的话就加载进内存中。
建立程序执行环境
也就是将PCB中的字段进行赋值的过程。将程序计数器设置为程序的入口地址。初始化栈指针ESP寄存器,为栈空间分配初始地址(寄存器中存的都是虚拟地址)。同时还会进行其他的寄存器数据的初始化。
页表操作
页表就是建立虚拟内存和物理内存的映射关系,新加载进内存的数据直接在页表中构建映射关系。对于映射关系中的物理地址如果不存在时则会发生缺页中断,根据页面信息在磁盘的位置进而找到对应页面,将其读进物理内存中,同时进行页表的更新。
我们的程序在编译链接形成可执行程序时,此时还没有进行运行,也就没有加载进内存,但是其内部代码数据就已经采用虚拟地址进行编址好了,也称作逻辑地址。当加载进内存以后,其内部代码数据就都会有对应的一个物理地址。所以此时页表也就构建出K-V结构的映射关系。但是页表并不是一次性完成所有页面的映射,对于动态分配的数据和还未访问的数据部分,其页表项并未填充。
调度执行
操作系统在就绪队列中根据调度算法选择一个进程进行执行,此时程序才正式开始运行。
动静态库对比
- 静态库在编译链接的过程中就直接将程序代码中所用到的静态库方法直接拷贝进可执行程序里。然后在运行的时候就将含有静态库方法的可执行程序一起加载进内存中。所以我们多个程序运行都用到了同一个静态库的话,那么内存中就会存在多份,此时对于内存空间就是一种极大的浪费。
- 动态库则是在程序运行的过程中被加载进物理空间中,而动态库中的方法被调用时才会将动态库加载进共享区。动态库在物理内存中只会存在一份,而每个使用了动态库的进程会在个地址空间的共享区中通过页表直接和物理内存中的动态库构建映射关系。动态库的共享区从而就节省了内存空间。
首先我们知道当形成动态库时,编译和静态库一样,需要包含库文件的路径与库名称,但是在运行时,静态库可以直接进行运行,而动态库运行时需要和库文件在同一目录下或者建立软链接,或者将库文件拷贝到lib64目录下,这样在运行时就会默认去该库下寻找所需库文件,或者直接去/exc/ld.so.conf.d目录下更改动态库配置文件,也就是创建一个文件,同时将我们库的绝对路径写进文件中。因为动态库并没有将库中的数据拷贝进代码中,所以在运行时需要寻找动态库的所在位置,然后才可以调用动态库中的方法。而且动态库形成过程时,生成.o文件时需要带上-fPIC(与位置无关码)。
地址空间中的函数调用
函数调用
在程序进行编译时,会通过程序入口地址确定函数的偏移地址。在链接阶段这些相对地址会在虚拟地址空间中转换成绝对地址。后续在虚拟地址的代码段中进行函数调用时直接通过存放下一条指令地址的寄存器找到函数入口地址直接进行调用函数。
动态库函数调用
动态库由于是在程序运行时才加载进虚拟地址空间的共享区,但是动态库在虚拟地址空间的加载位置是不确定的,所以说,动态库中的函数地址也是不确定的。而想要通过虚拟地址调用对应的动态库函数就与动态库生成与位置无关码有关联。
需要用到动态库的程序被编译生成可执行程序时,其会保存所用动态库函数的一个相对偏移量。也就是所调用的动态库函数相对于动态库的起始未知的偏移量。而当程序运行时,动态库的信息和程序用到动态库函数的偏移量关系也会加载进内存中。而且当程序的代码段中使用到了对应动态库中的函数方法时,动态链接器才开始将动态库加载进虚拟内存的共享区中的某个位置,从而就确定好了库的起始地址,那么通过偏移量就可以将库函数映射到共享区中的具体位置(那么说也就确定了绝对地址)。那么当程序调用动态库函数时,通过动态库起始地址+偏移量的方式进行调用对应动态库函数。
相关文章:
用到动态库的程序运行过程
当我们写好了一段代码然后编译运行后会生成可执行文件,该文件会存在磁盘的当前目录下,而当我们开始运行这段程序时,操作系统(加载器)需要将其从磁盘加载进内存然后执行相关操作,而对于用到动态库的程序&…...
类型转换与IO流:C++世界的变形与交互之道
文章目录 前言🎄一、类型转换🎈1.1 隐式类型转换🎈1.2 显式类型转换🎁1. C 风格强制类型转换🎁2. C 类型转换操作符 🎈1.3 C 类型转换操作符详解🎁1. static_cast🎁2. dynamic_cast&…...
Pytorch使用手册- TorchVision目标检测微调Tutorial的使用指南(专题十二)
这篇教程的目标是对一个预训练的 Mask R-CNN 模型进行微调,应用于 Penn-Fudan 行人检测与分割数据集。该数据集包含 170 张图像,里面有 345 个行人实例,我们将通过这个教程来演示如何使用 torchvision 中的新特性,训练一个面向自定义数据集的目标检测和实例分割模型。 注意…...
人工智能机器学习算法分类全解析
目录 一、引言 二、机器学习算法分类概述 (一)基于学习方式的分类 1. 监督学习(Supervised Learning) 2. 无监督学习(Unsupervised Learning) 3. 强化学习(Reinforcement Learning…...
Linux 35.6 + JetPack v5.1.4@DeepStream安装
Linux 35.6 JetPack v5.1.4DeepStream安装 1. 源由2. 步骤Step 1 安装Jetpack 5.1.4 L4T 35.6Step 2 安装依赖组件Step 3 安装librdkafkaStep 4 安装 DeepStream SDKStep 5 测试 deepstream-appStep 6 运行 deepstream-app 3. 总结3.1 版本问题3.2 二进制help 4. 参考资料 1. …...
图数据库 | 11、图数据库架构设计——高性能图存储架构(下)
在上篇内容中,老夫着重讲了高性能图存储系统的特点,咱们继续往下讲重点——高性能存储架构的设计思路!! 2.高性能存储架构设计思路 首先呢,存储架构以及核心数据结构的设计思路通常围绕如下4个维度来进行:…...
【HTTP】HTTP协议
一个Web Server就是个服务器软件(程序),或者是运行这个服务器软件的硬件(计算机),其主要功能是通过HTTP协议与客户端进行通信,来接收,存储,处理来自客户端的HTTP请求&…...
大数据新视界 -- Hive 基于 MapReduce 的执行原理(上)(23 / 30)
💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…...
SpringBoot源码解析(六):打印Banner
SpringBoot源码系列文章 SpringBoot源码解析(一):SpringApplication构造方法 SpringBoot源码解析(二):引导上下文DefaultBootstrapContext SpringBoot源码解析(三):启动开始阶段 SpringBoot源码解析(四):解析应用参数args Sp…...
【计算机网络】实验6:IPV4地址的构造超网及IP数据报
实验 6:IPV4地址的构造超网及IP数据报 一、 实验目的 加深对IPV4地址的构造超网(无分类编制)的了解。 加深对IP数据包的发送和转发流程的了解。 二、 实验环境 • Cisco Packet Tracer 模拟器 三、 实验内容 1、了解IPV4地址的构造超网…...
easy excel 生成excel 文件
导包 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.3</version> </dependency> 内容 List<类> limspjreport 值; String fileName sdf.format(new Date()) "-…...
Ajax:回忆与节点
一点回忆 面对我的Ajax学习,实现前后端交互,最开始我采用的使用网络寻找intellij IDEA Ultimate破解方法,然后最终成功,然后按照相关教程配置java ee项目,然后中间又去配置了Tomcat服务器,然后又去学习了一…...
Python+OpenCV系列:Python和OpenCV的结合和发展
PythonOpenCV系列:Python和OpenCV的结合和发展 **引言****Python语言的发展****1.1 Python的诞生与发展****1.2 Python的核心特性与优势****1.3 Python的应用领域** **OpenCV的发展****2.1 OpenCV的起源与发展****2.2 OpenCV的功能特性****2.3 OpenCV的应用场景** *…...
Ubuntu20.04 由源码编译安装opencv3.2 OpenCV
Ubuntu20.04 由源码编译安装opencv3.2.0 获取 opencv 及opencv_contrib源代码 创建目录以存放opencv及opencv_contrib源代码 mkdir ~/opencv3.2.0 cd ~/opencv3.2.0获取opencv源代码并切换到对应tag git clone https://github.com/opencv/opencv.git cd opencv git checkou…...
A058-基于Spring Boot的餐饮管理系统的设计与实现
🙊作者简介:在校研究生,拥有计算机专业的研究生开发团队,分享技术代码帮助学生学习,独立完成自己的网站项目。 代码可以查看项目链接获取⬇️,记得注明来意哦~🌹 赠送计算机毕业设计600个选题ex…...
RDIFramework.NET CS敏捷开发框架 SOA服务三种访问(直连、WCF、WebAPI)方式
1、介绍 在软件开发领域,尤其是企业级应用开发中,灵活性、开放性、可扩展性往往是项目成功的关键因素。对于C/S项目,如何高效地与后端数据库进行交互,以及如何提供多样化的服务访问方式,是开发者需要深入考虑的问题。…...
Linux——命名管道及日志
linux——进程间通信及管道的应用场景-CSDN博客 文章目录 目录 文章目录 前言 一、命名管道是什么? 理解: 2、编写代码 makefile 管道封装成类,想用中管道时只需要调用实例化 读端 写端 日志 1、日志是什么? 2、日志有什么&#x…...
Flink 常见面试题
1、Flink 的四大特征(基石) checkpoin基于Chandy-Lamport算法实现了分布式一致性快照提供了一致性的语义 state丰富的StateAPI time实现了Watermark机制,乱序数据处理,迟到数据容忍 window开箱即用的滚动,滑动会话窗口…...
rtc-pcf8563 0-0051: low voltage detected, date/time is not reliable
解决方法: 1、先测量pcf8563电源电压,是否满足要求。 2、pcf8563首次操作。第一次读取pcf8563的时间,未初始化,非法,芯片门槛电压检测配置不合理。使用hwclock命令写入一次,即可解决。 hwclock -f /dev/…...
(简单5步实现)部署本地AI大语言模型聊天系统:Chatbox AI + grok2.0大模型
摘要: 本文将指导您如何部署一个本地AI大语言模型聊天系统,使用Chatbox AI客户端应用和grok-beta大模型,以实现高效、智能的聊天体验。 引言: 由马斯克X-AI发布的Grok 2大模型以其卓越的性能超越了GPT4.0。Grok模型支持超长文本…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
