恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

【Linux指南】动静态库系列(九):动态库如何进入进程地址空间:从磁盘 .so 到共享内存映射

  • 首页
  • 资讯中心
  • /
  • 【Linux指南】动静态库系列(九):动态库如何进入进程地址空间:从磁盘 .so 到共享内存映射

相关资讯

【NLP】大模型长文本处理技术与GLM-4-Plus评测:从上下文窗口到TaoToken统一调用 2026/9/30 13:51:26
如何给DSH小鲸鱼挂件贡献代码:分支策略、Issue与PR规则的完整指南 2026/9/30 13:51:26
RAG找答案,Wiki长知识:双轨架构实现知识协同进化 2026/9/30 13:46:26

最新资讯

AI应用成本优化完全指南:Token压缩、语义缓存与模型路由的Java生产级实战
零基础学AI,为什么建议选“技术+项目管理”双轨?
104-杨逢昌解读:形式化6S的四种表征与三环体系破解框架
LangChain 单仓库开发指南:架构解析、工程规范与 CI/CD 流程
怎么做一个能查公司制度和流程的内部AI问答?
多孩家庭选车,丰田智能电混双擎的第三排空间够用吗?

今日推荐

模型优化器实战:从FP32到INT8的推理加速与精度平衡
LangGraph+FastAPI构建可审计AI编码助手
基于图像预处理与几何特征的人脸脸型发型搭配系统实现

本周热门

从像素到笔画:srt-whiteboard-animation骨架笔迹追踪实现(Zhang-Suen细化+8邻接追踪)
网站建设的英语怎么说?别只背单词,看完这套安全完整流程才敢上线
新手入门看这篇:建设网站加盟避坑指南与SEO实操

本月精选

自研推理加速器Redwood:两周内实现PyTorch模型高效部署的实战教程
V4L2摄像头采集实战:从camera_client.rar到出图全流程解析
从“谁发明了钢琴键”到知识问答智能体:RAG与记忆工程实践

【Linux指南】动静态库系列(九):动态库如何进入进程地址空间:从磁盘 .so 到共享内存映射

发布时间:2026/9/30 13:51:26
【Linux指南】动静态库系列(九):动态库如何进入进程地址空间:从磁盘 .so 到共享内存映射 文章目录一、动态库为什么比静态库更常用二、动态库也是文件三、动态库加载的整体流程四、从磁盘 .so 到物理内存五、从物理内存到进程虚拟地址空间六、多个进程如何共享同一个动态库七、共享的是代码不是什么都共享八、为什么动态库加载地址不固定九、使用 /proc 查看动态库映射十、使用 pmap 查看进程映射十一、动态链接和静态链接再对比一次十二、为什么动态库需要后续重定位十三、总结前面我们已经知道动态库.so不是在编译链接阶段完整拷贝进可执行程序而是在程序运行时被动态链接器加载。那么问题来了磁盘上的libxxx.so到底是怎么进入进程地址空间的多个程序都依赖同一个动态库时系统真的会给每个进程都复制一份库代码吗为什么说动态库可以节省内存这篇文章就围绕“动态库如何映射到进程地址空间”展开。一、动态库为什么比静态库更常用静态链接会把用到的库代码合并进可执行文件。这样程序可以独立运行但也带来两个问题可执行文件变大。多个程序使用同一个库时会重复保存同一份代码。假设系统里有 100 个程序都用到了 C 标准库。如果每个程序都把 libc 的代码静态链接进去磁盘和内存都会浪费大量空间。动态库的思路是把公共代码单独放在 .so 文件中 程序运行时再加载 多个进程尽量共享同一份库代码。这就是动态库广泛使用的重要原因。二、动态库也是文件先明确一点动态库不是内存里凭空出现的东西它首先是磁盘上的一个普通文件。例如ls-l/lib64/libc.so.6file/lib64/libc.so.6你会发现它是一个 ELF shared object。所以加载动态库的第一步仍然是文件操作找到 .so 文件 打开 .so 文件 读取 ELF 信息 把需要的 segment 映射进内存只不过这个过程通常由动态链接器和内核协作完成程序员平时不直接感知。三、动态库加载的整体流程一个动态链接程序启动时大致流程如下1. 内核加载主程序 ELF 2. 发现主程序需要动态链接器 3. 动态链接器读取主程序依赖的 .so 列表 4. 找到每个 .so 文件 5. 将 .so 的代码段、数据段等映射到进程地址空间 6. 完成必要的符号解析和重定位 7. 进入程序 main 函数如果第 4 步找不到库就会出现我们前一篇讲的libxxx.so not found如果能找到库下一步就是把库映射到进程地址空间中。四、从磁盘 .so 到物理内存当程序依赖libmyc.so时动态链接器会找到磁盘上的库文件。然后系统会把库中需要加载的 segment 放入物理内存尤其是代码段.text对应的内容。可以先粗略理解为磁盘 libmyc.so - 加载到物理内存中的若干页现代系统很多时候还会用文件映射、按需分页等机制并不是一开始就把整个库所有内容都读入内存。但从理解动态库共享的角度我们先抓住核心库文件的内容最终要对应到物理内存页。五、从物理内存到进程虚拟地址空间进程不能直接使用物理地址。每个进程看到的是自己的虚拟地址空间。所以动态库加载后还需要在当前进程的虚拟地址空间中划出一段区域用来映射这份库。可以理解为进程虚拟地址空间中的一段共享区 - 通过页表 - 映射到物理内存中的 libmyc.so 代码页例如进程 A 中libmyc.so可能映射到0x7f1000000000 ~ 0x7f1000010000这只是进程 A 自己看到的虚拟地址范围。真正的物理内存在哪里进程并不直接关心。CPU 会通过页表完成转换。六、多个进程如何共享同一个动态库假设进程 A 和进程 B 都依赖libmyc.so。进程 A 启动时磁盘 libmyc.so - 物理内存代码页 进程 A 的虚拟共享区 - 映射到这些物理页进程 B 启动时如果系统发现这份库的代码页已经在物理内存中就不必再加载一份完整代码。它只需要给进程 B 分配自己的虚拟共享区 让进程 B 的页表也映射到同一批物理代码页于是形成进程 A 虚拟地址 0x7f1000000000 - 同一份物理库代码 进程 B 虚拟地址 0x7f2000000000 - 同一份物理库代码注意两个进程的虚拟地址可以不同 但它们可以映射到同一份物理内存。这就是动态库节省内存的关键。七、共享的是代码不是什么都共享动态库中并不是所有内容都能随便共享。一般来说只读代码段可以共享 只读数据可以共享 可写数据通常不能直接在进程间共享。原因很简单如果动态库中的全局变量被多个进程共享那进程 A 修改变量会影响进程 B这显然不符合普通进程隔离原则。所以动态库的可写数据部分通常会为每个进程提供独立映射或者通过写时拷贝等机制保证进程隔离。动态库节省内存主要依赖代码段只读可以被多个进程共享。这也是为什么动态库代码要尽量做到位置无关不能随便修改代码段本身。八、为什么动态库加载地址不固定每个进程都有自己的虚拟地址空间。不同进程加载了不同的程序、不同的库地址空间中空闲区域也不同。所以动态链接器不能假设所有进程都把libmyc.so放到同一个虚拟地址。它通常会在当前进程地址空间中选择一段合适的空闲区域把动态库映射进去。这就带来一个关键问题动态库如果被加载到任意地址里面的函数调用和全局变量访问怎么保证正确这就是下一篇 GOT/PIC 要解决的问题。九、使用 /proc 查看动态库映射Linux 提供了/proc/[pid]/maps可以查看进程地址空间映射。先运行一个程序让它保持一段时间./main如果程序很快退出可以在代码中加sleep(100)。然后查看pidof maincat/proc/进程PID/maps你会看到类似7f... r-xp ... /lib64/libc.so.6 7f... r--p ... /lib64/libc.so.6 7f... rw-p ... /lib64/libc.so.6这些行说明libc.so.6的不同部分被映射到了进程虚拟地址空间中并且权限不同r-xp可读可执行通常对应代码段 r--p只读 rw-p可读可写通常对应数据段这能非常直观地看到动态库确实进入了进程地址空间。十、使用 pmap 查看进程映射也可以使用pmap 进程PID它会以更简洁的形式展示进程内存映射。例如pmap$(pidof main)可以看到主程序、堆、栈、动态库等区域。学习动态库时/proc/[pid]/maps是非常有价值的观察工具。十一、动态链接和静态链接再对比一次静态链接库代码在链接阶段进入可执行文件 程序运行时不再找库 多个程序各自包含一份库代码。动态链接可执行文件记录依赖 程序运行时加载 .so 多个进程可以共享同一份库代码物理页。动态链接本质上把一部分链接工作推迟到了程序加载和运行阶段。这带来灵活性也带来复杂性。十二、为什么动态库需要后续重定位动态库被映射到进程地址空间后它的加载地址才真正确定。但库代码中可能需要访问库内函数 库内全局变量 其他动态库函数 主程序中的符号有些地址必须在加载后才能知道。所以动态链接器还要做符号解析和重定位让这些引用指向正确位置。问题是代码段通常是只读且共享的不能每个进程都直接修改代码段里的地址。因此动态链接需要一种更巧妙的机制把可能变化的地址放到可写表中代码通过查表跳转。这张表就是 GOT全局偏移表。十三、总结动态库加载不是简单地“把.so拷贝进进程”。更准确的理解是动态链接器找到 .so 内核把 .so 的 segment 映射进进程虚拟地址空间 多个进程可以通过各自页表映射到同一份物理代码页 动态链接器再完成必要的符号解析和重定位动态库节省内存的关键在于只读代码段可以共享。但动态库加载地址不固定这就要求动态库不能把绝对地址写死在代码里。下一篇我们继续讲 GOT 与 PIC看动态库如何做到“加载到哪里都能运行”。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号