news 2026/6/10 13:49:34

深入了解动态链接中的GOT和PLT具体如何工作,以及进程调度中PCB的详细结构

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
深入了解动态链接中的GOT和PLT具体如何工作,以及进程调度中PCB的详细结构

关于GOT/PLT部分,需要解释清楚它们的分工:PLT是位于代码段的跳转表,GOT是位于数据段的地址表。重点说明首次调用函数时的解析过程——如何通过PLT条目跳转到动态链接器,解析出真实地址后写回GOT,后续调用如何直接跳转。这个过程体现了空间换时间和延迟绑定的设计思想。

关于PCB结构,需要从Linux实际的task_struct出发,但避免陷入过多代码细节,按功能分类讲解:标识信息、调度信息、内存信息、文件信息和上下文状态。特别强调上下文切换时如何通过保存和恢复PCB中的寄存器状态来实现进程透明切换。

为了更直观,考虑设计两个核心示意图:一个是GOT/PLT的首次调用与后续调用对比图,展示地址解析过程的变化;另一个是PCB在进程切换中的保存与恢复机制图。这两个图能帮助用户形象理解内存数据结构和系统操作流程。

在组织回答时,会先处理GOT/PLT机制,然后详细展开PCB结构,最后简要说明两者如何通过虚拟内存和系统调用在进程环境中协同工作。

动态链接、库、内存、进程等概念不是孤立的,它们共同构成了一个程序从“静态文件”变成“活跃任务”并访问资源的完整生命周期

为了帮助你直观理解这个复杂系统如何协同工作,我将其比喻为一个“剧院系统”。下图描绘了这个全景式的工作流程:

渲染错误:Mermaid 渲染失败: Parse error on line 4: ... A1[“可执行文件
(ELF/PE)”] -- “依赖声明” -----------------------^ Expecting 'SQE', 'DOUBLECIRCLEEND', 'PE', '-)', 'STADIUMEND', 'SUBROUTINEEND', 'PIPE', 'CYLINDEREND', 'DIAMOND_STOP', 'TAGEND', 'TRAPEND', 'INVTRAPEND', 'UNICODE_TEXT', 'TEXT', 'TAGSTART', got 'PS'

下面,我们来逐一拆解这个“剧院系统”中的每个角色和它的工作机制。

🎭 核心概念的角色与工作机制

概念在“剧院系统”中的角色核心工作机制与原理
进程一场完整的戏剧演出。它是一个独立的执行环境,拥有自己的舞台、道具和剧本。操作系统通过fork()系统调用“复制”一个父进程,再通过exec()系统调用“替换”为新的可执行程序,从而创建新进程。它为程序提供运行所需的虚拟CPU、内存和资源。
PCB导演手中的完整剧本和现场记录。它精准记录了演出(进程)在任一时刻的全部状态这是内核中的一个数据结构task_structin Linux)。当进程被切换出CPU时,其寄存器、状态等信息被保存在PCB中;切换回来时,再从中恢复,实现“无缝续演”。
内存块剧院舞台上的一个个“区块”。每个区块被规划为不同的用途(如静态区、堆区、栈区)。操作系统通过虚拟内存机制,为每个进程提供一个从0开始的、连续的虚拟地址空间。内核和MMU(内存管理单元)负责将虚拟地址映射到物理内存或硬盘交换区。
模块戏剧中的一幕或一个场景。在进程中,它是一段被加载的、可执行的代码和数据单元主程序是一个模块,每一个被动态加载的共享库也是一个独立的模块。它们被加载到进程内存空间的不同区域,但共同构成完整的程序功能。
动态链接与库共享道具库和实时调配机制。动态库(.so/.dll)是存放在后台道具库(磁盘)的可重用代码1.延迟绑定:程序启动时,动态链接器(ld.so)将库映射到进程内存,但函数地址的解析可能推迟到首次调用时,以提高启动速度。
2.全局偏移表(GOT):这是一个“地址查询表”,程序通过它间接调用库函数。链接器在运行时将真正的函数地址填入此表。
文件描述符(fd)/句柄(Handle)访问后台资源(如特殊道具、灯光控制台)的“提货单”或“控制令牌”它们是进程打开文件表的索引(整数)。这个表是PCB的一部分,每个条目指向内核中一个打开文件对象,该对象包含了文件的当前位置、访问模式等状态。所有资源(文件、套接字、设备)在此抽象下被统一看待。

💡 协同工作实例:在Linux上运行一个程序

让我们以在终端运行./myapp为例,看上述概念如何联动:

  1. 创建进程与初始化内存

    • 你的 Shell 进程调用fork()创建一个子进程(继承父进程的PCB副本和内存空间)。
    • 子进程调用execve("./myapp", ...)
    • 内核销毁子进程旧的虚拟内存空间,根据可执行文件信息,为其创建全新的虚拟内存空间(内存块),并设置好代码段、数据段等。
  2. 动态链接与加载模块

    • 内核将控制权交给动态链接器(ld-linux.so,它本身也是一个共享库模块)。
    • 链接器读取myapp的依赖列表(ldd myapp可查看),将所需的库(如libc.so.6)从磁盘加载(映射)到进程的虚拟内存空间,成为新的模块
    • 链接器执行重定位,在GOT中填充库函数的最终地址,完成所有模块的链接。
  3. 运行与资源访问

    • 程序开始执行。当它执行到open("data.txt", O_RDONLY)时,会触发系统调用
    • 内核打开文件,在进程的打开文件表中创建一个条目,并返回一个**文件描述符(例如 3)**给用户程序。
    • 此后,程序使用read(fd, ...)时,内核通过文件描述符 3 找到内核中的文件对象,完成读取。
  4. 进程调度与状态保存

    • 假设此时时间片用完,内核决定切换到另一个进程。
    • 它会将当前进程的所有CPU寄存器值保存到其PCB中,然后从另一个进程的PCB中恢复寄存器值,实现切换。
  5. 释放与结束

    • 程序结束,进程退出。内核会回收该进程占用的所有资源:销毁其虚拟内存空间(所有内存块)、关闭所有打开的文件(释放所有文件描述符)、删除其PCB

🔗 关系概述

它们的关系可以概括为:进程是容器和执行的单元;PCB是它的身份证和病历本;虚拟内存(内存块)是它的私人舞台;动态链接是在舞台上按需搭建共享场景(库模块)的机制;而文件描述符/句柄是它从内核这个“舞台后台”申请和使用各种资源(文件、网络等)的统一凭证。所有这一切,都依赖操作系统内核进行精密的调度和管理。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/9 15:38:44

Jupyter Lab整合PyTorch:交互式编程提升开发效率

Jupyter Lab整合PyTorch:交互式编程提升开发效率 在深度学习项目中,你是否曾因环境配置失败而浪费一整天?是否在调试模型时反复重启脚本,只为查看一个中间输出?又或者,在团队协作中因为“在我机器上能跑”这…

作者头像 李华
网站建设 2026/6/7 7:26:21

Docker Volume持久化存储PyTorch训练结果

Docker Volume 持久化存储 PyTorch 训练结果 在深度学习项目中,一次完整的模型训练往往需要数小时甚至数天。当 GPU 正在全力运行、显存占用接近极限时,最怕的不是性能瓶颈,而是——容器一删,所有训练成果灰飞烟灭。 这并非危言耸…

作者头像 李华
网站建设 2026/6/10 1:08:15

使用Logrotate管理PyTorch长时间训练日志

使用 Logrotate 管理 PyTorch 长时间训练日志 在深度学习项目中,一个看似不起眼却常常引发严重后果的问题是:日志文件失控增长。你是否经历过这样的场景?某次长达数天的模型训练任务正在进行,GPU 利用率稳定、损失曲线平滑下降——…

作者头像 李华
网站建设 2026/6/7 21:16:27

新手教程:手把手学习PCB设计规则基础内容

新手也能懂的PCB设计规则实战指南:从“连通就行”到“一次成功”你有没有过这样的经历?辛辛苦苦画完一块板子,原理图检查了三遍,元器件也排布得整整齐齐,结果一上电——MCU不启动、ADC读数跳来跳去,甚至电源…

作者头像 李华
网站建设 2026/6/10 10:28:50

Docker镜像瘦身技巧:减小PyTorch-CUDA体积

Docker镜像瘦身技巧:减小PyTorch-CUDA体积 在AI模型部署的日常中,你是否经历过这样的场景:CI流水线卡在“拉取镜像”阶段长达数分钟?Kubernetes集群因节点存储不足而拒绝调度新Pod?或者边缘设备上一次镜像推送耗时超过…

作者头像 李华
网站建设 2026/6/10 11:42:27

Zotero GPT完整使用教程:5步实现文献智能管理

还在为海量学术文献整理而头疼?Zotero GPT插件将彻底改变你的研究方式!这款创新工具将OpenAI的强大AI能力无缝集成到Zotero文献管理系统中,让你在5分钟内就能体验到智能文献处理的便利。无论你是学生、研究人员还是学术工作者,这款…

作者头像 李华