内存主要是用来存储系统和应用程序的指令、数据、缓存等
内存映射
内存是需要安全机制保护的,所以只有内核才可以直接访问物理内存。进程如果要访问内存需要通过独立的虚拟地址空间。
虚拟地址空间其实包含两部分。一部分是内核空间,另一部分就是用户空间。
进程有用户态和内核态,用户态下只能访问用户空间,只有切换到内核态时才可以访问内核空间。
只有实际使用的虚拟内存才会分配物理内存,通过内存映射来管理。
内存映射其实就是将物理地址内存映射到虚拟内存。为每个进程维护了一张页表
页表其实是存储在CPU的内存管理单元MMU中。当发生缺页中断的时候,进入内核分配内存,更新进程页表,然后返回用户空间。
TLB是MMU中的高速缓存,通过减少上下文切换,可以减少TLB的刷新次数,就可以提高TLB的使用率。进而提高CPU的内存访问性能。
MMU是按照4KB为一页进行存储的,如果是4GB内存,那么就需要100多W页表项进行存储,才可以实现整个地址空间的映射。为了解决页表项过多的问题,Linux提供了两种机制,多级页表&大页
多级页表其实就是按照多个层级,最后按照对应的偏移地址。如下就是通过4级页表来管理。并且只存储使用的内存。
虚拟内存空间分布
空间内存分配其实就是按照 栈、文件映射、堆、数据段、只读段。堆和文件映射是动态分配的。
内存分配与回收
内存的分配是通过brk()和mmap()两个函数进行处理的。
brk() : 分配小于128K的内存,使用完并不立即归还给系统,而是缓存起来重复利用
mmap() : 直接使用内存映射来分配,也就是在文件映射段找一块空闲内存分配出去。
而当内存不足时,
- 回收缓存:使用LRU算法等进行回收。
- 回收不常用的内存,通过交换分区直接写到磁盘中
- 杀死进程:内存紧张时通过OOM,杀死占用大量内存的进程。
交换分区 Swap
其实就是把一块磁盘当作内存来使用,把不需要的进程数据先存储到磁盘中称为幻出,把数据从磁盘拉入内存称为换入。
但是swap可以增加系统内存,但是磁盘读写慢,所以会导致严重的内存性能问题。
OOM
内核的一种保护机制,监控进程内存的使用情况,大概就是为每个进程进行评分oom_socre。占用分数比较高的,就容易被杀死。
/proc
范围在[-17, 15 ]可以进行设置 -17是禁止。数值越少,越不容易被OOM杀死。
可以通过配置
echo -16 > /proc/$(pidof sshd)/oom_adj
如何查看内存使用情况
total是总内存、used是硬使用内存,包含共享内存、free是未使用内存、shared是共享内存的大小。
buff/cache 是缓存和缓冲区的大小。 available是新进程可用内存大小。
VIRT:进程虚拟内存大小
RES常驻内存大小
SHR 共享内存大小
%MEM是进程占用内存百分比。
小结
本篇主要简要介绍虚拟内存、内存如何分配、如何回收的、以及如何进行查看内存占用TOP、FREE两个命令。