低版本内核与高版本内核__zone_watermark_ok函数的变化

机缘巧合,最近研究了一下linux内核__zone_watermark_ok函数,发现高版本(4.4)和低版本3.14之前有所区别,特此记录一下。
先上3.14版本的代码

/*
 * Return true if free pages are above 'mark'. This takes into account the order
 * of the allocation.
 */
static bool __zone_watermark_ok(struct zone *z, unsigned int order,
			unsigned long mark, int classzone_idx, int alloc_flags,
			long free_pages)
{
	/* free_pages my go negative - that's OK */
	long min = mark;
	int o;
	long free_cma = 0;

	free_pages -= (1 << order) - 1;
	if (alloc_flags & ALLOC_HIGH)
		min -= min / 2;
	if (alloc_flags & ALLOC_HARDER)
		min -= min / 4;

首先根据传进来的标志位判断是否要将水线降低,然后进行第一次水线判断

#ifdef CONFIG_CMA
	/* If allocation can't use CMA areas don't use free CMA pages */
	if (!(alloc_flags & ALLOC_CMA))
		free_cma = zone_page_state(z, NR_FREE_CMA_PAGES);
#endif

	if (free_pages - free_cma <= min + z->lowmem_reserve[classzone_idx])
		return false;

使用空闲page总数去比较水线与保留内存的和,如果空闲内存较小,返回false,表示内存水位不足。
若第一次水线判断成功,接下来进行第二次判断:

	for (o = 0; o < order; o++) {
		/* At the next order, this order's pages become unavailable */
		free_pages -= z->free_area[o].nr_free << o;

		/* Require fewer higher order pages to be free */
		min >>= 1;

		if (free_pages <= min)
			return false;
	}
	return true;
}

这个代码一开始看的一脸懵逼,仔细一看,就是在比较free_pages和min变量的值。
每次for循环,都做一次如下操作:
将free_pages减去对应阶数的内存空闲数,并且,将水线降低一半,然后比较二者的大小。
在内存碎片化严重的时候,完全可能出现如下图所示情况,即使空闲内存足够,也会导致水线判断失败
在这里插入图片描述
下面上4.4的代码,4.4的代码和3.14只有最后面部分不同。

/* If this is an order-0 request then the watermark is fine */
	if (!order)
		return true;

	/* For a high-order request, check at least one suitable page is free */
	for (o = order; o < MAX_ORDER; o++) {
		struct free_area *area = &z->free_area[o];
		int mt;

		if (!area->nr_free)
			continue;

		for (mt = 0; mt < MIGRATE_PCPTYPES; mt++) {
			if (!list_empty(&area->free_list[mt]))
				return true;
		}

#ifdef CONFIG_CMA
		if ((alloc_flags & ALLOC_CMA) &&
		    !list_empty(&area->free_list[MIGRATE_CMA])) {
			return true;
		}
#endif
		if (alloc_harder &&
			!list_empty(&area->free_list[MIGRATE_HIGHATOMIC]))
			return true;
	}
	return false;

首先多了一个判断点,如果申请的order是0,直接返回true。
接下来的循环中,循环体内并不是像3.14一样做减法然后判断,且for循环的起始和终止条件也变了。循环从o=order开始到MAX_ORDER,判断该阶的空闲内存中是否有buddy块,有的话,返回true。这样看起来,好像合理了些~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值