Linux 内核 - 页面缓存、结构 address_space 和内存 cgroup 之间的关系是什么?
Linux kernel - What is the relationship between page cache, struct address_space, and memory cgroups?
我正在尝试了解 Linux 页面缓存以及它与内存 cgroups (v2) 的关系。我知道使用 cgroupsv1,内存 cgroups 可以 isolated and have independent LRU lists (I assume cgroupsv2 is the same). This and the fact that mm/vmscan.c
has many references to mem_cgroups
and has a function 称为 shrink_node_memcgs
,这让我觉得每个 cgroup 都有自己的页面缓存。 这个假设是否正确?页面缓存中的所有页面都属于一个 cgroup 吗?
如果为真,我知道页面缓存由struct address_space
(here)表示。您如何找出与给定 struct address_space
关联的 cgroup?我是否必须只在 struct address_space
中找到第一页,然后从该页面中找到 cgroup?
经过大量调查,我原来的理解有几个问题。
首先,页面缓存是驻留在内存中的非连续页面的集合。很容易陷入将“页面缓存”视为单个连续 blocks/pages 内存(类似于硬件缓存)的陷阱,但页面缓存只是内存中一些页面的集合可供将来访问。
“页面缓存”中的这些页面实际上并没有存储在一起。如同,内核 doesn't 将页面缓存中的所有页面保存在一个全局结构或列表中。相反,更好的思考方式是页面缓存实际上是内核中所有 LRU 列表的联合。
This and the fact that mm/vmscan.c has many references to mem_cgroups and has a function called shrink_node_memcgs, makes me think that each cgroup has its own page cache.
如前所述,每个 cgroup 都有自己的 LRU 列表。但是,每个 cgroup 都没有自己的页面缓存。但是如果你整理所有 cgroups 的所有 LRU,你将持有页面缓存的所有页面。
I know that a page cache is represented by struct address_space
这是不正确的。 struct address_space
确实代表页面缓存中的一些页面,但它本身并不代表整个页面缓存。 struct address_space
实际上表示来自单个 inode
(文件)或块设备的缓存页面(请参阅原始 post 中链接的 host
member in the address_space
struct). In fact, one 有此引用: "更好的名字 [for struct address_space
] 也许是 page_cache_entity
或 physical_pages_of_a_file。”(pg.327,第 16 章)
How can you find out what cgroup is associated with a given struct address_space?
由于 address_space
对应于单个 inode
(文件)而不是单个 cgroup,因此并非此结构中的所有页面都归入同一个 cgroup 并且因此驻留在相同的 cgroup LRU 列表中。例如,假设 cgroup 1 中的一个进程读取一个大文件的开头,而 cgroup 2 中的另一个进程读取该文件的结尾。每个进程访问的页面来自相同的 inode
和 struct address_space
,但其中一些页面将在 cgroup 1 的 LRU 列表中,而其他页面将在 cgroup 2 中。
因此无法从 struct address_space
中找到 cgroup。相反,理论上,您可以遍历 struct address_space
个页面,然后找到与每个单独页面 (page->mem_cgroup->css.cgroup
) 对应的 cgroup。
请记住,向一个 cgroup 收费的页面可能仍然 shared/accessed 由不同 cgroup 中的另一个进程收费。请在此处查看有关为共享内存向 cgroups 收费的规则 (Section 2.3) and here for v2 ("Memory Ownership")。
附录:
在我的研究过程中,我遇到了 this article,这让我感到困惑,并让我认为 address_space
与单个 cgroup 相关联。图 4.2 使 address_space
看起来像是被埋在 mm_struct
中;并且由于 mm_struct
特定于一个进程,那么这个 address_space
也应该对应于一个进程,并且通过扩展,该进程的 cgroup。实际上,这个mm_struct
对应的进程持有一个文件的文件描述符(用struct file
表示),这个文件描述符导致文件inode
及其对应的address_space
.需要此 address_space
才能在“页面缓存”中专门从该文件中查找页面。
我正在尝试了解 Linux 页面缓存以及它与内存 cgroups (v2) 的关系。我知道使用 cgroupsv1,内存 cgroups 可以 isolated and have independent LRU lists (I assume cgroupsv2 is the same). This and the fact that mm/vmscan.c
has many references to mem_cgroups
and has a function 称为 shrink_node_memcgs
,这让我觉得每个 cgroup 都有自己的页面缓存。 这个假设是否正确?页面缓存中的所有页面都属于一个 cgroup 吗?
如果为真,我知道页面缓存由struct address_space
(here)表示。您如何找出与给定 struct address_space
关联的 cgroup?我是否必须只在 struct address_space
中找到第一页,然后从该页面中找到 cgroup?
经过大量调查,我原来的理解有几个问题。
首先,页面缓存是驻留在内存中的非连续页面的集合。很容易陷入将“页面缓存”视为单个连续 blocks/pages 内存(类似于硬件缓存)的陷阱,但页面缓存只是内存中一些页面的集合可供将来访问。
“页面缓存”中的这些页面实际上并没有存储在一起。如同,内核 doesn't 将页面缓存中的所有页面保存在一个全局结构或列表中。相反,更好的思考方式是页面缓存实际上是内核中所有 LRU 列表的联合。
This and the fact that mm/vmscan.c has many references to mem_cgroups and has a function called shrink_node_memcgs, makes me think that each cgroup has its own page cache.
如前所述,每个 cgroup 都有自己的 LRU 列表。但是,每个 cgroup 都没有自己的页面缓存。但是如果你整理所有 cgroups 的所有 LRU,你将持有页面缓存的所有页面。
I know that a page cache is represented by struct address_space
这是不正确的。 struct address_space
确实代表页面缓存中的一些页面,但它本身并不代表整个页面缓存。 struct address_space
实际上表示来自单个 inode
(文件)或块设备的缓存页面(请参阅原始 post 中链接的 host
member in the address_space
struct). In fact, one 有此引用: "更好的名字 [for struct address_space
] 也许是 page_cache_entity
或 physical_pages_of_a_file。”(pg.327,第 16 章)
How can you find out what cgroup is associated with a given struct address_space?
由于 address_space
对应于单个 inode
(文件)而不是单个 cgroup,因此并非此结构中的所有页面都归入同一个 cgroup 并且因此驻留在相同的 cgroup LRU 列表中。例如,假设 cgroup 1 中的一个进程读取一个大文件的开头,而 cgroup 2 中的另一个进程读取该文件的结尾。每个进程访问的页面来自相同的 inode
和 struct address_space
,但其中一些页面将在 cgroup 1 的 LRU 列表中,而其他页面将在 cgroup 2 中。
因此无法从 struct address_space
中找到 cgroup。相反,理论上,您可以遍历 struct address_space
个页面,然后找到与每个单独页面 (page->mem_cgroup->css.cgroup
) 对应的 cgroup。
请记住,向一个 cgroup 收费的页面可能仍然 shared/accessed 由不同 cgroup 中的另一个进程收费。请在此处查看有关为共享内存向 cgroups 收费的规则 (Section 2.3) and here for v2 ("Memory Ownership")。
附录:
在我的研究过程中,我遇到了 this article,这让我感到困惑,并让我认为 address_space
与单个 cgroup 相关联。图 4.2 使 address_space
看起来像是被埋在 mm_struct
中;并且由于 mm_struct
特定于一个进程,那么这个 address_space
也应该对应于一个进程,并且通过扩展,该进程的 cgroup。实际上,这个mm_struct
对应的进程持有一个文件的文件描述符(用struct file
表示),这个文件描述符导致文件inode
及其对应的address_space
.需要此 address_space
才能在“页面缓存”中专门从该文件中查找页面。