Linux 内核中folio简介
folio
一词源自拉丁语,意为“纸张”或“页”。在计算机科学和内核开发领域,这个术语被用来形象地描述页面的集合,尤其是在文件系统和内存管理中。在传统书籍和文档中,多个页(或纸张)被折叠成一个 folio
,以便于组织和管理。同样,在内核中,folio
将多个连续的物理页面聚合在一起,提供了一种更高效的内存管理方式,反映了其将多个页面作为一个逻辑单元进行处理的特性。
Linux 内核中的 folio
在 Linux 内核中,folio
是一种重要的内存管理数据结构,主要用于提高页面管理的效率。
定义
folio
在 Linux 内核中是一种表示页的结构,可以看作是 struct page
的扩展。它能够包含多个连续的物理页面,通常用于支持大页面(如 2MB 或 1GB 的大页)或其他多页操作。
结构体
在内核中,folio
结构体的定义通常如下(以 Linux 5.14 为例):
struct folio {
/* private: don't document the anon union */
union {
struct {
/* public: */
unsigned long flags;
union {
struct list_head lru;
struct {
void *__filler;
unsigned int mlock_count;
};
};
struct address_space *mapping;
pgoff_t index;
void *private;
atomic_t _mapcount;
atomic_t _refcount;
#ifdef CONFIG_MEMCG
unsigned long memcg_data;
#endif
/* private: the union with struct page is transitional */
};
struct page page;
};
union {
struct {
unsigned long _flags_1;
unsigned long _head_1;
unsigned char _folio_dtor;
unsigned char _folio_order;
atomic_t _entire_mapcount;
atomic_t _nr_pages_mapped;
atomic_t _pincount;
#ifdef CONFIG_64BIT
unsigned int _folio_nr_pages;
#endif
};
struct page __page_1;
};
union {
struct {
unsigned long _flags_2;
unsigned long _head_2;
void *_hugetlb_subpool;
void *_hugetlb_cgroup;
void *_hugetlb_cgroup_rsvd;
void *_hugetlb_hwpoison;
};
struct page __page_2;
};
};
主要特点
-
聚合页面:
folio
能够将多个连续的物理页面聚合成一个逻辑单元,这意味着在执行 I/O 操作时,可以一次性处理多个页面,从而减少系统调用的开销。 -
高效的内存管理:通过使用
folio
,内核可以更有效地管理内存。例如,在内存分配和释放时,可以以folio
为单位进行,减少了对单个页面的反复操作。 -
改进的缓存管理:
folio
提供了一种方式来更方便地实现缓存机制,比如在文件系统中,能更好地映射文件的块到内存页。 -
减少锁竞争:在多核处理器架构中,使用
folio
可以减少对单个页面的锁竞争,因为多个线程可以同时操作同一个folio
中的不同页面。
作用
- 文件系统:在文件系统层面,
folio
可用于缓存文件的多个页面,提高文件 I/O 性能。 - 内存映射:在处理内存映射文件时,
folio
能够降低管理开销,使得内存映射操作更高效。 - 页回收:
folio
在页面回收和清理过程中,能够以较大的单位进行管理,减少内存碎片。
与 struct page
的比较
- 单一 vs 聚合:
struct page
通常表示单个物理页面,而folio
可以表示多个连续的页面。 - 性能:
folio
由于其聚合特性,在处理大页面和大量页面时效率更高。 - 复杂性:虽然
folio
提供了更多的功能,但也使得内存管理的复杂性有所增加,因此需要合理使用。
folio
的重要性
folio
是 Linux 内核中一种用于改进内存管理的结构,通过聚合多个页面并提供更高效的操作,帮助内核在处理 I/O 和内存管理时提升性能。它是现代内核设计中重要的组成部分,特别是在处理大规模内存和高并发场景下。
page_folio
的作用
page_folio
是一个宏或函数,通常用于将 struct page
转换为 struct folio
。在 Linux 内核中,struct page
表示一个页的元数据,而 struct folio
是一个更高层次的结构,用于表示一组页(通常是一个页面的集合,尤其是在使用大页面时)。
作用
-
内存管理:
folio
结构可以帮助更高效地管理内存,因为它能够处理多个页面的聚合,以减少管理开销。 -
提高性能:通过将多个页面合并成一个
folio
,可以减少对页面的管理操作,从而提高性能,特别是在涉及大量页面的情况下。 -
简化代码:使用
folio
可以简化一些内存管理的代码逻辑,使得相关操作更容易实现和维护。
使用场景
- 在执行 I/O 操作时,通常会使用
folio
来处理从存储设备读取或写入的数据。 - 在缓存和页面回收策略中,
folio
能够更好地反映内存的使用情况。
总之,page_folio
的主要目的是提供一种方法来从单个页面获取其对应的 folio
,以便利用 folio
的优势进行更高效的内存管理和操作。