swapon-off系统调用及示例

swapon/swapoff 函数详解

  1. 函数介绍

swapon 和 swapoff 是Linux系统调用,用于管理系统的交换空间(swap space)。交换空间是磁盘上的一块区域,当物理内存不足时,系统会将不常用的内存页移动到交换空间,从而释放物理内存供其他进程使用。

  1. 函数原型
1
2
3
4
5
#include <sys/swap.h>

int swapon(const char *path, int swapflags);
int swapoff(const char *path);

  1. 功能
  • swapon: 启用指定的交换空间(文件或设备)

  • swapoff: 禁用指定的交换空间

  1. 参数
  • *const char path: 交换文件或设备的路径

  • int swapflags: swapon的标志位(通常为0)

  1. 返回值
  • 成功: 返回0

  • 失败: 返回-1,并设置errno

  1. 相似函数,或关联函数
  • swapctl: 更通用的交换控制接口

  • mkswap: 创建交换空间

  • /proc/swaps: 交换空间信息文件

  • free: 显示内存使用情况

  1. 示例代码

示例1:基础swapon/swapoff使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#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&#91;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&#91;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:交换空间管理工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
#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&#91;256];
long size_kb;
long used_kb;
int priority;
char type&#91;32];
} swap_entry_t;

/**
* 解析交换空间信息
*/
int parse_swap_info(swap_entry_t *entries, int max_entries) {
FILE *fp;
char line&#91;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&#91;count].path, token, sizeof(entries&#91;count].path) - 1);
entries&#91;count].path&#91;sizeof(entries&#91;count].path) - 1] = '\0';
break;
case 1: // Type
strncpy(entries&#91;count].type, token, sizeof(entries&#91;count].type) - 1);
entries&#91;count].type&#91;sizeof(entries&#91;count].type) - 1] = '\0';
break;
case 2: // Size
entries&#91;count].size_kb = atol(token);
break;
case 3: // Used
entries&#91;count].used_kb = atol(token);
break;
case 4: // Priority
entries&#91;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&#91;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&#91;i].size_kb / 1024.0;
double used_mb = entries&#91;i].used_kb / 1024.0;
double free_mb = (entries&#91;i].size_kb - entries&#91;i].used_kb) / 1024.0;

printf("%-20s %-10s %-12.1f %-12.1f %-10.1f %-8d\n",
entries&#91;i].path,
entries&#91;i].type,
size_mb,
used_mb,
free_mb,
entries&#91;i].priority);

total_size += entries&#91;i].size_kb;
total_used += entries&#91;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&#91;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:动态交换空间管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
#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&#91;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&#91;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&#91;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&#91;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:交换空间优先级管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#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&#91;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&#91;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&#91;3];
uid_t uid = getuid();

printf("=== 交换空间优先级管理演示 ===\n");

// 权限检查
if (uid != 0) {
printf("需要root权限来管理交换空间\n");
return 0;
}

// 初始化交换空间配置
strncpy(swaps&#91;0].path, "/tmp/priority_swap_high", sizeof(swaps&#91;0].path) - 1);
swaps&#91;0].priority = 10; // 高优先级
swaps&#91;0].is_active = 0;

strncpy(swaps&#91;1].path, "/tmp/priority_swap_medium", sizeof(swaps&#91;1].path) - 1);
swaps&#91;1].priority = 5; // 中优先级
swaps&#91;1].is_active = 0;

strncpy(swaps&#91;2].path, "/tmp/priority_swap_low", sizeof(swaps&#91;2].path) - 1);
swaps&#91;2].priority = 1; // 低优先级
swaps&#91;2].is_active = 0;

printf("交换空间优先级配置:\n");
for (int i = 0; i < 3; i++) {
printf(" %s: 优先级 %d\n", swaps&#91;i].path, swaps&#91;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&#91;i].path, size_mb, swaps&#91;i].priority) != 0) {
printf("创建交换文件 %s 失败\n", swaps&#91;i].path);
// 清理已创建的文件
for (int j = 0; j < i; j++) {
unlink(swaps&#91;j].path);
}
return -1;
}
}

// 按优先级顺序启用交换空间
printf("\n3. 按优先级启用交换空间:\n");
// 注意:实际的优先级设置可能需要通过命令行参数传递
for (int i = 0; i < 3; i++) {
printf("启用交换空间 %d:\n", i + 1);
// 这里简化处理,实际应用中可能需要更复杂的优先级设置
int result = swapon(swaps&#91;i].path, 0);
if (result == 0) {
swaps&#91;i].is_active = 1;
printf(" ✓ %s 启用成功\n", swaps&#91;i].path);
} else {
printf(" ✗ %s 启用失败: %s\n", swaps&#91;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&#91;i].is_active) {
int result = swapoff(swaps&#91;i].path);
if (result == 0) {
swaps&#91;i].is_active = 0;
printf(" ✓ %s 禁用成功\n", swaps&#91;i].path);
} else {
printf(" ✗ %s 禁用失败: %s\n", swaps&#91;i].path, strerror(errno));
}
}
}

// 清理文件
printf("\n6. 清理交换文件:\n");
for (int i = 0; i < 3; i++) {
if (unlink(swaps&#91;i].path) == 0) {
printf(" ✓ %s 清理成功\n", swaps&#91;i].path);
} else {
printf(" ✗ %s 清理失败: %s\n", swaps&#91;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:交换空间性能测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
#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&#91;i] = malloc(buffer_size);
if (buffers&#91;i]) {
// 填充数据以确保内存实际使用
memset(buffers&#91;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&#91;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&#91;i]) {
free(buffers&#91;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&#91;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&#91;] = {100, 200, 300, 400};
int num_tests = sizeof(test_sizes) / sizeof(test_sizes&#91;0]);

for (int i = 0; i < num_tests; i++) {
printf("\n测试 %d: 分配 %zu MB 内存\n", i + 1, test_sizes&#91;i]);

memory_test_result_t result = {0};
if (memory_pressure_test(test_sizes&#91;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内核

data-ad-format="fluid" data-ad-layout-key="-7k+ex-4a-9w+4a">

权限要求: 需要root权限

架构支持: 支持所有主流架构

文件要求:

权限: 交换文件权限必须为600

格式: 必须使用mkswap初始化

大小: 建议为页面大小的倍数

错误处理:

EPERM: 权限不足

EINVAL: 无效参数

EBUSY: 交换空间正在使用中

ENOMEM: 内存不足

安全考虑:

文件权限: 确保交换文件权限正确

数据安全: 交换空间可能包含敏感数据

系统稳定性: 不当的交换管理可能影响系统稳定性

最佳实践:

权限检查: 执行前检查是否具有足够权限

错误处理: 妥善处理各种错误情况

资源清理: 及时清理临时交换文件

监控管理: 监控交换空间使用情况

性能调优: 根据系统特性调整交换策略

交换空间相关常量和参数

交换标志:

1
2
3
4
// swapon标志(通常为0)
#define SWAP_FLAG_PREFER 0x8000 // 优先使用
#define SWAP_FLAG_DISCARD 0x10000 // 启用discard

系统参数:

1
2
3
4
// /proc/sys/vm/swappiness (0-100)
// 控制内核使用交换空间的倾向
echo 10 > /proc/sys/vm/swappiness // 降低交换倾向

相关文件和命令

系统文件:

  • /proc/swaps: 当前交换空间信息

  • /proc/meminfo: 内存使用信息

  • /proc/sys/vm/swappiness: 交换倾向参数

相关命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 显示交换空间信息
cat /proc/swaps
swapon --show

# 显示内存使用情况
free -h
cat /proc/meminfo

# 管理交换空间
swapon /swapfile
swapoff /swapfile
mkswap /swapfile

常见使用场景

1. 系统管理:

1
2
3
// 动态添加交换空间以应对内存不足
swapon("/tmp/emergency_swap", 0);

2. 性能调优:

1
2
3
// 为不同存储设备设置不同的交换优先级
swapon("/dev/ssd_swap", priority << 16);

3. 资源监控:

1
2
3
4
5
6
// 监控交换空间使用情况并动态调整
if (swap_usage > 90%) {
// 添加更多交换空间
swapon("/tmp/additional_swap", 0);
}

总结

swapon 和 swapoff 是Linux系统中重要的内存管理函数,提供了:

动态管理: 可以动态启用和禁用交换空间

灵活配置: 支持不同的交换文件和设备

优先级控制: 可以设置交换空间的使用优先级

系统集成: 与Linux内核深度集成

通过合理使用这些函数,可以构建灵活的内存管理系统,提高系统的稳定性和性能。在实际应用中,需要注意权限要求、错误处理和系统稳定性等关键问题。

data-ad-format="auto" data-full-width-responsive="true">