Luna Tech | 聊聊内存(Memory)

July 26, 2020 字数 2294 5 min


0. 前言

每台电脑都有操作系统,比如 Windows 系统,Mac OS 等。

对于操作系统而言,最重要的就是管理计算机的资源,包括(但不限于):

  1. 进程管理(Process Management)
  2. 内存管理(Memory Management)
  3. 文件管理(File Management)
  4. 设备管理(Device Management)

今天我们聊的是内存管理。

内存是什么呢?

首先我们要知道,计算机储存数据的方式有两种:

  1. 内存
  2. 外存(如硬盘、USB 等储存设备,使用时需要调入内存)

所以,内存就是计算机储存数据的方式之一。


1. 内存分类

内存又可以分为:

  1. RAM(包括 Cache)
  2. ROM

PS:Cache(缓存)在 CPU 里面讲过。

价格:Cache > RAM > ROM

速度:Cache > RAM > ROM

和 CPU 的距离:Cache < RAM < ROM

RAM 和 ROM 的区别

RAM (Ramdom Access Memory) :随机存取存储器

ROM (Read Only Memory):只读存储器

RAM(随机存取存储器) ROM(只读存储器)
断电后 数据丢失 数据还在
读数据
写数据 ×
大小(size) 比较大 比较小
用途 CPU cache,内存 存储与设备相关的信息;跟 BIOS(Basic Input/Output System) 相关

ROM 是在设备出厂的时候就写好的;

当你启动计算机的时候,ROM 是首先运行的,由于里面包含着一些重要的固件信息,一般来说是不会修改的。

PS: 目前有提议用 UEFI (Unified Extensible Fireware Interface) 来取代 BIOS。

Memory 的定义

一般来说,Memory 指的是 RAM。

Memory


2. Data - Stack vs Heap vs Queue

Stack(栈) vs Queue(队列)

之前我们在 Data Type 里面讲过 Stack 和 Queue 的区别,Stack 是 FILO,Queue 是 FIFO。

Stack 和 Queue 都是 Abstract Data Type。

那么 Heap 又是什么呢?

Heap(堆)

其实 Heap 是一种数据结构(Data Structure),而我们知道,数据结构是用来实现数据类型的。

那么 Heap 是什么数据类型呢?

答案是:Priority Queue,也就是 Queue 的一种特殊类型。

Priority Queue

这种 Queue 和我们之前讨论的 FIFO 有一个不同之处,那就是每个排队的成员都增加了一个叫做优先级(priority)的属性。

Queue:1 号,2 号,3 号,4 号(1 号先进,1 号先出)

Priority Queue:1 号(优先级=1),2 号(优先级=5),3 号(优先级=3),4 号(优先级=2)

在这个带有优先级的 Queue 里面,优先级越高,越先出去。

所以 2 号先出去,接着是 3 号,4 号,1 号。

在这种数据类型中,顺序是由优先级决定的。

Heap 就是 Priority Queue 的实现形式。

Heap vs Priority Queue vs Queue

Stack vs Heap vs Queue


3. Memory - Stack vs Heap

这里我必须吐槽一下,memory 里面的 stack 和 heap 其实跟 data 里面讲的 stack 和 heap 是不一样的!!!!!(虽然名字一样

对于新手小白来说,这些名词简直太容易混淆了(说的就是我)。

在咨询了各路大神之后,发现:

Memory Stack(内存栈)和 Memory Heap(内存堆)跟我们之前提到的数据结构(Heap)、数据类型(Stack)没有直接关系!!!

内存分配

内存分配有两种方式:静态内存分配(Static Memory Allocation)和动态内存分配(Dynamic Memory Allocation)。

Stack Memory 和 Heap Memory 是内存的不同区域,静态内存分配使用的是 Stack Memory,动态内存分配使用的是 Heap Memory。

Stack Memory 依旧保持着 FILO (先进后出)的特性,但是 Heap Memory 就跟我们之前说的 Priority Queue 没有半毛钱关系了。

静态内存和动态内存有什么区别?

Difference Between Static and Dynamic Memory Allocation > 动态内存与静态内存有何优劣?

Memory : Stack vs Heap

静态内存 动态内存
内存是否可以变 固定大小,分配好了就不能变 分配好了也可以变
内存创建时间 程序编译时 程序调入和执行时
内存创建者 编译器 程序员(比如 C 语言的 malloc, calloc 函数,C# 里面的 new)
内存回收者 操作系统 程序员或编程语言自带的 Garbage Collection 功能
内存速度 很快 比静态内存慢

静态内存和动态内存的创建时间和创建者是不同的,分别对应程序生命周期的两个阶段(编译、运行)。

静态内存:静态变量和自动变量

C# Global Variables, Fields and Functions

静态内存分配的是静态变量(static variable)所占用的存储空间,这个空间在程序运行之前就可以被计算出来。

静态变量是程序里面声明的 static 变量或者 global 变量。

1
2
// 创建一个静态变量(static or global variable)
static int number = 1;

而自动变量(automatic variable)往往也被称为 Local variable,这些变量离开了 scope(作用域)之后就不需要了。这些变量是通过 stack-based memory(也就是静态内存)来分配的。

1
2
3
4
5
// 创建一个自动变量
void Method()
{
  int localVariable = 1;
}

所以,静态变量和自动变量都是通过静态内存来分配的。

PS: 静态内存如果用完了(比如你写了个 infinite for loop),报错是:StackOverflowException。

动态内存:引用类型

动态内存里面放的是 Reference Type

这里拿我之前的 C# Types 文章配图来举例,我们可以看到,Reference Type 的实际 Object 是存放在 Heap Memory 里面的,只有 Object Reference 是存放在 Stack Memory 里面的。

PS: 动态内存如果用完了(比如你没有好好回收资源造成了 memory leak),报错是:OutOfMemoryException。

In computer programming, a static variable is a variable that has been allocated “statically”, meaning that its lifetime is the entire run of the program.

The storage of shorter-lived automatic variables is stack allocated and deallocated on the call stack.

The storage of objects is dynamically allocated and deallocated in heap memory.

图解

Memory

Data


4. 结语

在这篇文章里面,我们讲了:

  • 内存的分类(RAM, ROM)
    • CPU 里面的 Cache 属于 RAM
  • RAM 和 ROM 的区别(RAM 能读能写, ROM 只读不写)
  • 重点区分了在不同语境里面的 Stack 和 Heap(数据语境和内存语境是完全不同的哦!!)
    • Heap 在数据语境里面 = Priority Queue 这种 ADT 的实现形式
    • Heap 在内存语境里面跟 Queue 没有半毛钱关系……
    • Stack 在两种语境里面都有 FILO 的特征
    • Call Stack 是 Stack ADT 的一种实现形式
  • 内存语境下,Stack 和 Heap 分别对应不同的内存分配方式(static 和 dynamic)
  • 静态内存分配完了就不能改,存的是静态变量和自动变量,由编译器和 CPU 管理,在程序编译期间分配
  • 动态内存分配完了也能改,存的是引用类型,由程序员和编程语言的特性来管理,在程序运行期间分配

Talk to Luna


Support Luna