swapon/swapoff 函数详解
1. 函数介绍
swapon
和 swapoff
是Linux系统调用,用于管理系统的交换空间(swap space)。交换空间是磁盘上的一块区域,当物理内存不足时,系统会将不常用的内存页移动到交换空间,从而释放物理内存供其他进程使用。
2. 函数原型
#include <sys/swap.h>
int swapon(const char *path, int swapflags);
int swapoff(const char *path);
3. 功能
- swapon: 启用指定的交换空间(文件或设备)
- swapoff: 禁用指定的交换空间
4. 参数
- *const char path: 交换文件或设备的路径
- int swapflags: swapon的标志位(通常为0)
5. 返回值
- 成功: 返回0
- 失败: 返回-1,并设置errno
6. 相似函数,或关联函数
- swapctl: 更通用的交换控制接口
- mkswap: 创建交换空间
- /proc/swaps: 交换空间信息文件
- free: 显示内存使用情况
7. 示例代码
示例1:基础swapon/swapoff使用
#include <sys/swap.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
/**
* 显示当前交换空间信息
*/
void show_swap_info() {
FILE *fp;
char line[256];
printf("=== 当前交换空间信息 ===\n");
fp = fopen("/proc/swaps", "r");
if (fp) {
printf("交换空间列表:\n");
while (fgets(line, sizeof(line), fp)) {
printf(" %s", line);
}
fclose(fp);
} else {
printf("无法读取交换空间信息: %s\n", strerror(errno));
}
printf("\n内存使用情况:\n");
system("free -h");
printf("\n");
}
/**
* 创建交换文件
*/
int create_swap_file(const char *filename, size_t size_mb) {
int fd;
char *buffer;
size_t chunk_size = 1024 * 1024; // 1MB chunks
size_t written = 0;
printf("创建交换文件: %s (%zu MB)\n", filename, size_mb);
// 创建文件
fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0600);
if (fd == -1) {
perror("创建交换文件失败");
return -1;
}
// 设置文件大小
if (ftruncate(fd, size_mb * 1024 * 1024) == -1) {
perror("设置文件大小失败");
close(fd);
unlink(filename);
return -1;
}
// 可选:填充文件内容(对于某些文件系统可能需要)
buffer = malloc(chunk_size);
if (buffer) {
memset(buffer, 0, chunk_size);
// 写入一些数据以确保文件分配
ssize_t result = write(fd, buffer, chunk_size);
if (result == -1) {
perror("写入文件失败");
}
free(buffer);
}
close(fd);
// 创建交换空间
printf("初始化交换空间...\n");
char cmd[256];
snprintf(cmd, sizeof(cmd), "mkswap %s", filename);
int result = system(cmd);
if (result != 0) {
printf("创建交换空间失败\n");
unlink(filename);
return -1;
}
printf("交换文件创建成功\n");
return 0;
}
/**
* 演示基础swapon/swapoff使用方法
*/
int demo_swapon_swapoff_basic() {
const char *swap_file = "/tmp/test_swapfile";
const size_t swap_size = 64; // 64MB
int result;
printf("=== 基础swapon/swapoff使用示例 ===\n");
// 检查权限
uid_t uid = getuid();
printf("用户权限检查:\n");
printf(" 当前用户ID: %d\n", uid);
if (uid == 0) {
printf(" ✓ 具有root权限,可以管理交换空间\n");
} else {
printf(" ✗ 没有root权限,交换空间管理将失败\n");
printf(" 注意:swapon/swapoff需要root权限\n");
return 0;
}
// 显示原始交换空间信息
printf("\n1. 原始交换空间信息:\n");
show_swap_info();
// 创建交换文件
printf("2. 创建测试交换文件:\n");
if (create_swap_file(swap_file, swap_size) != 0) {
printf("创建交换文件失败\n");
return -1;
}
// 启用交换文件
printf("3. 启用交换文件:\n");
printf(" 交换文件路径: %s\n", swap_file);
result = swapon(swap_file, 0);
if (result == 0) {
printf(" ✓ 交换文件启用成功\n");
show_swap_info();
} else {
printf(" ✗ 交换文件启用失败: %s\n", strerror(errno));
if (errno == EPERM) {
printf(" 原因:权限不足\n");
} else if (errno == EBUSY) {
printf(" 原因:交换空间已在使用中\n");
} else if (errno == EINVAL) {
printf(" 原因:无效的交换文件\n");
}
unlink(swap_file);
return -1;
}
// 禁用交换文件
printf("4. 禁用交换文件:\n");
result = swapoff(swap_file);
if (result == 0) {
printf(" ✓ 交换文件禁用成功\n");
show_swap_info();
} else {
printf(" ✗ 交换文件禁用失败: %s\n", strerror(errno));
if (errno == EPERM) {
printf(" 原因:权限不足\n");
} else if (errno == EINVAL) {
printf(" 原因:无效的交换文件路径\n");
} else if (errno == EBUSY) {
printf(" 原因:交换空间忙或正在使用\n");
}
}
// 清理测试文件
printf("5. 清理测试文件:\n");
if (unlink(swap_file) == 0) {
printf(" ✓ 测试文件清理成功\n");
} else {
printf(" ✗ 测试文件清理失败: %s\n", strerror(errno));
}
return 0;
}
int main() {
return demo_swapon_swapoff_basic();
}
示例2:交换空间管理工具
#include <sys/swap.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <getopt.h>
/**
* 交换空间条目结构
*/
typedef struct {
char path[256];
long size_kb;
long used_kb;
int priority;
char type[32];
} swap_entry_t;
/**
* 解析交换空间信息
*/
int parse_swap_info(swap_entry_t *entries, int max_entries) {
FILE *fp;
char line[512];
int count = 0;
fp = fopen("/proc/swaps", "r");
if (!fp) {
return -1;
}
// 跳过标题行
fgets(line, sizeof(line), fp);
while (fgets(line, sizeof(line), fp) && count < max_entries) {
char *token;
char *saveptr;
int field = 0;
token = strtok_r(line, " \t\n", &saveptr);
while (token && field < 5) {
switch (field) {
case 0: // Filename
strncpy(entries[count].path, token, sizeof(entries[count].path) - 1);
entries[count].path[sizeof(entries[count].path) - 1] = '\0';
break;
case 1: // Type
strncpy(entries[count].type, token, sizeof(entries[count].type) - 1);
entries[count].type[sizeof(entries[count].type) - 1] = '\0';
break;
case 2: // Size
entries[count].size_kb = atol(token);
break;
case 3: // Used
entries[count].used_kb = atol(token);
break;
case 4: // Priority
entries[count].priority = atoi(token);
break;
}
token = strtok_r(NULL, " \t\n", &saveptr);
field++;
}
if (field >= 4) {
count++;
}
}
fclose(fp);
return count;
}
/**
* 显示详细的交换空间信息
*/
void show_detailed_swap_info() {
swap_entry_t entries[32];
int count = parse_swap_info(entries, 32);
printf("=== 详细交换空间信息 ===\n");
if (count <= 0) {
printf("没有活动的交换空间\n");
return;
}
printf("%-20s %-10s %-12s %-12s %-10s %-8s\n",
"路径", "类型", "大小(MB)", "已用(MB)", "可用(MB)", "优先级");
printf("%-20s %-10s %-12s %-12s %-10s %-8s\n",
"----", "----", "--------", "--------", "--------", "------");
long total_size = 0, total_used = 0;
for (int i = 0; i < count; i++) {
double size_mb = entries[i].size_kb / 1024.0;
double used_mb = entries[i].used_kb / 1024.0;
double free_mb = (entries[i].size_kb - entries[i].used_kb) / 1024.0;
printf("%-20s %-10s %-12.1f %-12.1f %-10.1f %-8d\n",
entries[i].path,
entries[i].type,
size_mb,
used_mb,
free_mb,
entries[i].priority);
total_size += entries[i].size_kb;
total_used += entries[i].used_kb;
}
printf("\n总计:\n");
printf(" 总大小: %.1f MB\n", total_size / 1024.0);
printf(" 已使用: %.1f MB\n", total_used / 1024.0);
printf(" 可用: %.1f MB\n", (total_size - total_used) / 1024.0);
printf(" 使用率: %.1f%%\n",
total_size > 0 ? (total_used * 100.0 / total_size) : 0.0);
}
/**
* 交换空间管理工具
*/
int demo_swap_management_tool() {
const char *test_swap_file = "/tmp/swap_management_test";
uid_t uid = getuid();
printf("=== 交换空间管理工具演示 ===\n");
// 权限检查
printf("权限检查:\n");
printf(" 当前用户ID: %d\n", uid);
if (uid == 0) {
printf(" ✓ 具有root权限\n");
} else {
printf(" ✗ 没有root权限,部分功能将受限\n");
}
// 显示当前交换空间状态
printf("\n1. 当前交换空间状态:\n");
show_detailed_swap_info();
// 如果有root权限,演示创建和管理交换文件
if (uid == 0) {
printf("\n2. 创建测试交换文件:\n");
// 创建小的交换文件用于测试
int fd = open(test_swap_file, O_CREAT | O_WRONLY | O_TRUNC, 0600);
if (fd != -1) {
// 设置文件大小为32MB
if (ftruncate(fd, 32 * 1024 * 1024) == 0) {
close(fd);
// 创建交换空间
char cmd[256];
snprintf(cmd, sizeof(cmd), "mkswap %s >/dev/null 2>&1", test_swap_file);
if (system(cmd) == 0) {
printf(" ✓ 创建交换文件成功: %s\n", test_swap_file);
// 启用交换文件
printf("3. 启用交换文件:\n");
int result = swapon(test_swap_file, 0);
if (result == 0) {
printf(" ✓ 交换文件启用成功\n");
show_detailed_swap_info();
// 禁用交换文件
printf("\n4. 禁用交换文件:\n");
result = swapoff(test_swap_file);
if (result == 0) {
printf(" ✓ 交换文件禁用成功\n");
} else {
printf(" ✗ 交换文件禁用失败: %s\n", strerror(errno));
}
} else {
printf(" ✗ 交换文件启用失败: %s\n", strerror(errno));
}
} else {
printf(" ✗ 初始化交换空间失败\n");
}
} else {
perror(" 设置文件大小失败");
close(fd);
}
// 清理测试文件
unlink(test_swap_file);
} else {
perror(" 创建交换文件失败");
}
}
// 显示交换空间管理建议
printf("\n=== 交换空间管理建议 ===\n");
printf("1. 交换空间大小:\n");
printf(" - 物理内存 < 2GB: 交换空间 = 物理内存 × 2\n");
printf(" - 物理内存 2-8GB: 交换空间 = 物理内存\n");
printf(" - 物理内存 > 8GB: 交换空间 = 4-8GB\n");
printf("\n2. 交换空间类型:\n");
printf(" - 交换分区: 性能更好,推荐用于生产环境\n");
printf(" - 交换文件: 灵活性更好,便于管理\n");
printf("\n3. 优先级设置:\n");
printf(" - 高速设备设置高优先级\n");
printf(" - SSD交换空间优先级高于HDD\n");
printf("\n4. 监控和维护:\n");
printf(" - 定期检查交换空间使用情况\n");
printf(" - 避免交换空间使用率过高\n");
printf(" - 及时清理不需要的交换文件\n");
return 0;
}
int main() {
return demo_swap_management_tool();
}
示例3:动态交换空间管理
#include <sys/swap.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
/**
* 交换空间监控器
*/
typedef struct {
long total_swap_kb;
long used_swap_kb;
double usage_percentage;
time_t last_update;
} swap_monitor_t;
/**
* 获取交换空间使用情况
*/
int get_swap_usage(swap_monitor_t *monitor) {
FILE *fp;
char line[256];
fp = fopen("/proc/meminfo", "r");
if (!fp) {
return -1;
}
long swap_total = 0, swap_free = 0;
while (fgets(line, sizeof(line), fp)) {
if (strncmp(line, "SwapTotal:", 10) == 0) {
sscanf(line + 10, "%ld", &swap_total);
} else if (strncmp(line, "SwapFree:", 9) == 0) {
sscanf(line + 9, "%ld", &swap_free);
}
}
fclose(fp);
monitor->total_swap_kb = swap_total;
monitor->used_swap_kb = swap_total - swap_free;
monitor->usage_percentage = swap_total > 0 ?
(monitor->used_swap_kb * 100.0 / swap_total) : 0.0;
monitor->last_update = time(NULL);
return 0;
}
/**
* 显示交换空间使用情况
*/
void show_swap_usage(const swap_monitor_t *monitor) {
printf("交换空间使用情况:\n");
printf(" 总大小: %.1f MB\n", monitor->total_swap_kb / 1024.0);
printf(" 已使用: %.1f MB\n", monitor->used_swap_kb / 1024.0);
printf(" 可用: %.1f MB\n", (monitor->total_swap_kb - monitor->used_swap_kb) / 1024.0);
printf(" 使用率: %.1f%%\n", monitor->usage_percentage);
char time_str[64];
strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S",
localtime(&monitor->last_update));
printf(" 更新时间: %s\n", time_str);
}
/**
* 动态交换空间管理器
*/
typedef struct {
char swap_file[256];
size_t initial_size_mb;
size_t max_size_mb;
int is_active;
swap_monitor_t monitor;
} dynamic_swap_manager_t;
/**
* 创建动态交换文件
*/
int create_dynamic_swap_file(dynamic_swap_manager_t *manager, size_t size_mb) {
int fd;
printf("创建动态交换文件: %s (%zu MB)\n", manager->swap_file, size_mb);
// 创建文件
fd = open(manager->swap_file, O_CREAT | O_WRONLY | O_TRUNC, 0600);
if (fd == -1) {
perror("创建交换文件失败");
return -1;
}
// 设置文件大小
if (ftruncate(fd, size_mb * 1024 * 1024) == -1) {
perror("设置文件大小失败");
close(fd);
unlink(manager->swap_file);
return -1;
}
close(fd);
// 创建交换空间
char cmd[512];
snprintf(cmd, sizeof(cmd), "mkswap %s >/dev/null 2>&1", manager->swap_file);
if (system(cmd) != 0) {
printf("初始化交换空间失败\n");
unlink(manager->swap_file);
return -1;
}
printf("动态交换文件创建成功\n");
return 0;
}
/**
* 启用动态交换空间
*/
int activate_dynamic_swap(dynamic_swap_manager_t *manager) {
if (manager->is_active) {
printf("交换空间已在使用中\n");
return 0;
}
printf("启用动态交换空间...\n");
int result = swapon(manager->swap_file, 0);
if (result == 0) {
manager->is_active = 1;
printf("✓ 动态交换空间启用成功\n");
return 0;
} else {
printf("✗ 动态交换空间启用失败: %s\n", strerror(errno));
return -1;
}
}
/**
* 禁用动态交换空间
*/
int deactivate_dynamic_swap(dynamic_swap_manager_t *manager) {
if (!manager->is_active) {
printf("交换空间未启用\n");
return 0;
}
printf("禁用动态交换空间...\n");
int result = swapoff(manager->swap_file);
if (result == 0) {
manager->is_active = 0;
printf("✓ 动态交换空间禁用成功\n");
return 0;
} else {
printf("✗ 动态交换空间禁用失败: %s\n", strerror(errno));
return -1;
}
}
/**
* 演示动态交换空间管理
*/
int demo_dynamic_swap_management() {
dynamic_swap_manager_t manager = {0};
uid_t uid = getuid();
printf("=== 动态交换空间管理演示 ===\n");
// 权限检查
if (uid != 0) {
printf("需要root权限来管理交换空间\n");
return 0;
}
// 初始化管理器
strncpy(manager.swap_file, "/tmp/dynamic_swap", sizeof(manager.swap_file) - 1);
manager.initial_size_mb = 64;
manager.max_size_mb = 256;
manager.is_active = 0;
printf("动态交换管理器初始化:\n");
printf(" 交换文件: %s\n", manager.swap_file);
printf(" 初始大小: %zu MB\n", manager.initial_size_mb);
printf(" 最大大小: %zu MB\n", manager.max_size_mb);
// 获取初始交换空间状态
printf("\n1. 初始交换空间状态:\n");
if (get_swap_usage(&manager.monitor) == 0) {
show_swap_usage(&manager.monitor);
}
// 创建并启用动态交换空间
printf("\n2. 创建动态交换空间:\n");
if (create_dynamic_swap_file(&manager, manager.initial_size_mb) != 0) {
printf("创建动态交换空间失败\n");
return -1;
}
printf("\n3. 启用动态交换空间:\n");
if (activate_dynamic_swap(&manager) != 0) {
printf("启用动态交换空间失败\n");
unlink(manager.swap_file);
return -1;
}
// 显示启用后的状态
printf("\n4. 启用后的交换空间状态:\n");
sleep(1); // 等待系统更新状态
if (get_swap_usage(&manager.monitor) == 0) {
show_swap_usage(&manager.monitor);
}
// 模拟监控和调整
printf("\n5. 监控交换空间使用情况:\n");
for (int i = 0; i < 3; i++) {
sleep(2);
if (get_swap_usage(&manager.monitor) == 0) {
printf("监控轮次 %d:\n", i + 1);
show_swap_usage(&manager.monitor);
// 简单的使用率监控逻辑
if (manager.monitor.usage_percentage > 80.0) {
printf(" 警告:交换空间使用率过高 (%.1f%%)\n",
manager.monitor.usage_percentage);
} else if (manager.monitor.usage_percentage > 50.0) {
printf(" 提示:交换空间使用率中等 (%.1f%%)\n",
manager.monitor.usage_percentage);
} else {
printf(" 状态:交换空间使用率正常 (%.1f%%)\n",
manager.monitor.usage_percentage);
}
}
}
// 禁用并清理
printf("\n6. 禁用动态交换空间:\n");
if (deactivate_dynamic_swap(&manager) != 0) {
printf("禁用动态交换空间失败\n");
}
// 显示最终状态
printf("\n7. 最终交换空间状态:\n");
sleep(1); // 等待系统更新状态
if (get_swap_usage(&manager.monitor) == 0) {
show_swap_usage(&manager.monitor);
}
// 清理文件
printf("\n8. 清理交换文件:\n");
if (unlink(manager.swap_file) == 0) {
printf("✓ 交换文件清理成功\n");
} else {
printf("✗ 交换文件清理失败: %s\n", strerror(errno));
}
// 显示管理策略建议
printf("\n=== 动态交换空间管理策略 ===\n");
printf("1. 自动扩展策略:\n");
printf(" - 监控交换空间使用率\n");
printf(" - 使用率 > 80% 时扩展\n");
printf(" - 使用率 < 30% 时收缩\n");
printf("\n2. 性能优化:\n");
printf(" - 使用SSD作为交换空间\n");
printf(" - 设置适当的优先级\n");
printf(" - 避免频繁的启用/禁用操作\n");
printf("\n3. 安全考虑:\n");
printf(" - 交换文件权限设置为600\n");
printf(" - 定期清理临时交换文件\n");
printf(" - 监控异常的交换空间使用\n");
return 0;
}
int main() {
return demo_dynamic_swap_management();
}
示例4:交换空间优先级管理
#include <sys/swap.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
/**
* 交换优先级管理器
*/
typedef struct {
char path[256];
int priority;
int is_active;
} priority_swap_t;
/**
* 创建带优先级的交换文件
*/
int create_priority_swap_file(const char *filename, size_t size_mb, int priority) {
int fd;
printf("创建优先级交换文件: %s (大小: %zu MB, 优先级: %d)\n",
filename, size_mb, priority);
// 创建文件
fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0600);
if (fd == -1) {
perror("创建交换文件失败");
return -1;
}
// 设置文件大小
if (ftruncate(fd, size_mb * 1024 * 1024) == -1) {
perror("设置文件大小失败");
close(fd);
unlink(filename);
return -1;
}
close(fd);
// 创建交换空间
char cmd[512];
snprintf(cmd, sizeof(cmd), "mkswap %s >/dev/null 2>&1", filename);
if (system(cmd) != 0) {
printf("初始化交换空间失败\n");
unlink(filename);
return -1;
}
printf("交换文件创建成功\n");
return 0;
}
/**
* 启用带优先级的交换空间
*/
int activate_priority_swap(const char *filename, int priority) {
printf("启用优先级交换空间: %s (优先级: %d)\n", filename, priority);
// 使用swapflags设置优先级
int swapflags = (priority << 16); // 优先级存储在高16位
int result = swapon(filename, swapflags);
if (result == 0) {
printf("✓ 交换空间启用成功\n");
return 0;
} else {
printf("✗ 交换空间启用失败: %s\n", strerror(errno));
return -1;
}
}
/**
* 演示交换空间优先级管理
*/
int demo_swap_priority_management() {
priority_swap_t swaps[3];
uid_t uid = getuid();
printf("=== 交换空间优先级管理演示 ===\n");
// 权限检查
if (uid != 0) {
printf("需要root权限来管理交换空间\n");
return 0;
}
// 初始化交换空间配置
strncpy(swaps[0].path, "/tmp/priority_swap_high", sizeof(swaps[0].path) - 1);
swaps[0].priority = 10; // 高优先级
swaps[0].is_active = 0;
strncpy(swaps[1].path, "/tmp/priority_swap_medium", sizeof(swaps[1].path) - 1);
swaps[1].priority = 5; // 中优先级
swaps[1].is_active = 0;
strncpy(swaps[2].path, "/tmp/priority_swap_low", sizeof(swaps[2].path) - 1);
swaps[2].priority = 1; // 低优先级
swaps[2].is_active = 0;
printf("交换空间优先级配置:\n");
for (int i = 0; i < 3; i++) {
printf(" %s: 优先级 %d\n", swaps[i].path, swaps[i].priority);
}
// 显示初始交换空间状态
printf("\n1. 初始交换空间状态:\n");
system("cat /proc/swaps");
// 创建交换文件
printf("\n2. 创建交换文件:\n");
for (int i = 0; i < 3; i++) {
size_t size_mb = 32 + i * 16; // 32MB, 48MB, 64MB
if (create_priority_swap_file(swaps[i].path, size_mb, swaps[i].priority) != 0) {
printf("创建交换文件 %s 失败\n", swaps[i].path);
// 清理已创建的文件
for (int j = 0; j < i; j++) {
unlink(swaps[j].path);
}
return -1;
}
}
// 按优先级顺序启用交换空间
printf("\n3. 按优先级启用交换空间:\n");
// 注意:实际的优先级设置可能需要通过命令行参数传递
for (int i = 0; i < 3; i++) {
printf("启用交换空间 %d:\n", i + 1);
// 这里简化处理,实际应用中可能需要更复杂的优先级设置
int result = swapon(swaps[i].path, 0);
if (result == 0) {
swaps[i].is_active = 1;
printf(" ✓ %s 启用成功\n", swaps[i].path);
} else {
printf(" ✗ %s 启用失败: %s\n", swaps[i].path, strerror(errno));
}
}
// 显示启用后的状态
printf("\n4. 启用后的交换空间状态:\n");
system("cat /proc/swaps");
printf("\n交换空间优先级说明:\n");
printf(" - 数值越高优先级越高\n");
printf(" - 高优先级交换空间先被使用\n");
printf(" - 相同优先级的交换空间轮询使用\n");
// 禁用交换空间
printf("\n5. 禁用交换空间:\n");
for (int i = 0; i < 3; i++) {
if (swaps[i].is_active) {
int result = swapoff(swaps[i].path);
if (result == 0) {
swaps[i].is_active = 0;
printf(" ✓ %s 禁用成功\n", swaps[i].path);
} else {
printf(" ✗ %s 禁用失败: %s\n", swaps[i].path, strerror(errno));
}
}
}
// 清理文件
printf("\n6. 清理交换文件:\n");
for (int i = 0; i < 3; i++) {
if (unlink(swaps[i].path) == 0) {
printf(" ✓ %s 清理成功\n", swaps[i].path);
} else {
printf(" ✗ %s 清理失败: %s\n", swaps[i].path, strerror(errno));
}
}
// 显示优先级管理最佳实践
printf("\n=== 交换空间优先级管理最佳实践 ===\n");
printf("1. 优先级设置原则:\n");
printf(" - SSD交换空间设置高优先级\n");
printf(" - 高速磁盘设置中等优先级\n");
printf(" - 低速磁盘设置低优先级\n");
printf("\n2. 负载均衡:\n");
printf(" - 相同类型设备设置相同优先级\n");
printf(" - 实现轮询使用,延长设备寿命\n");
printf("\n3. 性能优化:\n");
printf(" - 避免频繁调整优先级\n");
printf(" - 根据实际性能测试设置\n");
printf(" - 考虑I/O模式和访问模式\n");
return 0;
}
int main() {
return demo_swap_priority_management();
}
示例5:交换空间性能测试
#include <sys/swap.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <sys/resource.h>
/**
* 内存压力测试器
*/
typedef struct {
size_t allocated_memory_mb;
size_t swap_used_mb;
double test_duration_seconds;
int swap_enabled;
} memory_test_result_t;
/**
* 分配内存并测试交换性能
*/
int memory_pressure_test(size_t memory_mb, memory_test_result_t *result) {
char **buffers;
size_t num_buffers = memory_mb / 10; // 每个缓冲区10MB
size_t buffer_size = 10 * 1024 * 1024; // 10MB
struct timespec start, end;
printf("开始内存压力测试: %zu MB\n", memory_mb);
// 记录开始时间
clock_gettime(CLOCK_MONOTONIC, &start);
// 分配内存缓冲区数组
buffers = malloc(num_buffers * sizeof(char*));
if (!buffers) {
printf("分配缓冲区数组失败\n");
return -1;
}
// 逐步分配内存
size_t allocated_buffers = 0;
for (size_t i = 0; i < num_buffers; i++) {
buffers[i] = malloc(buffer_size);
if (buffers[i]) {
// 填充数据以确保内存实际使用
memset(buffers[i], i & 0xFF, buffer_size);
allocated_buffers++;
if (allocated_buffers % 10 == 0) {
printf("已分配 %zu MB 内存\n", allocated_buffers * 10);
}
} else {
printf("内存分配失败在第 %zu 次\n", i + 1);
break;
}
}
// 记录结束时间
clock_gettime(CLOCK_MONOTONIC, &end);
result->allocated_memory_mb = allocated_buffers * 10;
result->test_duration_seconds = (end.tv_sec - start.tv_sec) +
(end.tv_nsec - start.tv_nsec) / 1e9;
printf("内存分配完成: %zu MB, 耗时 %.2f 秒\n",
result->allocated_memory_mb, result->test_duration_seconds);
// 检查交换空间使用情况
FILE *fp = fopen("/proc/meminfo", "r");
if (fp) {
char line[256];
long swap_total = 0, swap_free = 0;
while (fgets(line, sizeof(line), fp)) {
if (strncmp(line, "SwapTotal:", 10) == 0) {
sscanf(line + 10, "%ld", &swap_total);
} else if (strncmp(line, "SwapFree:", 9) == 0) {
sscanf(line + 9, "%ld", &swap_free);
}
}
fclose(fp);
result->swap_used_mb = (swap_total - swap_free) / 1024; // 转换为MB
result->swap_enabled = (swap_total > 0);
}
// 释放内存
for (size_t i = 0; i < allocated_buffers; i++) {
if (buffers[i]) {
free(buffers[i]);
}
}
free(buffers);
return 0;
}
/**
* 演示交换空间性能测试
*/
int demo_swap_performance_test() {
const char *test_swap_file = "/tmp/performance_test_swap";
uid_t uid = getuid();
printf("=== 交换空间性能测试演示 ===\n");
// 权限检查
if (uid != 0) {
printf("需要root权限来管理交换空间\n");
printf("将以普通用户权限进行内存测试\n");
}
// 显示系统内存信息
printf("1. 系统内存信息:\n");
system("free -h");
printf("\n2. 当前交换空间信息:\n");
system("cat /proc/swaps");
// 如果有root权限,创建测试交换空间
if (uid == 0) {
printf("\n3. 创建测试交换空间:\n");
// 创建128MB交换文件
int fd = open(test_swap_file, O_CREAT | O_WRONLY | O_TRUNC, 0600);
if (fd != -1) {
if (ftruncate(fd, 128 * 1024 * 1024) == 0) {
close(fd);
// 创建交换空间
char cmd[256];
snprintf(cmd, sizeof(cmd), "mkswap %s >/dev/null 2>&1", test_swap_file);
if (system(cmd) == 0) {
printf(" ✓ 创建测试交换文件成功\n");
// 启用交换文件
if (swapon(test_swap_file, 0) == 0) {
printf(" ✓ 启用测试交换文件成功\n");
system("cat /proc/swaps");
} else {
printf(" ✗ 启用测试交换文件失败\n");
}
} else {
printf(" ✗ 初始化交换空间失败\n");
close(fd);
unlink(test_swap_file);
}
} else {
perror(" 设置文件大小失败");
close(fd);
unlink(test_swap_file);
}
} else {
perror(" 创建交换文件失败");
}
}
// 进行内存压力测试
printf("\n4. 内存压力测试:\n");
// 测试不同内存大小
size_t test_sizes[] = {100, 200, 300, 400};
int num_tests = sizeof(test_sizes) / sizeof(test_sizes[0]);
for (int i = 0; i < num_tests; i++) {
printf("\n测试 %d: 分配 %zu MB 内存\n", i + 1, test_sizes[i]);
memory_test_result_t result = {0};
if (memory_pressure_test(test_sizes[i], &result) == 0) {
printf(" 测试结果:\n");
printf(" 分配内存: %zu MB\n", result.allocated_memory_mb);
printf(" 测试耗时: %.2f 秒\n", result.test_duration_seconds);
printf(" 交换使用: %zu MB\n", result.swap_used_mb);
printf(" 交换启用: %s\n", result.swap_enabled ? "是" : "否");
if (result.swap_enabled && result.swap_used_mb > 0) {
printf(" ✓ 交换空间正常工作\n");
} else if (result.swap_enabled) {
printf(" 提示:交换空间已启用但未使用\n");
} else {
printf(" 提示:交换空间未启用\n");
}
} else {
printf(" 测试失败\n");
}
// 短暂休息
sleep(2);
}
// 如果创建了测试交换空间,清理它
if (uid == 0) {
printf("\n5. 清理测试交换空间:\n");
// 禁用交换文件
if (swapoff(test_swap_file) == 0) {
printf(" ✓ 禁用测试交换文件成功\n");
} else {
printf(" ✗ 禁用测试交换文件失败: %s\n", strerror(errno));
}
// 删除交换文件
if (unlink(test_swap_file) == 0) {
printf(" ✓ 删除测试交换文件成功\n");
} else {
printf(" ✗ 删除测试交换文件失败: %s\n", strerror(errno));
}
}
// 显示性能测试总结
printf("\n=== 性能测试总结 ===\n");
printf("1. 交换空间性能指标:\n");
printf(" - 交换I/O速度\n");
printf(" - 内存分配延迟\n");
printf(" - 系统响应时间\n");
printf("\n2. 性能优化建议:\n");
printf(" - 使用SSD作为交换空间\n");
printf(" - 合理设置交换空间大小\n");
printf(" - 调整交换倾向参数 (swappiness)\n");
printf("\n3. 监控要点:\n");
printf(" - 交换空间使用率\n");
printf(" - 系统负载情况\n");
printf(" - 内存使用趋势\n");
return 0;
}
int main() {
return demo_swap_performance_test();
}
swapon/swapoff 使用注意事项
系统要求:
- 内核版本: 支持交换空间管理的Linux内核
- 权限要求: 需要root权限
- 架构支持: 支持所有主流架构
文件要求:
- 权限: 交换文件权限必须为600
- 格式: 必须使用mkswap初始化
- 大小: 建议为页面大小的倍数
错误处理:
- EPERM: 权限不足
- EINVAL: 无效参数
- EBUSY: 交换空间正在使用中
- ENOMEM: 内存不足
安全考虑:
- 文件权限: 确保交换文件权限正确
- 数据安全: 交换空间可能包含敏感数据
- 系统稳定性: 不当的交换管理可能影响系统稳定性
最佳实践:
- 权限检查: 执行前检查是否具有足够权限
- 错误处理: 妥善处理各种错误情况
- 资源清理: 及时清理临时交换文件
- 监控管理: 监控交换空间使用情况
- 性能调优: 根据系统特性调整交换策略
交换空间相关常量和参数
交换标志:
// swapon标志(通常为0)
#define SWAP_FLAG_PREFER 0x8000 // 优先使用
#define SWAP_FLAG_DISCARD 0x10000 // 启用discard
系统参数:
// /proc/sys/vm/swappiness (0-100)
// 控制内核使用交换空间的倾向
echo 10 > /proc/sys/vm/swappiness // 降低交换倾向
相关文件和命令
系统文件:
- /proc/swaps: 当前交换空间信息
- /proc/meminfo: 内存使用信息
- /proc/sys/vm/swappiness: 交换倾向参数
相关命令:
# 显示交换空间信息
cat /proc/swaps
swapon --show
# 显示内存使用情况
free -h
cat /proc/meminfo
# 管理交换空间
swapon /swapfile
swapoff /swapfile
mkswap /swapfile
常见使用场景
1. 系统管理:
// 动态添加交换空间以应对内存不足
swapon("/tmp/emergency_swap", 0);
2. 性能调优:
// 为不同存储设备设置不同的交换优先级
swapon("/dev/ssd_swap", priority << 16);
3. 资源监控:
// 监控交换空间使用情况并动态调整
if (swap_usage > 90%) {
// 添加更多交换空间
swapon("/tmp/additional_swap", 0);
}
总结
swapon
和 swapoff
是Linux系统中重要的内存管理函数,提供了:
- 动态管理: 可以动态启用和禁用交换空间
- 灵活配置: 支持不同的交换文件和设备
- 优先级控制: 可以设置交换空间的使用优先级
- 系统集成: 与Linux内核深度集成
通过合理使用这些函数,可以构建灵活的内存管理系统,提高系统的稳定性和性能。在实际应用中,需要注意权限要求、错误处理和系统稳定性等关键问题。