linux 交换分区(Swap)

Linux 交换分区(Swap Partition) 是一块专门划分的磁盘空间,核心作用是作为物理内存的「扩展」 ------ 当物理内存不足时,内核会将物理内存中不活跃的页数据「换出(swap out)」到交换分区;当这些页数据需要被访问时,再将其「换入(swap in)」回物理内存。这种机制也被称为虚拟内存管理,是 Linux 内存管理子系统的重要组成部分。

核心目标

  • 扩展内存可用空间:让系统可以运行比物理内存总量更大的程序或更多进程。
  • 保证内存资源的高利用率:将不活跃的内存页置换到磁盘,释放物理内存给活跃进程使用。
  • 避免 OOM(内存不足) Killer 触发:当物理内存耗尽时,Swap 可以临时缓解内存压力,避免内核直接杀死进程。

典型应用场景

  • 物理内存较小的嵌入式系统:通过 Swap 弥补内存不足的问题。
  • 运行大内存消耗程序的场景:如数据库、虚拟机、科学计算等,Swap 可作为内存峰值的缓冲。
  • 休眠(Hibernation)功能:系统休眠时,会将整个物理内存的内容写入 Swap 分区,开机时再恢复,因此休眠功能要求 Swap 分区大小不小于物理内存。

工作原理

Swap 的核心是内核的 页面置换算法 ,其运作依赖于 Linux 内存管理的「页」机制 ------ 物理内存和 Swap 空间都以 页(通常 4KB) 为单位进行数据交换。

活跃页与不活跃页

内核通过 LRU(最近最少使用)链表 将物理内存中的页分为两类:

  • 活跃页(Active List):近期被频繁访问的页,内核会优先保留在物理内存中。
  • 不活跃页(Inactive List):近期很少被访问的页,是 Swap 换出的候选对象。

内核会定期扫描 LRU 链表,根据页面的访问频率调整其在活跃 / 不活跃链表之间的位置。

页面换出(Swap Out)

当物理内存使用率达到内核设定的阈值(由 /proc/sys/vm/swappiness 控制)时,内核启动换出流程:

  1. 选择换出页 :从 Inactive List 中挑选符合条件的页,优先选择匿名页(无文件映射的页,如进程栈、堆数据)------ 文件页可直接丢弃,需要时从磁盘文件重新读取,无需换出到 Swap。
  2. 分配 Swap 空间:内核从 Swap 分区 / 文件中分配一个空闲的 Swap 页槽(slot),记录该页的 Swap 位置(包括 Swap 设备编号和页偏移)。
  3. 写入数据 :将物理内存页的数据写入 Swap 槽,并更新该页对应的 page 结构体,标记为 PG_swapbacked,同时记录 Swap 位置信息。
  4. 释放物理页:将该页从 LRU 链表中移除,标记为空闲,纳入物理内存分配池。

页面换入(Swap In)

当进程访问一个已经被换出到 Swap 的页时,会触发 缺页异常,内核执行换入流程:

  1. 识别缺页类型 :内核通过 page 结构体判断该页是 Swap 换出页,获取其对应的 Swap 位置。
  2. 分配物理页:从物理内存中分配一个空闲页。
  3. 读取数据:将 Swap 分区中对应槽的数据读取到新分配的物理页中。
  4. 更新页表与 LRU :修改进程页表,将虚拟地址映射到新的物理页;将该页加入 Active List,标记为活跃;释放 Swap 槽,使其重新变为空闲。

Swap 的关键内核组件

组件 作用
swap_info_struct 描述 Swap 设备 / 文件的元数据,包括大小、空闲页槽数、优先级等
swap_entry_t 记录页在 Swap 中的位置(设备 ID + 页槽偏移),存储在页表项中
页面置换算法 决定哪些页被换出,Linux 默认使用 LRU-2Multi-Gen LRU(5.18+ 内核)
kswapd 内核线程 周期性扫描内存,当内存不足时主动触发页面换出,避免系统进入内存紧缺状态

Swap 的类型

Linux 支持两种 Swap 形式:Swap 分区Swap 文件,两者功能完全等价,仅创建和管理方式不同。

Swap 分区

  • 定义 :一块独立的磁盘分区,格式为 swap 类型(fdisk 中 ID 为 82)。
  • 优点:IO 性能略高(无文件系统开销),适合物理磁盘场景。
  • 缺点:需要提前划分分区,扩容或缩容需要重新分区,灵活性差。

Swap 文件

  • 定义:一个普通的磁盘文件,由内核格式化为 Swap 格式使用。
  • 优点:无需划分独立分区,创建和扩容灵活(支持动态增减),适合云服务器、虚拟机等灵活部署场景。
  • 缺点:有文件系统的元数据开销,IO 性能略低于 Swap 分区(现代文件系统如 Ext4/XFS 差距极小)。

创建 Swap 分区

步骤 1:划分磁盘分区

使用 fdiskparted 工具划分一个新分区,类型设为 swap(ID=82):

以 /dev/sdb 为例

fdisk /dev/sdb

在 fdisk 交互界面中:

1. 输入 n 创建新分区

2. 输入 t 修改分区类型,输入 82 设为 swap 类型

3. 输入 w 保存分区表

步骤 2:格式化 Swap 分区

使用 mkswap 命令将分区格式化为 Swap 格式:

mkswap /dev/sdb1

步骤 3:启用 Swap 分区

swapon /dev/sdb1

步骤 4:设置开机自动挂载

编辑 /etc/fstab 文件,添加以下内容:

/dev/sdb1 swap swap defaults 0 0

创建 Swap 文件

步骤 1:创建 Swap 文件

使用 dd 命令创建一个指定大小的文件(例如 4GB):

dd if=/dev/zero of=/swapfile bs=1G count=4

步骤 2:设置文件权限

限制 Swap 文件的访问权限,仅 root 可读写:

chmod 600 /swapfile

步骤 3:格式化 Swap 文件

mkswap /swapfile

步骤 4:启用 Swap 文件

swapon /swapfile

步骤 5:设置开机自动挂载

编辑 /etc/fstab 文件:

/swapfile swap swap defaults 0 0

常用 Swap 管理命令

命令 作用
swapon -s 查看当前启用的 Swap 设备 / 文件信息(大小、已用、优先级)
swapon /path/to/swap 启用指定的 Swap 设备 / 文件
swapoff /path/to/swap 关闭指定的 Swap 设备 / 文件
cat /proc/swaps 查看 Swap 详细信息(与 swapon -s 输出一致)
vmstat -s 查看内存和 Swap 的统计数据(如换入 / 换出页数)

Swap 的核心调优参数

Swap 的行为主要通过 /proc/sys/vm/ 下的内核参数调整,最关键的是 swappiness

swappiness:控制页面换出的倾向

  • 定义 :取值范围 0 ~ 100,默认值通常为 60(不同发行版略有差异)。
  • 含义
    • swappiness = 0:内核尽可能不换出内存页,仅在物理内存耗尽时才使用 Swap。
    • swappiness = 100:内核积极将不活跃页换出到 Swap,最大化物理内存的空闲空间。
  • 调优建议
    • 桌面系统 / 大内存服务器 :设置为 10 ~ 30,减少磁盘 IO 开销,提升响应速度。
    • 小内存系统 / 嵌入式设备 :设置为 60 ~ 80,充分利用 Swap 扩展内存。
    • 数据库服务器(如 MySQL) :设置为 1,避免数据库缓存页被换出,影响性能。

vfs_cache_pressure:控制文件缓存的换出倾向

  • 定义 :取值范围 0 ~ 100,默认值 100
  • 含义 :控制内核回收 页缓存(Page Cache) 的倾向,页缓存是文件系统的磁盘缓存。
    • 值越低,内核越倾向于保留页缓存;值越高,越倾向于回收页缓存。
  • 调优建议 :对于 IO 密集型场景,可适当降低该值(如 50),提升文件访问速度。

Swap的特点

  • Swap 是磁盘级存储 :磁盘 IO 速度远低于物理内存(机械硬盘差距约 1000 倍,SSD 差距约 100 倍),频繁的换入 / 换出会导致系统性能急剧下降,表现为 CPU 等待 IO 时间过长进程响应缓慢
  • Swap 是「应急方案」而非「性能方案」:Swap 仅适合缓解内存压力,不能替代物理内存。长期依赖 Swap 运行的系统,应优先扩容物理内存。
  • 误区 :「Swap 越大越好」------ Swap 过大会导致内核将大量活跃页换出,反而降低性能。通常建议 Swap 大小为 物理内存的 1~2 倍(休眠功能需等于或大于物理内存)。
  • 误区 :「禁用 Swap 能提升性能」------ 对于大内存系统,禁用 Swap 可能导致 OOM Killer 误杀进程;合理配置 swappiness 才是最优解。
相关推荐
南工孙冬梅2 小时前
【久久派】Linux 文件系统制作配置 基于buildroot
linux
宴之敖者、2 小时前
Linux——指令(下)
linux
抠脚学代码2 小时前
Qt与Linux
linux·数据库·qt
Code Warrior2 小时前
【Linux】多路转接poll、epoll
linux·服务器
跃渊Yuey2 小时前
【Linux】Linux进程信号产生和保存
linux·c语言·c++·vscode
CaspianSea2 小时前
清理 Ubuntu里不需要的文件
linux·运维·ubuntu
c++逐梦人2 小时前
命令⾏参数和环境变量
linux·操作系统·进程
天码-行空3 小时前
达梦数据库(DM8)详细安装教程
linux·运维·数据库
白驹过隙不负青春3 小时前
Centos7开启、关闭swap
linux·centos