在Linux内核中,匿名页(Anonymous Page)指的是没有与具体文件系统中的文件关联的内存页。这种内存通常用于存储动态分配的数据,如进程的堆、栈以及使用mmap
创建的匿名内存区域。
设计匿名页的原因
- 动态内存分配:许多应用程序在运行时需要动态分配内存,匿名页提供了一种简单的方式来满足这些需求,而无需在文件系统中创建相应的文件。
- 内存保护:匿名页允许操作系统为每个进程提供独立的内存空间,保护各个进程之间的内存不被直接访问。
- 简化I/O:对于不需要持久存储的内存,匿名页可以减少文件I/O的开销,提高内存访问的效率。
使用场景和作用
- 进程堆和栈:大多数应用程序在运行时会使用堆和栈来存储局部变量、对象等,匿名页为这些内存提供了支持。
- 共享内存:通过使用
shmget
或mmap
创建的匿名共享内存区域,进程可以有效地进行进程间通信(IPC)。 - 内存映射文件:当使用
mmap
映射一个文件但不希望文件内容影响内存(如执行代码或共享数据时),匿名页可以作为虚拟内存的一部分。 - 页面替换:在内存压力大的情况下,匿名页可以被交换到磁盘,以释放内存给其他进程。
总之,匿名页在动态内存管理和进程间通信中起着重要作用,为操作系统提供了灵活且高效的内存使用方式。
这是一个使用匿名页的例子:
#include <stdio.h>
#include <stdlib.h>
int main() {
// 动态分配内存
size_t size = 1024 * 1024 * 1024; // 分配1GB
void *ptr = malloc(size);
if (ptr == NULL) {
perror("malloc failed");
return 1;
}
// 使用分配的内存
for (size_t i = 0; i < size; i++) {
((char *)ptr)[i] = 'A'; // 填充内存
}
// 打印前10个字节
printf("First 10 bytes: ");
for (size_t i = 0; i < 10; i++) {
printf("%c ", ((char *)ptr)[i]);
}
printf("\n");
// 释放内存
free(ptr);
return 0;
}
程序执行之前:
# cat /proc/meminfo
MemTotal: 395115492 kB
MemFree: 374575448 kB
MemAvailable: 390520104 kB
Buffers: 574264 kB
Cached: 17450828 kB
SwapCached: 0 kB
Active: 2003164 kB
Inactive: 16358148 kB
Active(anon): 13036 kB
Inactive(anon): 365072 kB
Active(file): 1990128 kB
Inactive(file): 15993076 kB
Unevictable: 11188 kB
Mlocked: 11188 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Dirty: 92 kB
Writeback: 0 kB
AnonPages: 309404 kB
程序执行中:
# cat /proc/meminfo
MemTotal: 395115492 kB
MemFree: 373975116 kB
MemAvailable: 389919816 kB
Buffers: 574300 kB
Cached: 17450832 kB
SwapCached: 0 kB
Active: 2003208 kB
Inactive: 16960956 kB
Active(anon): 13040 kB
Inactive(anon): 967876 kB
Active(file): 1990168 kB
Inactive(file): 15993080 kB
Unevictable: 11188 kB
Mlocked: 11188 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Dirty: 12 kB
Writeback: 0 kB
AnonPages: 923592 kB
通过比较这两份/proc/meminfo
的输出,我们可以看到内存使用情况的变化,特别是关于匿名页(Active(anon)
、Inactive(anon)
和AnonPages
)的部分。
总体内存信息
- MemTotal: 总内存量未变化,依然是395115492 kB。
- MemFree: 从374575448 kB减少到373975116 kB,表示空闲内存减少。
- MemAvailable: 从390520104 kB减少到389919816 kB,表示可用内存也减少。
- Buffers 和 Cached: 这两项变化不大,表明文件系统缓存和缓冲区的使用相对稳定。
具体变化分析
- Active(anon):
- 从13036 kB增加到13040 kB,表示活跃的匿名页略有增加。这通常是由于有新的匿名内存被分配并被使用。
- Inactive(anon):
- 从365072 kB增加到967876 kB,表示闲置的匿名页显著增加。这意味着之前有一些匿名页不再被活动进程使用,因此变得不活跃。这可能是因为某些进程释放了动态分配的内存,或者某些进程终止后其内存被标记为不活跃。
- AnonPages:
- 从309404 kB增加到923592 kB,表示匿名页的总量显著增加。这表明系统在这段时间内分配了大量新的匿名内存。从这里我们可以得知,匿名内存增加了600MB,这与我们实际分配的1GB有区别。
总结
- 整体内存使用中,虽然空闲和可用内存有所减少,但活跃的匿名页变化不大。
- 但有相当数量的匿名页变为不活跃,并且
AnonPages
的数量大幅增加,这表明有新的匿名内存分配(如通过malloc
、mmap
等动态分配方式)。 - 这可能是因为某些应用程序在这段时间内增加了内存使用(如加载新的数据或对象),或者一些进程使用了新的动态内存。
总体来看,这些变化反映了系统在处理内存请求和动态内存分配时的状态,尤其是与匿名页相关的内存动态变化。
这是一个不使用匿名页的例子:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
int main() {
const char *filename = "example.txt";
// 打开文件
int fd = open(filename, O_RDONLY);
if (fd == -1) {
perror("open failed");
return 1;
}
// 获取文件大小
off_t filesize = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET); // 重置文件指针
// 映射文件到内存
char *mapped = mmap(NULL, filesize, PROT_READ, MAP_PRIVATE, fd, 0);
if (mapped == MAP_FAILED) {
perror("mmap failed");
close(fd);
return 1;
}
// 使用映射的内容
printf("File contents:\n");
write(STDOUT_FILENO, mapped, filesize); // 输出文件内容
// 解除映射
if (munmap(mapped, filesize) == -1) {
perror("munmap failed");
}
// 关闭文件
close(fd);
return 0;
}
程序执行前:
# cat /proc/meminfo
MemTotal: 395115492 kB
MemFree: 374571060 kB
MemAvailable: 390518552 kB
Buffers: 576640 kB
Cached: 17451112 kB
SwapCached: 0 kB
Active: 2011892 kB
Inactive: 16351760 kB
Active(anon): 19356 kB
Inactive(anon): 358420 kB
Active(file): 1992536 kB
Inactive(file): 15993340 kB
Unevictable: 11188 kB
Mlocked: 11188 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Dirty: 84 kB
Writeback: 0 kB
AnonPages: 301836 kB
程序执行中:
# cat /proc/meminfo
MemTotal: 395115492 kB
MemFree: 374571084 kB
MemAvailable: 390518584 kB
Buffers: 576648 kB
Cached: 17451112 kB
SwapCached: 0 kB
Active: 2011904 kB
Inactive: 16352272 kB
Active(anon): 19360 kB
Inactive(anon): 358932 kB
Active(file): 1992544 kB
Inactive(file): 15993340 kB
Unevictable: 11188 kB
Mlocked: 11188 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Dirty: 92 kB
Writeback: 0 kB
AnonPages: 302380 kB
可以看到程序执行前和执行中的匿名内存几乎没有变化。