1. 什么是虚拟内存?为什么需要?

虚拟内存:每个进程有独立的虚拟地址空间(64 位 Linux 上约 128TB),通过页表映射到物理内存。进程看到的地址 ≠ 物理地址。

三个价值:

  1. 隔离与安全:进程间地址互不可见,A 进程崩溃不影响 B
  2. 内存不足也能跑:物理内存不够时,不常访问的页换出(swap)到磁盘,用的时候换入(缺页中断)——虚拟内存 > 物理内存
  3. 简化编程:程序不用管物理内存碎片和布局,地址连续

🎯 面试要点

  • 页表开销:每个进程一张页表 → 多级页表 + TLB(快表)缓存最近映射,TLB miss 才查内存
  • Java 视角:JVM 堆是虚拟地址,物理内存不足时可能 swap(性能暴跌)→ 监控要关注 swap 使用
  • free 命令的 buff/cache:PageCache 占"看起来"很多内存是正常的(可回收)

2. 分页和分段的区别?

🎯 面试要点

  • 内部碎片 vs 外部碎片:分页内碎片(每页浪费 <4KB)、分段外碎片(缝隙无法利用)
  • 大页(Huge Pages 2MB/1GB):减少页表项、TLB miss → JVM/数据库优化参数(-XX:+UseLargePages)

3. 页面置换算法?

🎯 面试要点

  • 最优置换(OPT)只存在于理论(预知未来)——LRU 是它的实际近似
  • Redis 的近似 LRU 也是 Clock 思路(抽样)——跨模块呼应

4. mmap 是什么?与普通 IO 的区别(零拷贝)?

Java 中的 mmap
// MappedByteBuffer:直接映射文件,省拷贝
FileChannel channel = FileChannel.open(path, StandardOpenOption.READ);
MappedByteBuffer buf = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
// 后续像操作 ByteBuffer 一样读文件(缺页按需加载)

🎯 面试要点

  • mmap 风险:映射大文件占虚拟地址空间、写回时机不可控(可用 msync 强制)
  • 零拷贝是 IO 性能面试的王牌答案:Kafka 消费(sendfile)+ Netty(mmap/DirectBuffer)

🎤 常见面试追问

  1. 虚拟内存解决了什么问题?——进程隔离(地址互不可见)、内存不足兜底(swap 换入换出)、简化编程(连续地址)。代价:页表 + 缺页开销。
  2. 缺页中断是什么?——访问的页不在物理内存 → CPU 触发异常 → OS 从磁盘换入 → 更新页表 → 恢复执行。频繁缺页 = 抖动(thrashing),性能灾难。
  3. 页面置换算法有哪些?——FIFO(简单有 Belady 异常)、LRU(最优近似)、LFU(按频率)、Clock(LRU 近似,Linux 实际用)。
  4. mmap 和普通 read 的区别?——mmap 把文件映射到虚拟地址空间,读写像操作内存,省一次用户态拷贝(零拷贝基础);普通 read 要用户缓冲中转。
  5. 大页(Huge Pages)有什么用?——页表项更少(2MB/1GB 一页),TLB miss 减少——数据库/JVM 大内存场景的调优项。

📖 名词解释(本页术语)

术语 大白话解释
虚拟内存给每个进程一个"假的大地址空间",页表映射到物理内存——隔离 + 可超卖物理内存。
页表 / TLB页表 = 虚拟页→物理页的映射表;TLB = 页表的 CPU 快缓存(miss 才查内存)。
缺页中断要用的页不在内存 → 从磁盘换入(慢,毫秒级)。内存不够时频繁触发 = 性能灾难。
swap(交换分区)磁盘上的"备用内存":物理内存不足时换出闲置页。swap 用得越多程序越慢。
分页 / 分段内存管理两种方式:分页固定 4KB(现代 OS 用);分段按逻辑划分(有外部碎片)。
页面置换算法内存满时"换出谁"的决策:LRU(最久没用)、LFU(用得最少)、Clock(近似 LRU)。
mmap(内存映射)把文件/设备映射进虚拟地址空间,读写像内存操作——零拷贝的基础(Java MappedByteBuffer)。
零拷贝数据从磁盘到网卡不经用户态(mmap/sendfile/DMA)——Kafka、Netty 的性能关键。
⚠️ 本页面由 AI 生成,内容仅供参考,请以官方文档和实际源码为准。