Linux 什么是内存映射页和匿名页?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13024087/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What are memory mapped page and anonymous page?
提问by bornfree
I am not able to understand memory mapped page and anonymous page in linux. Can someone please explain it with an example? What are the kernel data structures related to them?
我无法理解 linux 中的内存映射页面和匿名页面。有人可以用一个例子解释一下吗?与它们相关的内核数据结构是什么?
采纳答案by typedeaf
The correct terms are memory mapped filesand anonymous mappings. When referring to memory mapping, one is usually referring to mmap(2). There are 2 categories for using mmap. One category is SHARED vs PRIVATE mappings. The other category is FILE vs ANONYMOUS mappings. Mixed together you get the 4 following combinations:
正确的术语是内存映射文件和匿名映射。当提到内存映射时,通常指的是 mmap(2)。使用 mmap 有 2 个类别。一类是共享映射与私有映射。另一个类别是文件与匿名映射。混合在一起,您将获得以下 4 种组合:
- PRIVATE FILE MAPPING
- SHARED FILE MAPPING
- PRIVATE ANONYMOUS MAPPING
- SHARED ANONYMOUS MAPPING
- 私人文件映射
- 共享文件映射
- 私人匿名映射
- 共享匿名映射
A File Mapping specifies a file, on disk, that will have N many bytes mapped into memory. The function mmap(2) takes, as its 4th argument a file descriptor to the file to be mapped into memory. The 5th argument is the number of bytes to be read in, as an offset. The typical process of using mmap to create a memory mapped file goes
文件映射指定磁盘上的文件,该文件将有 N 个字节映射到内存中。函数 mmap(2) 将要映射到内存的文件的文件描述符作为其第四个参数。第 5 个参数是要读入的字节数,作为偏移量。使用 mmap 创建内存映射文件的典型过程是
- open(2) file to get a file descriptor.
- fstat(2) the file to get the size from the file descriptor data structure.
- mmap(2) the file using the file descriptor returned from open(2).
- close(2) the file descriptor.
- do whatever to the memory mapped file.
- open(2) file 获取文件描述符。
- fstat(2) 从文件描述符数据结构中获取文件大小。
- mmap(2) 使用从 open(2) 返回的文件描述符的文件。
- close(2) 文件描述符。
- 对内存映射文件做任何事情。
When a file is mapped in as PRIVATE, changes made are not committed to the underlying file. It is a PRIVATE, in-memory copy of the file. When a file is mapped SHARED, changes made are committed to the underlying file by the kernel automatically. Files mapped in as shared can be used for what is called Memory Mapped I/O, and IPC. You would use a memory mapped file for IPC instead of a shared memory segment if you need the persistence of the file
当文件被映射为 PRIVATE 时,所做的更改不会提交到基础文件。它是文件的私有内存副本。当文件被映射为 SHARED 时,内核会自动将所做的更改提交给底层文件。映射为共享的文件可用于所谓的内存映射 I/O 和 IPC。如果您需要文件的持久性,您可以为 IPC 使用内存映射文件而不是共享内存段
If you use strace(1) to watch a process initialize, you will notice that the different sections of the file are mapped in using mmap(2) as private file mappings. The same is true for system libs.
如果您使用 strace(1) 观察进程初始化,您会注意到文件的不同部分使用 mmap(2) 作为私有文件映射进行映射。系统库也是如此。
Examples of output from strace(1) where mmap(2) is being used to map in libraries to the process.
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, "7ELFfiro@linux-6qg8:~> strace -e mmap,openat ls 2>&1 |grep -A1 libc.so
openat(AT_FDCWD, "/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
mmap(NULL, 3906144, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0)
##代码####代码####代码####代码####代码####代码####代码####代码##>##代码####代码####代码####代码##p61n8##代码####代码####代码##"..., 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
Anonymous mappings are not backed by a file. To be specific, the 4th (file descriptor) and 5th (offset) argument of mmap(2) are not even used when the MAP_ANONYMOUS flag is used as the 3rd argument to mmap(2). An alternative to using the MAP_ANONYMOUS flag is to use /dev/zero as the file.
匿名映射不受文件支持。具体来说,当 MAP_ANONYMOUS 标志用作 mmap(2) 的第三个参数时,甚至不使用 mmap(2) 的第 4 个(文件描述符)和第 5 个(偏移量)参数。使用 MAP_ANONYMOUS 标志的替代方法是使用 /dev/zero 作为文件。
The word 'Anonymous' is, to me, a poor choice in that it sounds as if the file is mapped anonymously. Instead, it is the file that is anonymous, ie. there isn't a file specified.
“匿名”这个词对我来说是一个糟糕的选择,因为它听起来好像文件是匿名映射的。相反,它是匿名的文件,即。没有指定文件。
Uses for private anonymous mappings are few in user land programming. You could use a shared anonymous mapping so that applications could share a region of memory, but I do not know the reason why you wouldn't use SYSV or POSIX shared memory instead.
在用户域编程中很少使用私有匿名映射。您可以使用共享匿名映射,以便应用程序可以共享内存区域,但我不知道为什么不使用 SYSV 或 POSIX 共享内存。
Since memory mapped in using Anonymous mappings is guaranteed to be zero filled, it could be useful for some applications that expect/require zero filled regions of memory to use mmap(2) in this way instead of the malloc(2) + memset(2) combo.
由于使用匿名映射映射的内存保证为零填充,因此对于某些期望/需要零填充内存区域的应用程序以这种方式使用 mmap(2) 而不是 malloc(2) + memset(2) 可能很有用) 组合。
回答by Alex Hoppus
As i understand anonymous pages is so named, because they have no named filesystem source, while mapped pages is a mapping of concrete file. For example you can get anonymos pages using a simple malloc operation in any userspace process...
据我所知,匿名页面之所以如此命名,是因为它们没有命名的文件系统源,而映射页面是具体文件的映射。例如,您可以在任何用户空间进程中使用简单的 malloc 操作获取匿名页面...
About kernel structures: Obviously it is struct page, but in case of the anonymos pages you will have struct anon_vmasitting in page->mapping, and in case of mapped pages - struct address_space, which is connected with concrete inode.
关于内核结构:显然它是struct page,但是在匿名页面的情况下,您将struct anon_vma位于 page->mapping 中,并且在映射页面的情况下 - struct address_space,它与具体的 inode 连接。
回答by firo
I am not sure what memory mapped page means? So I am not going to talk about it.
我不确定内存映射页面是什么意思?所以我不打算谈论它。
Regarding anonymous pages, it's usually referred when kernel does page frame reclamation. Instances of anonymous pages include process's stack, heap, shared memory, and any modified shared libraries. In Linux, all dynamic shared libraries are mapped to a process's virtual memory address space through a system call like the following:
关于匿名页面,通常在内核进行页框回收时引用。匿名页面的实例包括进程的堆栈、堆、共享内存和任何修改过的共享库。在 Linux 中,所有动态共享库都通过如下系统调用映射到进程的虚拟内存地址空间:
##代码##Any write on the page which belongs to MAP_PRIVATEed files/libraries will trigger a changing from file-backend page to anonymous page.
属于 MAP_PRIVATEed 文件/库的页面上的任何写入都将触发从文件后端页面到匿名页面的更改。
By definition, the anonymous page, also called anonymous memory, is just a kind of page which doesn't have backend device to be swapped to when kernel does page frame reclamation. That is the reason why Linux supports swap area.
根据定义,匿名页面,也称为匿名内存,只是一种在内核进行页框回收时没有后端设备可以交换到的页面。这就是 Linux 支持交换区的原因。
There are two kinds of kernel data structures relating to anonymous pages.
有两种与匿名页面相关的内核数据结构。
In order to reclaim an anonymous page, kernel have to know all the processes which are using the anonymous page for changing their PTEs(Page table entry). We call this as reverse mapping or rmap.
struct address_space is used by shared memory to maintain the reverse mapping.
struct anon_vma is used by rest of anonymous pages to maintain the reverse mapping.
Kernel uses LRU algorithm to reclaim page frame. For kernel 5.0+, check struct lruvec in struct pglist_data
为了回收匿名页面,内核必须知道所有使用匿名页面来更改其 PTE(页表条目)的进程。我们称之为反向映射或 rmap。
struct address_space 被共享内存用来维护反向映射。
其余匿名页面使用 struct anon_vma 来维护反向映射。
内核使用 LRU 算法回收页框。对于内核 5.0+,检查 struct pglist_data 中的 struct lruvec