我无法理解Linux中的内存映射页面和匿名页面。 有人可以用一个例子来解释吗? 什么是与他们有关的内核数据结构?
正确的术语是内存映射文件和匿名映射。 当提到内存映射时,通常是指mmap(2)。 有2类使用mmap。 一个类别是共享与私有映射。 另一类是FILE与ANONYMOUS的映射。 混合在一起,你会得到以下4种组合:
文件映射指定一个文件,在磁盘上,将有N个字节映射到内存中。 函数mmap(2)将第四个参数作为文件描述符映射到内存中。 第五个参数是要读入的字节数,作为偏移量。 使用mmap创建内存映射文件的典型过程如下
当一个文件被映射为PRIVATE时,所做的更改不会被提交到底层文件。 这是一个私人的,在内存中的文件副本。 当一个文件被映射SHARED时,所做的更改将被内核自动提交到底层文件。 映射为共享的文件可用于所谓的内存映射I / O和IPC。 如果您需要文件的持久性,您将使用IPC的内存映射文件而不是共享内存段
如果你使用strace(1)来观察一个进程的初始化,你会注意到文件的不同部分被映射为使用mmap(2)作为私有文件映射。 系统库也是如此。
strace(1)的输出示例,其中mmap(2)正被用于在库中映射到进程。
open("/etc/ld.so.cache", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=42238, ...}) = 0 mmap(NULL, 42238, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ff7ca71e000 close(3) = 0 open("/lib64/libc.so.6", O_RDONLY) = 3 read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p\356\341n8\0\0\0"..., 832) = 832 fstat(3, {st_mode=S_IFREG|0755, st_size=1926760, ...}) = 0 mmap(0x386ee00000, 3750152, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x386ee00000
匿名映射不支持文件。 具体地说,当MAP_ANONYMOUS标志被用作mmap(2)的第三个参数时,mmap(2)的第四个(文件描述符)和第五个(偏移量)参数甚至不被使用。 使用MAP_ANONYMOUS标志的替代方法是使用/ dev / zero作为文件。
对我而言,“匿名”这个词是一个糟糕的选择,因为听起来好像该文件是匿名映射的。 相反,这是匿名的文件,即。 没有指定的文件。
私人匿名映射的用途很少在用户的土地编程。 您可以使用共享的匿名映射,以便应用程序可以共享内存区域,但是我不知道为什么不使用SYSV或POSIX共享内存的原因。
由于使用匿名映射映射的内存保证为零填充,所以对于某些希望/要求填充的内存区域以这种方式使用mmap(2)而不是malloc(2)+ memset(2)的应用程序)组合。
据我所知,匿名页面是这样命名的,因为他们没有命名的文件系统源,而映射的页面是具体文件的映射。 例如,您可以在任何用户空间进程中使用简单的malloc操作来获取anonymos页面…
关于内核结构:显然它是结构页面 ,但是在anonymos页面的情况下,您将具有坐在页面 – >映射中的anon_vma结构 ,以及映射页面中的结构address_space ,它与具体的inode连接。
匿名内存是一个没有文件或设备支持的内存映射。 这是程序如何从操作系统分配内存以供堆栈和堆等使用。
最初,匿名映射只分配虚拟内存。 新的映射在零页的写映射上以冗余副本开始。 匿名映射的每个虚拟页面都附加到这个现有的prezeroed页面,所以即使没有新的物理内存分配给它,尝试从映射中的任何位置读取也会返回归零内存。