Linux页框分配器之内存碎片化整理
页框分配器在慢速分配中包括内存碎片化整理和内存回收,代码如下:
static inline struct page *
__alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
struct alloc_context *ac)
{
page = __alloc_pages_direct_compact(gfp_mask, order,
alloc_flags, ac,
INIT_COMPACT_PRIORITY,
&compact_result);
......
page = __alloc_pages_direct_reclaim(gfp_mask, order, alloc_flags, ac,
&did_some_progress);
......
}
出于篇幅设计,这次我们只讲内存的碎片化整理,下文再讲内存回收。
什么是内存碎片化
Linux物理内存碎片化包括两种:内部碎片化和外部碎片化。
内部碎片化:
指分配给用户的内存空间中未被使用的部分。例如进程需要使用3K bytes物理内存,于是向系统申请了大小等于3Kbytes的内存,但是由于Linux内核伙伴系统算法最小颗粒是4K bytes,所以分配的是4Kbytes内存,那么其中1K bytes未被使用的内存就是内存内碎片。
外部碎片化:
指系统中无法利用的小内存块。例如系统剩余内存为16K bytes,但是这16K bytes内存是由4个4K bytes的页面组成,即16K内存物理页帧号#1不连续。在系统剩余16K bytes内存的情况下,系统却无法成功分配大于4K的连续物理内存,该情况就是内存外碎片导致。
碎片化整理算法
Linux内存对碎片化的整理算法主要应用了内核的页面迁移机制,是一种将可移动页面进行迁移后腾出连续物理内存的方法。
假设存在一个非常小的内存域如下:蓝色表示空闲的页面,白色表示已经被分配的页面,可以看到如上内存域的空闲页面(蓝色)非常零散,无法分配大于两页的连续物理内存。
下面演示一下内存规整的简化工作原理,内核会运行两个独立的扫描动作:第一个扫描从内存域的底部开始,一边扫描一边将已分配的可移动(MOVABLE)页面记录到一个列表中:另外第二扫描是从内存域的顶部开始,扫描可以作为页面迁移目标的空闲页面位置,然后也记录到一个列表里面:
等两个扫描在域中间相遇,意味着扫描结束,然后将左边扫描得到的已分配的页面迁移到右边空闲的页面中,左边就形成了一段连续的物理内存,完成页面规整。
碎片化整理的三种方式
static struct page *
__alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,
unsigned int alloc_flags, const struct alloc_context *ac,
enum compact_priority prio, enum compact_result *compact_result)
{
struct page *page;
unsigned int noreclaim_flag;
if (!order)
return NULL;
noreclaim_flag = memalloc_noreclaim_save();
*compact_result = try_to_compact_pages(gfp_mask, order, alloc_flags, ac,
prio);
memalloc_noreclaim_restore(noreclaim_flag);
if (*compact_result <= COMPACT_INACTIVE)
return NULL;
count_vm_event(COMPACTSTALL);
page = get_page_from_freelist(gfp_mask, order, alloc_flags, ac);
if (page) {
struct zone *zone = page_zone(page);
zone->compact_blockskip_flush = false;
compaction_defer_reset(zone, order, true);
count_vm_event(COMPACTSUCCESS);
return page;
}
count_vm_event(COMPACTFAIL);
cond_resched();
return NULL;
}
这也是上面memory compaction算法的代码实现。
在linux内核里一共有3种方式可以碎片化整理,我们总结如下:
这里就不展开源码的解析了,有了宏观的理解然后再去网上搜下具体实现细节相信不是什么难事,OK,我们进入下面的文章内容:内存回收(memory reclaim)。
本文分享自微信公众号 - 人人都是极客(rrgeek)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
爱奇艺号基于Prometheus的微服务应用监控实践
前 言 微服务架构是目前各大互联网公司普遍采用的软件架构方式。在微服务架构中,系统被拆分为多个小的、相互独立的服务,这些服务运行在自己的进程中,可以独立的开发和部署。在业务快速变化时,微服务单一职责、自治的特点,使系统的边界更加清晰,提升了系统的可维护性;同时,简化了系统部署的复杂度,可以针对某个微服务单独升级和发布;在业务增长时,也可以方便的进行独立扩展。 微服务架构虽然带来了很多好处,但也带来了新的问题。在以往的单体应用中,排查问题往往通过查看日志定位错误信息和异常堆栈;但是在微服务架构中服务繁多,出现问题时的问题定位变得非常困难。另外,微服务往往通过组合已有的服务来创建新服务,一个服务的故障很可能会产生雪崩效应,导致整个系统的不可用。因此,如何监控微服务的运行状况、当出现异常时能快速给出报警,这给开发人员带来很大挑战。 本文将介绍我们基于Prometheus搭建微服务监控系统的一些实践经验,及爱奇艺号在微服务监控方面的一些探索和实践,从爱奇艺号的业务特点出发,结合现有的开发运维技术栈确定监控的对象和指标,并有针对性地自研了一些关键组件和服务,实现服务的全面监控和统一报警。 1 监...
- 下一篇
Redis的各种数据类型到底能玩出什么花儿?
两个星期终于肝了出来,Redis相关问题脑图,终于整理完了!!! 文末无套路分享~~附获取方式 Redis作为一款NoSQL内存数据库,其丰富的数据类型、简单易用的命令、单机可达10万的高并发(官方数据),从面世以来就深受广大用户的喜爱。Redis的五种数据类型,是我们学习Redis时的必修课,但是大多数人都只是去学它的命令、API,却不知道这些数据类型都能应用在哪些场景,那这些命令学起来也就会很快就忘,终究只是“纸上谈兵”。 用好这五种数据类型将给你的开发带来很大的便利,给你的程序带来很大的性能提升,同时这五种数据类型能玩出很多花样。 不过大多数同学,在实际的开发过程中,大多只用到了Redis五种数据类型中的1-3种,甚至有的只用过一种String类型。要么是业务场景简单用string足矣,要么就是根本不知道或想不到用别的数据类型更合适,那么即使是有些场景更适合用别的数据类型,可能自己也发觉不到。所以今天就来聊聊Redis的各种数据类型以及各自适用于什么场景。 其实这个问题也是面试中问到Redis时的一个“开篇词”,问这个问题主要有两个原因: 第一,看看你到底有没有全面的了解Redi...
相关文章
文章评论
共有0条评论来说两句吧...