linux伙伴系统接口,Linux伙伴系统(一)--伙伴系统的概述

伙伴系统的概述

Linux内核内存管理的一项重要工作就是如何在频繁申请释放内存的情况下,避免碎片的产生。Linux采用伙伴系统解决外部碎片的问题,采用slab解决内部碎片的问题,在这里我们先讨论外部碎片问题。避免外部碎片的方法有两种:一种是之前介绍过的利用非连续内存的分配;另外一种则是用一种有效的方法来监视内存,保证在内核只要申请一小块内存的情况下,不会从大块的连续空闲内存中截取一段过来,从而保证了大块内存的连续性和完整性。显然,前者不能成为解决问题的普遍方法,一来用来映射非连续内存线性地址空间有限,二来每次映射都要改写内核的页表,进而就要刷新TLB,这使得分配的速度大打折扣,这对于要频繁申请内存的内核显然是无法忍受的。因此Linux采用后者来解决外部碎片的问题,也就是著名的伙伴系统。

什么是伙伴系统?

伙伴系统的宗旨就是用最小的内存块来满足内核的对于内存的请求。在最初,只有一个块,也就是整个内存,假如为1M大小,而允许的最小块为64K,那么当我们申请一块200K大小的内存时,就要先将1M的块分裂成两等分,各为512K,这两分之间的关系就称为伙伴,然后再将第一个512K的内存块分裂成两等分,各位256K,将第一个256K的内存块分配给内存,这样就是一个分配的过程。下面我们结合示意图来了解伙伴系统分配和回收内存块的过程。

1338122705_5396.png

1 初始化时,系统拥有1M的连续内存,允许的最小的内存块为64K,图中白色的部分为空闲的内存块,着色的代表分配出去了得内存块。

2 程序A申请一块大小为34K的内存,对应的order为0,即2^0=1个最小内存块

2.1 系统中不存在order 0(64K)的内存块,因此order 4(1M)的内存块分裂成两个order 3的内存块(512K)

2.2 仍然没有order 0的内存块,因此order 3的内存块分裂成两个order 2的内存块(256K)

2.3 仍然没有order 0的内存块,因此order 2的内存块分裂成两个order 1的内存块(128K)

2.4 仍然没有order 0的内存块,因此order 1的内存块分裂成两个order 0的内存块(64K)

2.5 找到了order 0的内存块,将其中的一个分配给程序A,现在伙伴系统的内存为一个order 0的内存块,一个order

1的内存块,一个order 2的内存块以及一个order 3的内存块

3 程序B申请一块大小为66K的内存,对应的order为1,即2^1=2个最小内存块,由于系统中正好存在一个order 1的内

存块,所以直接用来分配

4 程序C申请一块大小为35K的内存,对应的order为0,同样由于系统中正好存在一个order 0的内存块,直接用来分

5 程序D申请一块大小为67K的内存,对应的order为1

5.1 系统中不存在order 1的内存块,于是将order 2的内存块分裂成两块order 1的内存块

5.2 找到order 1的内存块,进行分配

6 程序B释放了它申请的内存,即一个order 1的内存块

7 程序D释放了它申请的内存

7.1 一个order 1的内存块回收到内存当中

7.2由于该内存块的伙伴也是空闲的,因此两个order 1的内存块合并成一个order 2的内存块

8 程序A释放了它申请的内存,即一个order 0的内存块

9 程序C释放了它申请的内存

9.1 一个order 0的内存块被释放

9.2 两个order 0伙伴块都是空闲的,进行合并,生成一个order 1的内存块m

9.3 两个order 1伙伴块都是空闲的,进行合并,生成一个order 2的内存块

9.4 两个order 2伙伴块都是空闲的,进行合并,生成一个order 3的内存块

9.5 两个order 3伙伴块都是空闲的,进行合并,生成一个order 4的内存块

相关的数据结构

在前面的文章中已经简单的介绍过struct zone这个结构,对于每个管理区都有自己的struct zone,而struct zone中的struct free_area则是用来描述该管理区伙伴系统的空闲内存块的

structzone {

...

...

structfree_area    free_area[MAX_ORDER];

...

...

}

structfree_area {

structlist_head    free_list[MIGRATE_TYPES];

unsigned longnr_free;

};

free_area共有MAX_ORDER个元素,其中第order个元素记录了2^order的空闲块,这些空闲块在free_list中以双向链表的形式组织起来,对于同等大小的空闲块,其类型不同,将组织在不同的free_list中,nr_free记录了该free_area中总共的空闲内存块的数量。MAX_ORDER的默认值为11,这意味着最大内存块的大小为2^10=1024个页框。对于同等大小的内存块,每个内存块的起始页框用于链表的节点进行相连,这些节点对应的着struct page中的lru域

structpage {

...

...

structlist_head lru;/* Pageout list, eg. active_list

* protected by zone->lru_lock !

*/

...

}

连接示意图如下:

1338135700_6593.png

在2.6.24之前的内核版本中,free_area结构中只有一个free_list数组,而从2.6.24开始,free_area结构中存有MIGRATE_TYPES个free_list,这些数组是根据页框的移动性来划分的,为什么要进行这样的划分呢?实际上也是为了减少碎片而提出的,我们考虑下面的情况:

1338176164_4666.png

图中一共有32个页,只分配出了4个页框,但是能够分配的最大连续内存也只有8个页框(因为伙伴系统分配出去的内存必须是2的整数次幂个页框),内核解决这种问题的办法就是将不同类型的页进行分组。分配出去的页面可分为三种类型:

不可移动页(Non-movable pages):这类页在内存当中有固定的位置,不能移动。内核的核心分配的内存大多属于这种类型

可回收页(Reclaimable pages):这类页不能直接移动,但可以删除,其内容页可以从其他地方重新生成,例如,映射自文件的数据属于这种类型,针对这种页,内核有专门的页面回收处理

可移动页:这类页可以随意移动,用户空间应用程序所用到的页属于该类别。它们通过页表来映射,如果他们复制到新的位置,页表项也会相应的更新,应用程序不会注意到任何改变。

假如上图中大部分页都是可移动页,而分配出去的四个页都是不可移动页,由于不可移动页插在了其他类型页的中间,就导致了无法从原本空闲的连续内存区中分配较大的内存块。考虑下图的情况:

1338177511_4702.png

将可回收页和不可移动页分开,这样虽然在不可移动页的区域当中无法分配大块的连续内存,但是可回收页的区域却没有受其影响,可以分配大块的连续内存。

内核对于迁移类型的定义如下:

mmzone.h>

#define MIGRATE_UNMOVABLE     0

#define MIGRATE_RECLAIMABLE   1

#define MIGRATE_MOVABLE       2

#define MIGRATE_PCPTYPES      3 /* the number of types on the pcp lists */

#define MIGRATE_RESERVE       3

#define MIGRATE_ISOLATE       4 /* can't allocate from here */

#define MIGRATE_TYPES         5

前三种类型已经介绍过

MIGRATE_PCPTYPES是per_cpu_pageset,即用来表示每CPU页框高速缓存的数据结构中的链表的迁移类型数目

MIGRATE_RESERVE是在前三种的列表中都没用可满足分配的内存块时,就可以从MIGRATE_RESERVE分配

MIGRATE_ISOLATE用于跨越NUMA节点移动物理内存页,在大型系统上,它有益于将物理内存页移动到接近于是用该页最频繁地CPU

MIGRATE_TYPES表示迁移类型的数目

当一个指定的迁移类型所对应的链表中没有空闲块时,将会按以下定义的顺序到其他迁移类型的链表中寻找

staticintfallbacks[MIGRATE_TYPES][MIGRATE_TYPES-1] = {

[MIGRATE_UNMOVABLE]   = { MIGRATE_RECLAIMABLE, MIGRATE_MOVABLE,   MIGRATE_RESERVE },

[MIGRATE_RECLAIMABLE] = { MIGRATE_UNMOVABLE,   MIGRATE_MOVABLE,   MIGRATE_RESERVE },

[MIGRATE_MOVABLE]     = { MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE, MIGRATE_RESERVE },

[MIGRATE_RESERVE]     = { MIGRATE_RESERVE,     MIGRATE_RESERVE,   MIGRATE_RESERVE }, /* Never used */

};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/504743.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c# 创建委托 消息订阅_C#面向对象之委托和事件

委托1.定义:委托也叫代理,就是把事情交给别人来做。2.声明委托语法: delegate 返回类型 委托名称();委托使用步骤1.声明委托public delegate int CalculatorDelegate(int a,int b);2.根据委托类型创建方法3.创建委托对象并指定方法Calculator…

linux 集群 lvs,linux集群--LVS集群

拓扑图:1、LVS配置脚本:需要安装:ipvsadm-1.24-10.i386.rpmvi /etc/rc.d/init.d/lvsdr#!/bin/bashvip192.168.0.116web1192.168.0.104web2192.168.0.114./etc/rc.d/init.d/functionscase "$1" instart)echo "startlvs-dr&quo…

服务器连接工具mat_将个人笔记本改造成Linux简易服务器

实验过程1、开启Ubuntu系统的ssh服务开启之后其他电脑就可以通过ssh登录Ubuntu服务器,通过安装openssh-server就可以达到目的。(1)查看主机有没有ssh服务在Ubuntu系统桌面右击后点击“打开终端”,输入一下命令:ssh localhost若出现&#xff1…

c语言存储结构的实现,(C语言)栈的链式存储结构的实现

#includetypedef struct Stack_Linklist{int data;struct Stack_Linklist *next;}Node,*pNode;typedef struct Stack{pNode pTop;pNode pBottom;}Stack,*pStack;void Initstack();//初始化;int Isempty();//判断栈是否为空void Push();//压栈int Pop();//出栈int Ge…

以下对c语言函数的描述中正确的是,以下对C语言函数的有关描述中,正确的是

摘要:它决习定于的学后天,下语密切关系的能与社力是会文化有。关描透性的是起渗利尿可引。认的r默链接路径是(,述中在建点时立站。...它决习定于的学后天,下语密切关系的能与社力是会文化有。函数人感型的偏好感受觉很丰富。关描透…

创建前缀一样的文件_SpringBoot:配置文件属性读取

SpringBoot中默认加载的是application.properties或者application.yaml文件,当然也支持自定义的属性文件。我们可以在此文件中写一些自己想要的配置信息,然后在用的地方读取。默认属性文件在application.properties文件中添加配置信息,如下&a…

c语言降序多项式加法,数据结构算法(多项式加法)的C语言完美实现

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼/*数据结构多项式加法用C语言的完美实现,书43页 算法 2.23[ 数据结构(C语言版) 严尉敏主编]*//*注释就不加了,本程序的所有函数书上都有说明*//*本程序Tourboc 2.0编译通过*/#include #include #include #in…

c语言 算术平均滤波法_单片机数字滤波的算法

单片机主要作用是控制外围的器件,并实现一定的通信和数据处理。但在某些特定场合,不可避免地要用到数学运算,尽管单片机并不擅长实现算法和进行复杂的运算。下面主要是介绍如何用单片机实现数字滤波。在单片机进行数据采集时,会遇…

非顺序控制结构的c语言语法是怎样的,流程控制语句:顺序结构和选择结构

流程控制语句概述:控制程序的执行流程分类:顺序结构选择结构循环结构顺序结构语句顺序结构语句:从上往下,依次执行选择结构if语句:switch语句:if语句:格式1:格式2:格式3:if语句的格式:if(比较表达式){语句体;}执行流程:先计算比较表达式的值,看其返回值是true还是fa…

python3 asyncio 爬虫_python3 asyncio异步新浪微博爬虫WeiboSpider

一些废话之前写的用python3urllib写的多线程微博(传送门),后面发现登录账号频繁被403,所以解决登录问题迫在眉睫。而且python的“多线程”并不那么多线程,最近因为刚需,需要稳定的微博爬虫,所以琢磨了一下使用selenium…

linux .forward,linux forward的实现

对于linux的数据包流向,大家应该是比较了解,如果还不是很了解,可以参考《OReilly.Understanding.Linux.Network.Internals.Dec.2005》,其中有一个图非常清楚的描述了数据包的流向。ip的数据包接收函数是ip_rcv()>ip_rcv_finish…

参数 携带 跳转_微信小程序:页面跳转及参数传递

本文首发自个人自有博客:【FaxMiao个人博客】,一个关注Web前端开发技术、关注用户体验、记录前端点滴,坚持更多原创,为大家提供高质量技术博文!前言小程序的跳转方法有很多种,有的人一直只用wx.navigateTo跳…

android+apk启动过程,Android Apk的运行过程(一)—— Activity启动与页面事件传递...

最近在看一本书--《Android 内核剖析》。看名字很唬人,内核剖析,看起来是讲很深入的东西,其实作者自己在前言里也说了对于Android内核深度的一些见解。此书其实只是一些抛砖引玉,对于更深度与更细节的东西并没有涉猎,但…

python在数字后添加字符_Python在字符前后补字符

def addForLR(voldStr, vaddStr, vlength, vleftTrue):"""数字前补0可以补"0"也可以补""# print(tools.addForLR(1123,0,6));# print(tools.addForLR(1123,0,6,False));param voldStr 旧字符串param vaddStr 添加字符串param vlength 字符长…

google 浏览器默认打开控制台_chrome浏览器使用 Console(控制台)

chrome浏览器使用 Console(控制台) 了解如何:打开DevTools Console(控制台),堆叠冗余消息或在自己的行上显示它们,清除或保持输出或将其保存到文件,过滤输出,以及了解其他Console(控制台)设置。 TL;DR 以专用面板形式,或作为任何其他面板的抽屉式面板的形式,打开Console…

android 外部内容分享到app内,外部跳转APP

需求广告推广、华为微服务;通过外部网页或者卡片跳转到我们的app指定界面。如果app已经存在打开app,app不存在跳转下载界面。APP配置android:name".LauncherActivity"android:launchMode"singleTask"android:screenOrientation"…

vue组件一直注册不了_Vue自定义组件及组件的注册方法

为了能在模板中使用,这些组件必须先注册以便 Vue 能够识别。这里有两种组件的注册类型:全局注册和局部注册。至此,我们的组件都只是通过Vue.component全局注册的:Vue.component(component-name, {// ... options ...})该组件名Vue…

android fragment 管理器,Android Fragment 與 Fragment管理器

Android Fragment 與 Fragment管理器首先談談Fragement的需求過去開發人員認為界面之間的跳轉只需要使用多個activity組成就行了;例如下圖中,在Activity-A管理的界面中單擊按鈕后,Activity-A響應事件並啟動Activity-B;而用戶在單擊…

如何把本地yum源给其他机器使用_如何使用系统安装盘做yum的本地源?

第一种方法:1。 在server1上copy所有光盘的内容到/server/rhel5/i386/,并对此目录做好了NFS共享,然后把Server下repodata改名为repodata。ins2。 # createrepo -g /misc/cd/Server/repodata。ins/comps-rhel5-server-core。xml -v /server/rh…

android 手机 报证书错误,Android设备中的SSL证书错误

了解网络科技近年来高速增长,对人们日常生活的影响可通过PC端和移动设备的使用增长数据可以推断。在数字化技术的今天,用户也希望能够在移动设备上保护网站的信息以及用户的数据。SSL证书是保护网站信息的安全协议,也是目前互联网站点必备的安…