当前位置: 首页 > news >正文

CPU RAM(内存) 是什么?一篇文章搞定入门!

先来看两张图大致了解一下基本结构:


CPU

我们先来看看一条程序是如何执行的?

CPU 执行程序的过程如下:

  • 第⼀步,CPU 读取「程序计数器」的值,这个值是指令的内存地址,然后 CPU 的「控制单元」操作

「地址总线」指定需要访问的内存地址,接着通知内存设备准备数据,数据准备好后通过「数据总线」将指令数据传给 CPU,CPU 收到内存传来的数据后,将这个指令数据存⼊到「指令寄存器」。

  • 第二步,CPU 分析「指令寄存器」中的指令,确定指令的类型和参数,如果是计算类型的指令,就把

指令交给「逻辑运算单元」运算;如果是存储类型的指令,则交由「控制单元」执行;

  • 第三步,CPU 执⾏完指令后,「程序计数器」的值⾃增,表示指向下⼀条指令。这个自增的大小,由

CPU 的位宽决定,⽐如 32 位的 CPU,指令是 4 个字节,需要 4 个内存地址存放,因此「程序计数器」的值会⾃增 4;

简单总结⼀下就是,⼀个程序执行的时候,CPU 会根据程序计数器⾥的内存地址,从内存里面把需要执行

的指令读取到指令寄存器里面执行,然后根据指令长度自增,开始顺序读取下⼀条指令。

CPU 从程序计数器读取指令、到执行、再到下⼀条指令,这个过程会不断循环,直到程序执行结束,这个

不断循环的过程被称为CPU 的指令周期

这里可能有人又会有疑问了,你说 CPU 读取「程序计数器」的值,那程序计数器的值在哪来?(了解)

这里的程序计数器(PC/RIP)的值从哪来?—— 现代 Linux 版:

阶段一:系统启动(从 UEFI 到 Kernel)

当你按下电源键时,现代 Linux 的接力跑是这样的:

  1. 硬件强制 (Reset Vector): 通电瞬间,CPU 的程序计数器(在 64 位下叫RIP)被硬件强制指向主板 Flash 芯片上的UEFI 固件入口。
  2. UEFI 掌权 (The Firmware): UEFI 开始运行,初始化硬件(内存、显卡等)。
    • 关键区别:它不再去读取硬盘的前 512 字节(MBR),而是直接挂载硬盘上的ESP 分区(一个 FAT32 格式的分区)。
  1. 加载“垫脚石”与引导程序 (Shim & GRUB): UEFI 在 ESP 分区里找到并执行.efi文件。
    • 通常先执行shimx64.efi(为了通过安全启动验证)。
    • 然后由 Shim 拉起真正的 Linux 引导程序GRUB(grubx64.efi)。
    • 此时,PC 指针指向了内存中的 GRUB 代码。
  1. 加载内核 (Loading vmlinuz): GRUB 读取配置文件,找到硬盘里的Linux 内核文件(通常叫vmlinuz)和初始化内存盘initramfs)。 GRUB 把这两个大文件加载到内存里。
  2. 移交控制权 (Kernel Takeover): GRUB 完成任务,修改 PC (RIP) 指针,使其指向Linux 内核的入口地址
    • 从此,CPU 归 Linux 内核管,开始初始化systemd等进程。

阶段二:你运行程序(ELF 的加载与执行)

当你双击一个图标,或者在终端输入./my_program时,Linux 内核开始忙活了:

  1. 识别格式 (Not .exe but ELF): Linux 不认.exe,它运行的是ELF (Executable and Linkable Format)格式的文件。 操作系统调用fork()execve()系统调用来启动新进程。
  2. 映射而非搬运 (mmap)关键修正:现代 Linux 通常不会傻傻地把整个文件从硬盘一次性“搬运”到内存。
    • 它使用mmap(内存映射)技术,在虚拟内存里“占个座”,告诉 CPU:“这个程序的数据在硬盘的某某位置,用到的时候再去拿(缺页中断)。”这样速度极快。
  1. 动态链接 (Dynamic Linker): 大多数 Linux 程序需要依赖.so库(类似 Windows 的 .dll)。 内核会先让 PC 跳到动态连接器(ld-linux.so) 的地址,由它把需要的库(如libc.so)加载进来。
  2. 寻找入口 (Find Entry Point): Linux 读取 ELF 文件的头部信息(ELF Header),找到Entry Point Address
    • 注意:现代系统开启了ASLR (地址随机化),所以入口地址不再是固定的0x8000这种整数,而是一个每次运行都不同的随机虚拟地址(例如0x55a3...),以防止黑客攻击。
  1. JUMP (Context Switch): 万事俱备,内核调度器(Scheduler)决定运行这个新进程。 内核修改 CPU 的RIP 寄存器(程序计数器),将其指向程序的 Entry Point(通常是_start符号,随后调用main函数)。
  2. 开始执行: CPU 看到 RIP 变了,跳转到用户空间的代码开始执行。你的 Linux 程序窗口(比如 VS Code 或 终端输出)就出现了。

下面以a = 1 + 2为例,看看在冯诺伊曼模型(32位 CPU)下的程序执行过程:

第一步:翻译与布局 (Compile & Layout)

  • 翻译:编译器将高级代码a = 1 + 2依次转化为汇编代码->机器码(CPU 唯一认识的 0/1 指令)。
  • 分段存储
    • 数据段:存放数据1(在 0x100) 和2(在 0x104)。
    • 正文段:存放编译后的4 条指令(从 0x200 开始)。

第二步:初始化 (Initialization)

  • 程序计数器 (PC)被设置为程序的起始指令地址0x200,准备开始执行。

第三步:指令执行循环 (Execution Cycle)

CPU 依次执行正文段中的 4 条指令:

  1. Load (取数):把地址0x100里的数(1)加载到寄存器R0
  2. Load (取数):把地址0x104里的数(2)加载到寄存器R1
  3. Add (运算):CPU 运算单元计算R0 + R1,结果(3)存入R2
  4. Store (存回):把R2里的结果写回内存地址0x108(变量 a 的位置)。

第四步:地址自增 (PC Increment)

  • 每执行完一条指令,PC 自动增加4(因为 32 位 CPU 中一条指令占 4 字节),指向下一条指令(0x200 -> 0x204 -> ...),直到程序结束。

RAM

我们先来看看 RAM 的大致结构以及操作系统是如何管理 RAM 的:

  • 地址隔离(安全性): 操作系统为每个进程分配独立的虚拟地址空间。进程只能看到并使用自己的虚拟地址,无法直接触碰物理内存,从而互不干扰。
  • 两套地址(概念区分)
  • 虚拟地址:程序代码中使用的逻辑地址。
  • 物理地址内存条(RAM)硬件上实际存在的存储地址。
  • 动态映射(核心实现): 操作系统维护映射表,由硬件MMU(内存管理单元)负责实时将“虚拟地址”翻译成“物理地址”,确保数据准确落入物理内存且不发生冲突。

所以我们重点要了解的一个概念就是 ——虚拟内存

学习虚拟内存之前,我们需要了解,虚拟内存怎么发展来的,虚拟内存是啥

计算机发展史上的两个核心阶段:实模式(Real Mode)保护模式(Protected Mode/Virtual Memory)

阶段一:裸奔时代(无操作系统 / DOS 时代)

  • 你可以叫它:单片机模式、实模式。
  • 写代码的人:必须知道这台机器有多少内存。如果机器只有 1KB 内存,你写代码往0x2000写数据,程序直接崩溃或跑飞。
  • 编译出的指令MOV EAX, [0x100]
  • 执行过程:CPU 看到0x100,直接把电流送到内存条的第 100 号单元。
  • 缺点
    • 不安全:程序 A 可以随意修改程序 B 的数据(因为大家都在物理内存上裸奔)。
    • 麻烦:每次换个内存大小不同的电脑,程序可能都要重新改。

阶段二:现代操作系统时代(虚拟内存时代)

  • 你可以叫它:保护模式。
  • 写代码的人:完全不用管物理内存多大。你假装自己有 4GB,随便用。
  • 编译出的指令MOV EAX, [0x100](注意:这里的指令长得一模一样!)
  • 执行过程
    1. 指令中的地址0x100虚拟地址
    2. 中间层介入:CPU 想去访问0x100,被**MMU(硬件)**拦住了。
    3. 查表(OS的工作):MMU 去查操作系统维护的页表
    4. 映射:页表上写着:“虚拟0x100-> 物理0x9999”。
    5. 最终访问:电流最终去读内存条的第9999号单元。

接下来我们就学习一下操作系统是如何管理虚拟地址与物理地址之间的关系

1. 虚拟内存机制(核心目标:隔离与扩展)

  • 隔离性:为每个进程分配独立的虚拟地址空间,进程间互不干扰,感知不到物理内存的差异。
  • 内存交换 (Swap):通过将不常使用的内存数据暂时“换出”到硬盘,解决物理内存不足的问题。

2. 地址映射方案(分段 vs 分页)

  • 分段 (Segmentation):按逻辑(代码、堆、栈)分块,连续但大小不一。
    • 缺点:易产生内存碎片,内存交换效率低。
  • 分页 (Paging):按固定大小(如 Linux 4KB)切分。
    • 优点:彻底解决外部碎片,大幅提升内存交换效率(按页流转)。

3. 性能与空间优化(多级页表 & TLB)

  • 多级页表:解决“页表本身占用内存过大”的问题(空间换时间,虽然变慢但省内存)。
  • TLB (快表):利用局部性原理,在 CPU 缓存最近的映射关系,解决“多级页表导致寻址慢”的问题(提速)。

4. Linux 的具体实现(“屏蔽”分段)

  • 策略:Linux 主要采用分页管理
  • 兼容性:为了兼容 x86 硬件的段式架构,Linux 将所有段基址设为0。这被称为“扁平模型”,实质上屏蔽了分段的逻辑地址转换,只利用分段做权限控制。

5. 虚拟空间布局

  • 两态区分:虚拟空间划分为内核态(高地址)和用户态(低地址)。
  • 用户态包含:代码段、数据段(全局变量/BSS)、堆(Heap)、栈(Stack)、文件映射区。

一句话总结:操作系统通过虚拟内存实现进程隔离,利用分页解决碎片和效率问题,通过多级页表+TLB平衡空间与时间开销,并在 Linux 中采用扁平模型弱化分段机制,最终构建出高效、安全的内存管理体系。

参考资料 —— 小林coding《图解系统》


http://www.cnnetsun.cn/news/174868.html

相关文章:

  • 【毕业设计】基于springboot的校园零售管理系统的设计与实现(源码+文档+远程调试,全bao定制等)
  • 硬件自查自纠!十年前的电脑可能还可以再战十年
  • 一键配置 Web 前端开发环境(PowerShell 自动化脚本)
  • 程序员必备技能:AI Agent 9种设计模式深度解析,提升大模型应用效能(值得收藏)
  • 【python大数据毕设实战】哮喘患者症状数据可视化分析系统、Hadoop、计算机毕业设计、包括数据爬取、数据分析、数据可视化、机器学习
  • 9 个降AI率工具,MBA 必备避坑指南
  • Windows系统文件inetmib1.dll丢失损坏 下载修复方法
  • Boost电路的右半平面零点
  • 【全球AI伦理治理】
  • 毕业季必看!7款免费AI写论文神器实测,一站式搞定选题、大纲到降重
  • LLMs之Survey之Agent:《Measuring Agents in Production》翻译与解读
  • 零代码上手Google Gemini 3:5种实用方法大揭秘
  • “你用的那个AI,到底把你坑了还是救了?”——解锁宏智树论文的协作新范式
  • 好写作AI:别等学校采购了!你的论文“救命神器”自己就能用上
  • Windows系统文件GdiPlus.dll丢失或损坏 下载修复方法
  • 研究生必备8款AI写论文神器:5分钟生成25000字问卷类论文,自动生成高信度数据
  • 【BuildFlow 筑流】unitrix_macros库 Cargo.toml 配置详解及依赖库用法
  • 《开发者出海必看:如何优雅地搞定海外服务支付?(保姆级干货)》
  • Thinkphp和Laravel企业防爆安全设备信息系统
  • Thinkphp和Laravel全家桶鲜花售卖商城系统vue
  • 记录我适配iOS26遇到的一些问题
  • 通过命令模拟pod创建
  • 同步机无感 STM32 低成本 MD500E 永磁同步控制方案大揭秘
  • 小宝玩具 【通达信、源码 、主图、附图】
  • 使用 Github Pages 和 Hexo
  • 审稿 一区期刊注意事项: journal offers the option to connec;please note, reviewers are not expected 是什么意思
  • 线性代数:多维世界的变形工具箱
  • 力扣题目142. 环形链表 II​的解法分享,附图解
  • MATLAB电力系统继电保护之自动重合闸
  • 10 个AI写作工具,助你轻松搞定继续教育论文!