当前位置:文档之家› Linux内存管理实现的分析与研究

Linux内存管理实现的分析与研究

Linux内存管理实现的分析与研究
Linux内存管理实现的分析与研究

收稿日期:!""#$"%$"&

作者简介:肖竟华(’(%%$),女,湖北武汉人,副教授,硕士生导师,主要研究方向为系统软件开发、操作系统、信息安全。

!"#$%内存管理实现的分析与研究

肖竟华,陈

(武汉科技大学计算机科学与技术学院,湖北武汉)*""&’

)摘

要:存储管理子系统作为操作系统中最重要的组成部分之一,对整个系统的运行起着举足轻重的作用。+,-./继承了

0123系统的优秀设计思想,并采用了许多先进算法来保持系统的高效性和稳定性。文中先概述了+,-./!4)物理内存的管理,然后介绍了解决内存中碎片问题的伙伴系统算法和5678分配器,并讨论了它们实现的要点,着重对5678分配器中的几个数据结构进行了分析。

关键词:+,-./内存管理;伙伴系统算法;5678分配器中图分类号:9:***

文献标识码:;

文章编号:’#<*$#!(3(!""<)"!$"’&<$"*

!"#$%&’&#"()*&*#+,-./)*#$’0#1’."/.+2’"345*6.+%5#"#7

*6*"132;=>,-?

@A .7,B C D 1+7-(B E F G .H I J 5K A E E 6,L .A 7-0-,M I J N ,H O E P 5K ,I -K I 7-Q9I K A -E 6E ?O

,L .A 7-)*""&’,B A ,-7)!8&1+#,1:;N E -I E P H A IF E N H ,F G E J H 7-H G 7J H N E P H A I E G I J 7H ,-?N O N H I F ,H A IF I F E J O F 7-7?I F I -H N .8N O N H I F G 67O N 7R I O J E 6I ,-H A I J .--,-?E P 7N O N H I F 4+,-./,-A I J ,H I Q N E F I I /K I 66I -H Q I N ,?-,Q I 7N P J E F0123,7-Q 7Q E G H I QF 7-O 7Q M 7-K I Q 76?E J ,H A F N H E R I I G H A I N O N H I FI P P ,K ,I -H 7-Q N H 786I 49A ,N G 7G I J N .F F 7J ,S I N H A I G A O N ,K 76F I F E J O F 7-7?I F I -H ,-+,-./!4)R I J -I 649A I -,H ,-H J E Q .K I N H A I T .Q Q O N O N H I F76?E J ,H A F 7-Q 5678766E K 7H E J H A 7H N E 6M I H A I P J 7?F I -H G J E 86I F N ,-R I J -I 6,7-Q Q ,N K .N N I N H A I G E ,-H N ,-J I 76,S 7H ,E -,I N G I K ,766O 7-76O N I N N E F IF 7,-Q 7H 7N H J .K H .J I N ,-5678766E K 7H E J 4

9*%:

.+(&:+,-./F I F E J O F 7-7?I F I -H ;T .Q Q O N O N H I F76?E J ,H A F ;5678766E K 7H E J ;引

内存作为最重要的系统资源,其分配和释放策略对系统的运行效率起着至关重要的作用。系统内核和所有进程通过共享有限的物理内存来运行,一个系统的高效性与稳定性往往取决于它内存管理机制。因此,一个高效的内存管理系统不仅要能够有效地管理系统内存,减少频繁分配和回收内存而导致的内存碎片,还要尽量提高分配和回收的速度来提高系统的运行效率。此外,内存管理系统还应该保证内存分配和回收的公平性。

<2’"34内存管理概述

+,-./!4)支持非一致存储器访问(10U ;)

模型[’],根据每个B :0对存储器的访问时间,存储器单元被划分为不同的节点(-E Q I ),每个B :0对每个节点访问页所需的时间是相同的。每个节点通过一个类型为G ?$Q 7H 7$

H 的描述符来表示。+,-./将每个节点的存储区划分为*个管理区(S E -I ):V =1D $W U ;,V =1D $1=X U ;+,V =1D $C 2Y C U D U 。在&"/&#系统上,V =1D $W

U ;管理区包含’#U T 以下的页框,可供原有25;设备通过W U ;直接访问。V =1D $1=X @U ;+包含大于’#U T 而小于&(#U T 的页框。V 1=D $

C 2Y C U

D U 包含所有大于&(#U T 的页框,不能直接被内核使用。V =1D $W U ;和V =1D $1

=X U ;+可以线性地映射到线性地址空间的第)个Y T ,内核就可以直接进行访问。每个管理区通过S E -I $N H J .K H 类型结构描述。

+,-./系统用F I F $F 7G 数据结构描述保存系统中所有的页框信息。F I F $F 7G 是由F I F $F 7G $H 结构组成的链表,每个F I F $F 7G $H 结构都描述了系统中的一个页框。系统在初始化时,通过调用P J I I $7J I 7$

,-,H ()函数来初始化F I F $F 7G 数据。频繁的请求和释放同大小的一组连续页框,必然导致在已分配页框块内分散许多小块的空闲页框,也即所谓的外碎片。另一方面,如果请求存储器的大小与分配给它的大小不匹配,也会造成另外一种问题,即所谓的内碎片。+,-./采用伙伴系统算法和5678分配

第’<卷第!期!""<年!月

计算机技术与发展

B =U :09D X9D B

C 1=+=Y Z;1WW

D [D +=:U D 19

[E 64’<1E 4!

\I 84!""<

器模式来解决外碎片和内碎片问题。

!伙伴系统算法

!"#$%系统采用伙伴系统算法管理系统页框的分配和回收,该算法对不同的管理区使用单独的伙伴系统管理。伙伴系统算法把内存中的所有页框按照大小分成&’组不同大小的页块,每块分别包含&,(,),*,…,+&(个页框。每种不同的页块都通过一个,-..

/ 0-.0/12-$32结构体来管理。系统将&’个,-../0-.0/ 12-$32结构体组成一个,-../0-.0[]数组。在,-../ 0-.0/12-$32包含指向空闲页块链表的指针。此外在每

个,-..

/

0-.0/12-$32中还包含一个系统空闲页块位图(4"2506),位图中的每一位都用来表示系统按照当前

页块大小划分时每个页块的使用情况,同5.5

/

506

一样,系统在初始化时调用,-..

/

0-.0/"#"2()函数来初

始化每个,-..

/

0-.0/12-$32中的位图结构。

当向内核请求分配一定数目的页框时,若所请求的页框数目不是(的幂次方,则按稍大于此数目的(的幂次方在页块链表中查找空闲页块,如果对应的页块链表中没有空闲页块,则在更大的页块链表中查找[(]。当分配的页块中有多余的页框时,伙伴系统将根据多余的页框大小插入到对应的空闲页块链表中。向伙伴系统释放页框时,伙伴系统会将页框插入到对应的页框链表中,并且检查新插入的页框能否和原有的页块组合构成一个更大的页块,如果有两个块的大小相同且这两个块的物理地址连续,则合并成一个新页块并加入到对应的页块链表中,并迭代此过程直到不能合并为止,这样可以极大限度地减少内存的外碎片。

伙伴系统提供了分配和释放页框的函数。7.2

/ 8.-9.:/607.()用于分配用’填充好的页框。和7.2/ 8.-9.:/607.()相似,/7.2/,-../607.()用来分配一个新

的页框,但是没有被’填充,

/

7.2/,-../607.1()用来分

配指定数目的页框。通过调用

/

,-../607.()和/,-../ 607.1()可以向伙伴系统释放已申请的页框。0;;93/ 607.1/#9:.()是伙伴系统分配页框的核心函数,它有

两个变体:0;;93

/

607.()和0;;93/607.1()。0;;93/607.1/ #9:.()函数在指定的节点中分配一定数目的页框。0;< ;93/607.()和0;;93/607.1()分别在当前节点中分配一个或指定数目的页框。

"#$%&分配器

"’(#$%&分配器基本思想

很多时候,内核需要频繁地申请和释放某一特定

类型的对象,如果每次都从伙伴系统中按页框为单位分配和释放内存块,不仅造成大量的内碎片,而且严重影响系统的运行性能。为此,!"#$%提供了从缓存中分配内存的机制,即=;04分配器。=;04分配器通过预先分配一块内存区域当作缓冲区,当要求分配对象时就直接从缓冲区中返回,释放对象时=;04分配器只是将对象归还到缓冲区以供下次分配时使用,这样就可以避免频繁地调用伙伴系统的申请和释放操作,从而加快申请和释放对象的时间。

"’!#$%&分配器实现结构

=;04分配器有>层基本结构:缓存(303?.)、=;04、对象(94@.32)[>]。其结构可见图&。

图&缓存、=;04和对象的结构图

>A(A&缓存

=;04分配器把对象分组放进高速缓存,每个高速缓存都是同种类型对象的一个集合。缓存通过

B5.5/303?./2结构体来描述,它由多个=;04组成。

缓存分为通用和专用(种类型。通用缓存由=;04分配器自己使用,专用缓存由内核的其他部分使用。!"#$%中通用缓存包括两种:

&)一个用于分配高速缓存描述的缓存303?./ 303?.,此高速缓存在系统初始化时通过B5.5/303?./ "#"2()函数创建;

()两组共(C个包含几何分布的高速缓存,每组相关的存储区大小分别为>(,C),&(*,…,&>&’D(字节,一组用于E F G分配,另一组用于普通分配。

它们的描述符保存在303?.

/

1"8.1[]数组中,在系

统初始化时通过B.5.

/

303?./1"8.1/"#"2()创建。

从缓存中分配一个新的对象,可以调用B5.5

/ 303?./0;;93()函数,该函数用于在指定的缓存中申请一个对象。B50;;93()函数也可用从高速缓存中分配一个指定大小的对象,=;04分配器首先根据要求分配对

象的大小在303?.

/

1"8.1[]数组描述的通用缓存选择一

个通用高速缓存,然后通过B5.5

/

303?./0;;93()从该

缓存中分配一个对象实例[)]。B5.5

/

303?./,-..()用于释放从某个高速缓存中分配的对象。与B50;;93()对应,B,-..()用于释放从通用缓存中分配的对象。

通过调用B5.5

/

3?03?./3-.02.()函数,可以为一

?

*

*

&

?计算机技术与发展第&D

个特定对象创建一个专用高速缓存。此时,在新创建的缓存中还没有!"#$。只有当第一次要求分配对象时,!"#$分配器才为此高速缓存创建一个新的!"#$。%&’&’!"#$

!"#$是!"#$分配器的基本单位,每个!"#$由一个或多个连续的页框组成。!"#$通过("#$

)

(结构体来描述。每个!"#$中存放一定数量的已初始化的对象,当从指定缓存中申请一个对象时,!"#$分配器从缓存中找一个未满的!"#$,并从中返回一个对象。如果缓存

中所有的!"#$都已满,则!"#$分配器通过调用*+,+

) -#-.,)/012()函数为此缓存添加一个新的!"#$,并从新!"#$中返回一个对象。!"#$分配器一般不会主动释放!"#$的页框,即使某个缓存中有空的!"#$,只有当伙伴系统无法满足页框分配请求时,!"#$分配器才会通

过调用*+,+

)

-#-.,)0,#3()函数从缓存中释放空的!"#$。

!"#$分配器根据对象的大小使用不同的技术来存

放!"#$描述符。当对象比较小时(小于45’*6),("#$

)

(

存放于!"#$首部[4]。对比较大的对象,("#$

)

(位于-#-.,)(78,(指向的一个普通高速缓存中。

每个对象都有一个类型为*+,+

)

$9:-;");的描述符,依次存放在一个数组中,位于相应的!"#$结构之后,该数组中的描述符与!"#$中的对象一一对应。!"!着色功能

为了充分利用硬件的高速缓存性能,!"#$分配器为每个!"#$分配一个不同的着色数,即在!"#$的未用空间上划出一部分空间,放到!"#$的起始部分,这样将!"#$中第一个对象分配在相对于该!"#$起始地址

的不同偏移地址(着色数)处,使!"#$块在硬件缓存区中均匀分布,也使该类对象有良好的地址分布。利用着色功能可以避免!"#$中对象被映射到相同的高速缓存行上,从而提高了硬件高速缓存的命中率与系统的运行效率。

#小结

<7=9>内核使用大量的技术来改进内存管理系统,在有效地控制内存碎片的同时提高内存分配和释放效率。在<7=9>’&?内核中,对存储管理子系统进行了一系列的改进,提高了系统的可扩展性,包含对大型服务器如@A B C服务器的良好支持,此外还提供了对BB A的支持。随着<7=9>内核的不断发展和成熟,<7=9>已经越来越具备商业级系统所需的一切品质,完全可以运行非常大的系统来处理科学分析应用程序或者甚至海量数据库。

参考文献:

[5]厉海燕,李新明&<7=9>操作系统特性分析[D]&微机发展,’E E’,5’(5):5F)5G&

[’]H10$,;D,I9$7=7C,J01#.)K#0;+#L&<7=9>M,N7-,M07N,0([B]&%0O,O&[(&"&]:P’I,7""Q,’E E4&

[%]61N,;MR,H,(#;7B&深入<7=9>内核[B]&第’版S陈莉君,冯锐,牛欣源译&北京:中国电力出版社,’E E%&[F]楼程辉,孙守迁&<7=9>下物理内存管理技术探讨[D]&计算机应用研究,’E E E(G):T’)T%&

[4]洪津津,石教英&

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

G’)G F&

(上接第5G?页)

好地解决基于不同操作系统和不同编程语言的分布式系统的互操作问题以及遗留系统的集成问题。但随着分布式系统规模的不断增大,对系统的开发周期,以及不同编程语言间,系统组件的可复用性的要求越来越高。文中以“香港利苑集团餐饮管理系统”为背景,使用B M C的方法开发分布式系统。在缩短系统开发周期的同时,还有效地解决了不同编程语言间的系统组件的可复用问题。

参考文献:

[5]汪芸,顾冠群&H P I6C技术及其应用[B]&南京:东南大学出版社,5T T T&

[’]崔萌,史耀馨,李宣东,等&基于B M C的R U B到D’W W平台R!B的转换方法[D]&计算机应用与科学,’E E4,’’(5):5

)’&[%]B7"",0D,B9*,0X7D&B M C L97O,Y,0(71=5&E&5[W6/P<]&’E E%)E?)5’&.;;3://222&1+/&10//O1-(/1+//E%)E?)

E5&3O:&

[F]顾峥峰,蔡勇&基于B M C的Z,$服务开发与集成[D]&计算机应用,’E E%,’%(4):5F’)5F F&

[4]K9#=/!,K9[,<7H&CH P I6C)6#(,O H1+39;,0!93310;

H113,0#;7N,Z10*:10M Q=#+7-C""7#=-,([D]&U=;D C O N

B#=9:,’E E’,5T:\4’)\44&

[?]史耀馨,崔萌,李宣东,等&基于B M C的A B<模型转换技术———从顺序图到状态图[D]&计算机工程与应用,’E E F (5%):F E)F4&

[\]沈卓炜,谢俊清,顾冠群&集成H P I6C和A B<的分布式应用开发[D]&东南大学学报,’E E5,%5:5)4&

[G]W++,07-.Z&M7(;07$9;,O H1++31=,=;],-.=1"1/7,(#=O;.,70 !1:;2#0,W=/7=,,07=/U+3"7-#;71=([B]&[(&"&]:C H B R0,((,’E E’&

?

T

G

5

?

第’期肖竟华等:<7=9>内存管理实现的分析与研究

操作系统内存管理复习过程

操作系统内存管理

操作系统内存管理 1. 内存管理方法 内存管理主要包括虚地址、地址变换、内存分配和回收、内存扩充、内存共享和保护等功能。 2. 连续分配存储管理方式 连续分配是指为一个用户程序分配连续的内存空间。连续分配有单一连续存储管理和分区式储管理两种方式。 2.1 单一连续存储管理 在这种管理方式中,内存被分为两个区域:系统区和用户区。应用程序装入到用户区,可使用用户区全部空间。其特点是,最简单,适用于单用户、单任务的操作系统。CP/M和 DOS 2.0以下就是采用此种方式。这种方式的最大优点就是易于管理。但也存在着一些问题和不足之处,例如对要求内

存空间少的程序,造成内存浪费;程序全部装入,使得很少使用的程序部分也占用—定数量的内存。 2.2 分区式存储管理 为了支持多道程序系统和分时系统,支持多个程序并发执行,引入了分区式存储管理。分区式存储管理是把内存分为一些大小相等或不等的分区,操作系统占用其中一个分区,其余的分区由应用程序使用,每个应用程序占用一个或几个分区。分区式存储管理虽然可以支持并发,但难以进行内存分区的共享。 分区式存储管理引人了两个新的问题:内碎片和外碎片。 内碎片是占用分区内未被利用的空间,外碎片是占用分区之间难以利用的空闲分区(通常是小空闲分区)。 为实现分区式存储管理,操作系统应维护的数据结构为分区表或分区链表。表中各表项一般包括每个分区的起始地址、大小及状态(是否已分配)。

分区式存储管理常采用的一项技术就是内存紧缩(compaction)。 2.2.1 固定分区(nxedpartitioning)。 固定式分区的特点是把内存划分为若干个固定大小的连续分区。分区大小可以相等:这种作法只适合于多个相同程序的并发执行(处理多个类型相同的对象)。分区大小也可以不等:有多个小分区、适量的中等分区以及少量的大分区。根据程序的大小,分配当前空闲的、适当大小的分区。 优点:易于实现,开销小。 缺点主要有两个:内碎片造成浪费;分区总数固定,限制了并发执行的程序数目。 2.2.2动态分区(dynamic partitioning)。 动态分区的特点是动态创建分区:在装入程序时按其初始要求分配,或在其执行过程中通过系统调用进行分配或改变分区大小。与固定分区相比较其优点是:没有内碎

linux内核之内存管理

Linux内核之内存管理 作者:harvey wang 邮箱:harvey.perfect@https://www.doczj.com/doc/688521279.html, 新浪博客地址:https://www.doczj.com/doc/688521279.html,/harveyperfect,有关于减肥和学习英语相关的博文,欢迎交流 把linux内存管理分为下面四个层面 (一)硬件辅助的虚实地址转换 (二)内核管理的内存相关 (三)单个进程的内存管理 (四)malloc软件 (一)处理器硬件辅助的虚实地址转换(以x86为例) 在x86中虚实地址转换分为段式转换和页转换。段转换过程是由逻辑地址(或称为虚拟地址)转换为线性地址;页转换过程则是将线性地址转换为物理地址。段转换示意图如下 X86支持两种段,gdt和ldt(全局描述段表和局部描述符段表),在linux中只使用了4个全局描述符表,内核空间和用户空间分别两个gdt,分别对应各自的代码段和数据段。也可以认为在linux中变相地disable了x86的段式转换功能。 页转换示意图如下

在linux中x86 的cr3寄存器(页表基地址寄存器)保存在进程的上下文中,在进程切换时会保存或回复该寄存器的内容,这样每个进程都有自己的转换页表,从而保证了每个进程有自己的虚拟空间。 (二)内核管理的内存相关 从几个概念展开内存管理:node、zone、buddy、slab 1、Node SGI Altix3000系统的两个结点 如上图,NUMA系统的结点通常是由一组CPU(如,SGI Altix 3000是2个Itanium2 CPU)和本地内存组成。由于每个结点都有自己的本地内存,因此全系统的内存在物理上是分布的,每个结点访问本地内存和访问其它结点的远地内存的延迟是不同的,为了优化对NUMA 系统的支持,引进了Node 来将NUMA 物理内存进行划分为不同的Node。而操作系统也必须能感知硬件的拓扑结构,优化系统的访存。

linux内存管理子系统 笔记

4-4 linux内存管理子系统 4-4-1 linux内存管理(参考课件) 物理地址:cpu地址总线上寻址物理内存的地址信号,是地址变换的最终结果 逻辑地址:程序代码经过编译后,出现在汇编程序中的地址(程序设计时使用的地址) 线性地址:又名虚拟地址,32位cpu架构下4G地址空间 CPU要将一个逻辑地址转换为物理地址,需要两步: 1、首先CPU利用段式内存管理单元,将逻辑地址转换成线性地址; 2、再利用页式内存管理单元,把线性地址最终转换为物理地址 相关公式: 逻辑地址=段基地址+段内偏移量(段基地址寄存器+段偏移寄存器)(通用的) 16位CPU:逻辑地址=段基地址+段内偏移量(段基地址寄存器+段偏移寄存器) 线性地址=段寄存器的值×16+逻辑地址的偏移部分 物理地址=线性地址(没有页式管理) 32位CPU:逻辑地址=段基地址+段内偏移量(段基地址寄存器+段偏移寄存器) 线性地址=段寄存器的值+逻辑地址的偏移部分 物理地址<——>线性地址(mapping转换) ARM32位:逻辑地址=段基地址+段内偏移量(段基地址寄存器+段偏移寄存器) 逻辑地址=段内偏移量(段基地址为0) 线性地址=逻辑地址=段内偏移量(32位不用乘以32) 物理地址<——>线性地址(mapping转换) ************************!!以下都是x86模式下!!********************************* 一、段式管理 1.1、16位CPU:(没有页式管理) 1.1.1、段式管理的由来: 16位CPU内部有20位地址总线,可寻址2的20次方即1M的内存空间,但16位CPU 只有16位的寄存器,因此只能访问2的16次方即64K。因此就采用了内存分段的管理模式,在CPU内部加入了段寄存器,这样1M被分成若干个逻辑段,每个逻辑段的要求如下: 1、逻辑段的起始地址(段地址)必须是16的整数倍,即最后4个二进制位须全是0 (因此不必保存)。 2、逻辑段的最大容量为64K。 1.1.2、物理地址的形成方式: 段地址:将段寄存器中的数值左移4位补4个0(乘以16),得到实际的段地址。 段偏移:在段偏移寄存器中。 1)逻辑地址=段基地址+段内偏移量(段基地址寄存器+段偏移寄存器) 2)由逻辑地址得到物理地址的公式为:(因为没有页式管理,所以这一步就得到了物理地址)物理地址PA=段寄存器的值×16+逻辑地址的偏移部分(注意!!)(段与段可能会重叠)

Solaris 8内存管理机制研究

Solaris 8内存管理机制研究 吴海燕 戚丽 冯珂 摘 要:寻找性能瓶颈是性能分析中的一项重要任务,内存瓶颈的表现并不像CPU或磁盘那样直接,本文通过对Solaris 8内存管理机制的研究,给出了寻找Solaris 8系统内存瓶颈的方法。 关键词:Solaris 8,内存管理,性能优化 一、问题的提出 清华大学计算机与信息管理中心数据中心现有服务器近百台,其中包括了SUN Fire 15000、SUN Enterprise 5500、SUN Enterprise 5000等大型SUN服务器,Solaris 8是主流操作系统。为了对服务器的资源(如CPU、内存、磁盘、网络)的使用情况进行长期监控,建立性能优化(performance tuning)的基准值,我们开发了一套脚本程序定时采集系统运行参数。在长期的监控中,我们发现Solaris 8系统的空闲内存(freemem)呈现一个有趣的变化规律,如图1所示: 图1 空闲内存(freemem)变化图 图1是某Solaris 8系统(在下文中我们称之为15k-a)自2003年2月份以来的freemem 变化情况,横坐标是时间,纵坐标是freemem的数量,以8K字节为单位。15k-a配置是10路Super SPARCIII CPU,10GB物理内存。从上图可以看到在正常运行时,freemem应该是比较稳定的,15k-a主要是运行数据库,数据库在运行时会占用2G内存作为SGA区使用,因此在通常的负载下,freemem保持在6~7G之间是比较正常的。稳定一段时间后,

15k-a的freemem会持续走低,直到最低值,约为18893×8KMB,然后系统开始回收内存,我们就会看到freemem数量急剧上升。freemem的陡降都发生在凌晨1:00之后,检查系统作业发现每天1:00都会有一个数据库备份脚本开始运行:首先是用“exp”命令给数据库做逻辑备份,然后用“cp”命令把备份出来的文件拷贝到后备存储上。这两个命令都是正常退出,没有任何报错。开始时我们曾怀疑是有内存泄漏,当某一天freemem大幅攀升时,此怀疑被解除了,因为如果有内存泄漏,系统是无法将内存回收回来的。 对于一个物理内存为10GB的系统来说,如果空闲内存(freemem)真的减少到不到二百兆,那将存在着严重的问题。但奇怪的是系统的CPU使用率一直很低,所有进程的反应也很快,系统没有任何资源匮乏的迹象。如何解释这些问题呢,为此我们对Solaris 2.x 的内存管理机制进行了研究。 二、Solaris的内存管理机制 Solaris 8的内存管理为虚拟内存管理。[1]简单地说,虚拟内存就是进程看到比它实际使用的物理内存多得多的内存空间,对于64位的Solaris 8操作系统,进程可以通过8K 大小的段寻址访问2的64次方字节的内存空间,这种8K的段被称为页(page)。传统的UNIX通过进程(pagedaemon)完成虚拟地址和物理地址间的转换,在Solaris中这些是通过一个硬件-MMU(Memory Management Unit)-来实现的。在多处理器系统中,每个CPU 都有自己的MMU。Solaris 8的虚拟存储体系由系统寄存器、CPU CACHE、主存(RAM,物理内存)、外存(磁盘、磁带等)构成。 有两个基本的虚拟内存系统管理模型[2]:交换(swapping)和按需换页(demand paged)模型。交换模型的内存管理粒度是用户进程,当内存不足时,最不活跃的进程被交换出内存(swapping out)。按需换页模型的内存管理粒度是页(page),当内存匮乏时,只有最不经常使用的页被换出。Solaris 8结合使用了这两种内存管理模型,在通常情况下使用按需换页模型,当内存严重不足时,使用交换模型来进行内存释放。 与传统UNIX系统相比,Solaris虚拟内存系统的功能要丰富得多,它负责管理所有与I/O和内存相关的对象,包括内核、用户应用程序、共享库和文件系统。传统的UNIX系统V(System V)使用一个单独的缓冲区来加速文件系统的I/O, Solaris 8则使用虚拟内存系统来管理文件系统的缓存,系统的所有空闲内存都可以被用来做为文件I/O缓存,因为RAM的访问速度比磁盘快得多,所以这样做带来的性能提高是可观的。这也意味着在存在大量文件系统I/O的系统上,空闲内存的数量几乎是0。 了解系统内存被分配到了什么地方,系统在什么情况下进行内存整理是系统管理的重

JVM原理以及JVM内存管理机制

一、 JVM简介 JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。JVM工作原理和特点主要是指操作系统装入JVM是通过jdk中Java.exe来完成, 首先来说一下JVM工作原理中的jdk这个东西, .JVM 在整个jdk中处于最底层,负责于操作系统的交互,用来屏蔽操作系统环境,提供一个完整的Java运行环境,因此也就虚拟计算机. 操作系统装入JVM是通过jdk中Java.exe来完成。 通过下面4步来完成JVM环境. 1.创建JVM装载环境和配置 2.装载JVM.dll 3.初始化JVM.dll并挂界到JNIENV(JNI调用接口)实例 4.调用JNIEnv实例装载并处理class类。 对于JVM自身的物理结构,我们可以从下图了解:

JVM的一个重要的特征就是它的自动内存管理机制,在执行一段Java代码的时候,会把它所管理的内存划分 成几个不同的数据区域,其中包括: 1. 程序计数器,众所周知,JVM的多线程是通过线程轮流切换并 分配CPU执行时间的方式来实现的,那么每一个线程在切换 后都必须记住它所执行的字节码的行号,以便线程在得到CPU 时间时进行恢复,这个计数器用于记录正在执行的字节码指令的地址,这里要强调的是“字节码”,如果执行的是Native方法,那么这个计数器应该为null; 2.

3. Java计算栈,可以说整个Java程序的执行就是一个出栈入栈 的过程,JVM会为每一个线程创建一个计算栈,用于记录线程中方法的调用和变量的创建,由于在计算栈里分配的内存出栈后立即被抛弃,因此在计算栈里不存在垃圾回收,如果线程请求的栈深度大于JVM允许的深度,会抛出StackOverflowError 异常,在内存耗尽时会抛出OutOfMemoryError异常; 4. Native方法栈,JVM在调用操作系统本地方法的时候会使用到 这个栈; 5. Java堆,由于每个线程分配到的计算栈容量有限,对于可能会 占据大量内存的对象,则会被分配到Java堆中,在栈中包含了指向该对象内存的地址;对于一个Java程序来说,只有一个Java堆,也就是说,所有线程共享一个堆中的对象;由于Java堆不受线程的控制,如果在一个方法结束之后立即回收这个方法使用到的对象,并不能保证其他线程是否正在使用该对象;因此堆中对象的回收由JVM的垃圾收集器统一管理,和某一个线程无关;在HotSpot虚拟机中Java堆被划分为三代:o新生代,正常情况下新创建的对象会被分配到新生代,但如果对象占据的内存足够大以致超过了新生代的容量限 制,也可能被分配到老年代;新生代对象的一个特点是最 新、且生命周期不长,被回收的可能性高;

《深入理解LINUX内存管理》学习笔记.

引子 为什么要写这个笔记: 1,这本书的中文版翻译了太垃圾,没法阅读。阅读英文原版,可以很好的理解作者的思路。作此笔记备忘 2,一直以来学习LINUX kernel的知识缺乏系统化,借对这本书的学习,系统化的学习一下LINUX kernel。 3,自己一直在做一个too small,too simple的单进程,特权模式,64bit保护模式的称不上OS的OS,已经做完了bootloader, 构思kernel的实现的时候,困惑在内存管理的实现上,阅读这本书,希望能有利于自己的OS的编写。 4,克服惰性,多读书,希望一天能阅读5页,争取半年内阅读完这本原版700多页的巨著。 不足: 我不可能完全理解LINUX 内存管理的精髓,肯定有很多地方理解错误。希望大家能够指正,以便提高,谢谢。 学习方法: 可能您第一次阅读的时候很多地方都不理解,不用担心。那您可能需要阅读一些文件系统的知识。 或者阅读全部笔记后,再回头阅读,有些地方您就理解了。 言归正传: 一、概要 可用工具 CodeViz: 生成代码调用关系图的工具,这个工具我现在还没有去使用,有兴趣的可以自己试试去建立调用关系图。 http://www.csn.ul.ie/~mel/projects/codeviz/ Linux cross reference (LXR): 以web的方式阅读和查找LINUX内核源代码的工具。这个工具安装相当麻烦,我建议直接到它的官方网站直接读代码。 http://lxr.linux.no/linux+v2.6.24/ 模块 LINUX内存管理代码模块主要分为4个部分: 1.Out of memory 代码在mm/oom_kill.c 貌似用于杀进程的时候对内存的操作 2.虚拟内存的分配代码在mm/vmalloc.c

全面介绍Windows内存管理机制

全面介绍Windows内存管理机制及C++内存分配实例 文章整理: https://www.doczj.com/doc/688521279.html, 文章来源: 网络- - 本文背景: 在编程中,很多Windows或C++的内存函数不知道有什么区别,更别谈有效使用;根本的原因是,没有清楚的理解操作系统的内存管理机制,本文企图通过简单的总结描述,结合实例来阐明这个机制。 本文目的: 对Windows内存管理机制了解清楚,有效的利用C++内存函数管理和使用内存。本文内容: 本文一共有六节,由于篇幅较多,故按节发表。 1.进程地址空间 1.1地址空间 ?32|64位的系统|CPU 操作系统运行在硬件CPU上,32位操作系统运行于32位CPU 上,64位操作系统运行于64位CPU上;目前没有真正的64位CPU。 32位CPU一次只能操作32位二进制数;位数多CPU设计越复杂,软件设计越简单。 软件的进程运行于32位系统上,其寻址位也是32位,能表示的空间是232=4G,范围从0x0000 0000~0xFFFF FFFF。 ?NULL指针分区 范围:0x0000 0000~0x0000 FFFF 作用:保护内存非法访问 例子:分配内存时,如果由于某种原因分配不成功,则返回空指针0x0000 0000;当用户继续使用比如改写数据时,系统将因为发生访问违规而退出。 那么,为什么需要那么大的区域呢,一个地址值不就行了吗?我在想,是不是因为不让8或16位的程序运行于32位的系统上呢?!因为NULL分区刚好范围是16的进程空间。 ?独享用户分区 范围:0x0001 0000~0x7FFE FFFF 作用:进程只能读取或访问这个范围的虚拟地址;超越这个范围的行为都 会产生违规退出。 例子: 程序的二进制代码中所用的地址大部分将在这个范围,所有exe 和dll文件都加载到这个。每个进程将近2G的空间是独享的。 注意:如果在boot.ini上设置了/3G,这个区域的范围从2G扩大为3G: 0x0001 0000~0xBFFE FFFF。 ?共享内核分区 范围:0x8000 0000~0xFFFF FFFF 作用:这个空间是供操作系统内核代码、设备驱动程序、设备I/O高速缓存、非页面内存池的分配、进程目表和页表等。 例子: 这段地址各进程是可以共享的。

操作系统内存管理原理

内存分段和请求式分页 在深入i386架构的技术细节之前,让我们先返回1978年,那一年Intel 发布了PC处理器之母:8086。我想将讨论限制到这个有重大意义的里程碑上。如果你打算知道更多,阅读Robert L.的80486程序员参考(Hummel 1992)将是一个很棒的开始。现在看来这有些过时了,因为它没有涵盖Pentium处理器家族的新特性;不过,该参考手册中仍保留了大量i386架构的基本信息。尽管8086能够访问1MB RAM的地址空间,但应用程序还是无法“看到”整个的物理地址空间,这是因为CPU寄存器的地址仅有16位。这就意味着应用程序可访问的连续线性地址空间仅有64KB,但是通过16位段寄存器的帮助,这个64KB大小的内存窗口就可以在整个物理空间中上下移动,64KB逻辑空间中的线性地址作为偏移量和基地址(由16位的段寄存器给处)相加,从而构成有效的20位地址。这种古老的内存模型仍然被最新的Pentium CPU支持,它被称为:实地址模式,通常叫做:实模式。 80286 CPU引入了另一种模式,称为:受保护的虚拟地址模式,或者简单的称之为:保护模式。该模式提供的内存模型中使用的物理地址不再是简单的将线性地址和段基址相加。为了保持与8086和80186的向后兼容,80286仍然使用段寄存器,但是在切换到保护模式后,它们将不再包含物理段的地址。替代的是,它们提供了一个选择器(selector),该选择器由一个描述符表的索引构成。描述符表中的每一项都定义了一个24位的物理基址,允许访问16MB RAM,在当时这是一个很不可思议的数量。不过,80286仍然是16位CPU,因此线性地址空间仍然被限制在64KB。 1985年的80386 CPU突破了这一限制。该芯片最终砍断了16位寻址的锁链,将线性地址空间推到了4GB,并在引入32位线性地址的同时保留了基本的选择器/描述符架构。幸运的是,80286的描述符结构中还有一些剩余的位可以拿来使用。从16位迁移到32位地址后,CPU的数据寄存器的大小也相应的增加了两倍,并同时增加了一个新的强大的寻址模型。真正的32位的数据和地址为程序员带了实际的便利。事实上,在微软的Windows平台真正完全支持32位模型是在好几年之后。Windows NT的第一个版本在1993年7月26日发布,实现了真正意义上的Win32 API。但是Windows 3.x程序员仍然要处理由独立的代码和数据段构成的64KB内存片,Windows NT提供了平坦的4GB地址空间,在那儿可以使用简单的32位指针来寻址所有的代码和数据,而不需要分段。在内部,当然,分段仍然在起作用,就像我在前面提及的那样。不过管理段的所有责任都被移给了操作系统。

Windows内存管理机制及C++内存分配实例(三):虚拟内存

本文背景: 在编程中,很多Windows或C++的内存函数不知道有什么区别,更别谈有效使用;根本的原因是,没有清楚的理解操作系统的内存管理机制,本文企图通过简单的总结描述,结合实例来阐明这个机制。 本文目的: 对Windows内存管理机制了解清楚,有效的利用C++内存函数管理和使用内存。 本文内容: 3. 内存管理机制--虚拟内存 (VM) · 虚拟内存使用场合 虚拟内存最适合用来管理大型对象或数据结构。比如说,电子表格程序,有很多单元格,但是也许大多数的单元格是没有数据的,用不着分配空间。也许,你会想到用动态链表,但是访问又没有数组快。定义二维数组,就会浪费很多空间。 它的优点是同时具有数组的快速和链表的小空间的优点。 · 分配虚拟内存 如果你程序需要大块内存,你可以先保留内存,需要的时候再提交物理存储器。在需要的时候再提交才能有效的利用内存。一般来说,如果需要内存大于1M,用虚拟内存比较好。 · 保留 用以下Windows 函数保留内存块

VirtualAlloc (PVOID 开始地址,SIZE_T 大小,DWORD 类型,DWORD 保护 属性) 一般情况下,你不需要指定“开始地址”,因为你不知道进程的那段空间 是不是已经被占用了;所以你可以用NULL。“大小”是你需要的内存字 节;“类型”有MEM_RESERVE(保留)、MEM_RELEASE(释放)和 MEM_COMMIT(提交)。“保护属性”在前面章节有详细介绍,只能用前 六种属性。 如果你要保留的是长久不会释放的内存区,就保留在较高的空间区域, 这样不会产生碎片。用这个类型标志可以达到: MEM_RESERVE|MEM_TOP_DOWN。 C++程序:保留1G的空间 LPVOID pV=VirtualAlloc(NULL,1000*1024*1024,MEM_RESERVE|MEM_TOP_DOWN,PAGE_READW if(pV==NULL) cout<<"没有那么多虚拟空间!"<

Windows7内存管理机制Superfetch介绍

Windows7内存管理机制Superfetch介绍 Windows seven :内存占用高并不是不好!(Windows7内存管理机制Superfetch介绍) 读过了“森木”管理员的《windows vista wow》之后,受益匪浅。虽说不是成为了一个“专家”,但也对从vista开始引进的新的内存管理机制Superfetch有了一定的了解。发现了很多人一开始(包括我)对于vista、7的内存的使用的误区。一般来说,从XP升的用户大多都认为系统空闲时内存使用越少越好。而到了7的时代(更准确的说是vista之后),这一个本该转变的观念却还迟迟留在大家的记忆里。今天,我看到一篇说7的内存占用太多而换回使用XP的,对此我认为比较遗憾。所以,我又翻开了那本的《windows vista wow》,仔细再次阅读了关于Superfetch的章节。因为不是人人都有这本书。所以在此介绍给大家。同时也是想改变一下大家的观念。从而使更多的用户可以对7充满积极! 介绍之前,我也对我们的管理员Sveir表示感谢,他的《windows vista wow》让我更加的了解的vista(当然,了解vista后才能进一步了解7)。同时我也会引用一些书中的例子等。由于书中的句子比较繁杂,不容易理解。我还会使用图片以及生动的比喻告诉给大家。因为我的理解能力有限,且也是从书中获取的知识,如果有什么讲的不对的话,非常欢迎大家的指正和批评。 在了解Superfetch内存管理机制之前。我们要弄清楚一些概念。下面我就来讲解一下什么叫做“工作集”。 一、工作集的概念和作用 首先,我们从内存讲起。我们可以简单的将内存理解为“数据结构”+“工作集”。也就是说,在内存这个大房子里面有两个房间,一个是“数据结构”房间,另一个是“工作集”房间。那么我们就开始讲什么是“工作集”房间。 我们可以将每一个程序的运行占用的内存当做一个员工,而这些员工要工作的话就必须要走进他们的办公室,然后才能开始工作,那么这些“办公室”就可以理解为工作集了。引用森木的话就是“简单的说,应用程序在运行过程中进程所占用的内存中的工作空间就叫做工作集”。 那工作集的作用是什么呢?就如我刚才说的,是各个员工办公的场所,我们可以想象这些员工来自他们的“家”,也就是硬盘,工作集的作用就是让这些员工从家进入到大厦里(也就是内存里),也可以说,在这个大厦里,门口就是工作集房间,员工进入了工作集才能进入大厦。再次引用森木的话就是“工作集的作用是为了应用程序在运行时将硬盘当中对应的文件引入物理内存中”。 可是我们知道,大厦不能只有工作集一个房间,所有的员工在这个房间里面占用的地方并不是整个大厦(内存)。而工作集房间的面积大小就要看你这个大厦有多大了。如果大一

JVM的内存机制介绍

本文分为两个部分: 1,JVM specification s(JVM规范) 对JVM内存的描述 2,Sun的JVM的内存机制。 JVM specification对JVM内存的描述 首先我们来了解JVM specification中的JVM整体架构。如下图: 主要包括两个子系统和两个组件: Class loader(类装载器) 子系统,Execution engine(执行引擎) 子系统;Runtime data area (运行时数据区域)组件, Native interface(本地接口)组件。 Class loader子系统的作用:根据给定的全限定名类名(如 https://www.doczj.com/doc/688521279.html,ng.Object)来装载class文件的内容到 Runtime data area中的method area(方法区域)。Javsa程序员可以extends https://www.doczj.com/doc/688521279.html,ng.ClassLoader类来写自己的Class loader。 Execution engine子系统的作用:执行classes中的指令。任何JVM specification实现(JDK)的核心是Execution engine,换句话说:Sun 的JDK 和IBM的JDK好坏主要取决于他们各自实现的Execution engine的好坏。每个运行中的线程都有一个Execution engine的实例。 Native interface组件:与native libraries交互,是其它编程语言交互的接口。 Runtime data area 组件:这个组件就是JVM中的内存。下面对这个部分进行详细介绍。

Runtime data area的整体架构图 Runtime data area 主要包括五个部分:Heap (堆), Method Area(方法区域), Java Stack(java的栈), Program Counter(程序计数器), Native method stack(本地方法栈)。Heap 和Method Area是被所有线程的共享使用的;而Java stack, Program counter 和Native method stack是以线程为粒度的,每个线

LINUX系统基本的内存管理知识讲解

内存是Linux内核所管理的最重要的资源之一。内存管理系统是操作系统中最为重要的部分,因为系统的物理内存总是少于系统所需要的内存数量。虚拟内存就是为了克服这个矛盾而采用的策略。系统的虚拟内存通过在各个进程之间共享内存而使系统看起来有多于实际内存的内存容量。Linux支持虚拟内存, 就是使用磁盘作为RAM的扩展,使可用内存相应地有效扩大。核心把当前不用的内存块存到硬盘,腾出内存给其他目的。当原来的内容又要使用时,再读回内存。 一、内存使用情况监测 (1)实时监控内存使用情况 在命令行使用Free命令可以监控内存使用情况 代码如下: #free total used free shared buffers cached Mem: 256024 192284 63740 0 10676 101004 -/+ buffers/cache: 80604 175420 Swap: 522072 0 522072 上面给出了一个256兆的RAM和512兆交换空间的系统情况。第三行输出(Mem:)显示物理内存。total列不显示核心使用的物理内存(通常大约1MB)。used列显示被使用的内存总额(第二行不计缓冲)。 free列显示全部没使用的内存。Shared列显示多个进程共享的内存总额。Buffers列显示磁盘缓存的当前大小。第五行(Swap:)对对换空间,显示的信息类似上面。如果这行为全0,那么没使用对换空间。在缺省的状态下,free命令以千字节(也就是1024字节为单位)来显示内存使用情况。可以使用—h参数以字节为单位显示内存使用情况,或者可以使用—m参数以兆字节为单位显示内存使用情况。还可以通过—s 参数使用命令来不间断地监视内存使用情况: #free –b –s2 这个命令将会在终端窗口中连续不断地报告内存的使用情况,每2秒钟更新一次。 (2)组合watch與 free命令用来实时监控内存使用情况: 代码如下: #watch -n 2 -d free

内存管理以及内存管理单元简介(MMU)

MMU简介 1.概念 MMU是Memory Management Unit的缩写,中文名是内存管理单元,它是中央处理器(CPU)中用来管理虚拟存储器、物理存储器的控制线路,同时也负责虚拟地址映射为物理地址,以及提供硬件机制的内存访问授权。 虚拟地址映射为物理地址 内存访问授权 另一个概念:内存管理,是指软件运行时对计算机内存资源的分配和使用的技术。其最主要的目的是如何高效,快速的分配,并且在适当的时候释放和回收内存资源。 2.术语 虚拟地址空间——又称逻辑地址空间,CPU看到的使用的地址空间。32位CPU可以使用0~0xFFFFFFFF(4G)的地址空间。 物理地址空间——实际的内存空间,例如一个256M的内存,实际地址空间也就是0~0x0FFFFFFF(256M)。 VA——virtual address,虚拟地址 PA——physical address,物理地址 3.背景 内存有限 内存保护 内存碎片 1)内存有限——交换 程序很大,而内存不够一次装入太大的程序。 在磁盘中分配虚拟内存。进程在内存中执行,可以暂时从内存中交换(swap)出去到备份存储上,当需要时再调回到内存中。 2)内存保护

不同进程使用不同的物理地址空间,必须防止不同进程使用同一块内存产生冲突。 内存保护最基本的思路是操作系统为不同进程分配不同的地址空间。可以是逻辑地址,也可以是实际物理地址。(但如果是实际物理地址,操作系统还要负责实际物理地址的分配调度,任务过重,因此设计MMU减轻操作系统负担,负责逻辑地址到物理地址的映射。) 3)内存碎片 最初操作系统的内存是连续分配的,即进程A需要某一大小的内存空间,如200KB,操作系统就需要找出一块至少200KB的连续内存空间给进程A。随着系统的运行,进程终止时它将释放内存,该内存可以被操作系统分配给输入队列里的其他等待内存资源的进程。 可以想象,随着进程内存的分配和释放,最初的一大块连续内存空间被分成许多小片段,即使总的可用空间足够,但不再连续,因此产生内存碎片。 一个办法是不再对内存空间进行连续分配。这样只要有物理内存就可以为进程进行分配。而实际上,不进行连续分配只是相对的,因为完全这样做的代价太大。现实中,往往定出一个最小的内存单元,内存分配是这最小单元的组合,单元内的地址是连续的,但各个单元不一定连续。这样的内存小单元有页和段。 当然,分段和分页也会产生碎片,但理论上每个碎片的大小不超过内存单元的大小。 另外,操作系统分配给进程的逻辑地址就可以是连续的,通过MMU的映射,就可以充分利用不连续的物理内存。 4.MMU原理 分页 页表查找(映射) 以S3C2440的MMU为例,(ARM920T内核,三星产) MVA——modified virtual address,变换后的虚拟地址。一般是在虚拟地址上再标记上进程号。 4.1分页机制 虚拟地址最终需要转换为物理地址才能读写实际的数据,通过将虚拟地址空间和物理空间划分为同样大小的空间(段或页),然后两个空间建立映射关系。 在虚拟地址空间上划分的空间单元称为页(page,较大的则称为段section)。在物理地址空间上划分的同样大小的空间单元称为页帧(page frame,或叫页框)。Linux上地址空间单元大小为4k。 由于虚拟地址空间远大于物理地址,可能多块虚拟地址空间映射到同一块物理地址空间,或者有些虚拟地址空间没有映射到具体的物理地址空间上去(使用到时再映射)。 S3C2440最多会用到两级页表,以段(Section,1M)的方式进行转换时只用到一级页表,以页(Page)的方式进行转换时用到两级页表。 页的大小有3种:大页(64KB),小页(4KB),极小页(1KB)。

相关主题
文本预览
相关文档 最新文档