Linux内存管理:(八)页面迁移

本文详细解释了Linux5.0内核中针对不同类型的内存页面(包括LRU和非LRU,如virtio-balloon)的页面迁移机制,涉及migrate_pages函数及其内部unmap_and_move等关键步骤,并展示了源代码中的具体实现和流程.

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章说明:

1. 可迁移页面

页面迁移机制支持两大类内存页面:

  • 传统LRU页面,如匿名页面和文件映射页面
  • 非LRU页面,如zsmalloc或者virtio-balloon页面,以virtio-balloon页面为例,它也有页面迁移的需求,之前的做法是在virtio-balloon驱动中进行迁移操作和相应的逻辑。如果其他的驱动也想做类似的页面迁移,那么它们就不能复用与virtio-balloon驱动相关的代码,必须重新写一套代码,这样会造成很多代码的重复和冗余。为了解决这个问题,内存管理的页面迁移机制提供相应的接口来支持这些非LRU页面的迁移。

2. 页面迁移流程

页面迁移的本质是将页面的内容迁移到新的页面。这个过程中会分配新页面,将旧页面的内容复制到新页面,断开旧页面的映射关系,并把映射关系映射到新页面,最后释放旧页面。页面迁移的整个流程图如下所示:

在这里插入图片描述

为了使读者有更真切的理解,下文将根据流程图围绕源代码进行讲解这个过程。

页面迁移(page migration)在Linux内核的主函数是migrate_pages()函数:

// 页面迁移的主函数
// from: 将要迁移页面的链表
// get_new_page: 申请新内存的页面的函数指针
// put_new_page: 迁移失败时释放目标页面的函数指针
// private: 传递给 get_new_page 的参数
// mode:迁移模式
// reason: 迁移的原因
int migrate_pages(struct list_head *from, new_page_t get_new_page,
		free_page_t put_new_page, unsigned long private,
		enum migrate_mode mode, int reason)
{
   
	...
				rc = unmap_and_move(get_new_page, put_new_page,
						private, page, pass > 2, mode,
						reason);

			....
}

migrate_pages()->unmap_and_move()

static ICE_noinline int unmap_and_move(new_page_t get_new_page,
				   free_page_t put_new_page,
				   unsigned long private, struct page *page,
				   int force, enum migrate_mode mode,
				   enum migrate_reason reason)
{
   
	...

	// 分配一个新的页面
	newpage = get_new_page(page, private);
	if (!newpage)
		return -ENOMEM;

	if (page_count(page) == 1) {
   
		...
		// 刚分配的页面需要调用 put_new_page() 回调函数
		if (put_new_page)
			put_new_page(newpage, private);
		...
	}

	// 尝试迁移页面到新分配的页面中
	rc = __unmap_and_move(page, newpage, force, mode);
	if (rc == MIGRATEPAGE_SUCCESS)
		set_page_owner_migrate_reason(newpage, reason);

out:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值