当前位置:文档之家› Linux内存管理之slab分配器分析

Linux内存管理之slab分配器分析

Linux内存管理之slab分配器分析
Linux内存管理之slab分配器分析

Linux内存管理之slab分配器分析

一:准备知识:

前面我们分析过了大内存分配的实现机制,事实上,若为小块内存而请求整个页面,这样对于内存来说是一种极度的浪费。因此linux 采用了slab来管理小块内存的分配与释放。Slab最早是由sun的工程师提出。它的提出是基于以下因素考虑的:

1:内核函数经常倾向于反复请求相同的数据类型。比如:创建进程时,会请求一块内存来存放mm结构。

2:不同的结构使用不同的分配方法可以提高效率。同样,如果进程在撤消的时候,内核不把mm结构释放掉,而是存放到一个缓冲区里,以后若有请求mm存储空间的行为就可以直接从缓冲区中取得,而不需重新分配内存.

3:前面我们曾分析过,如果伙伴系统频繁分配,释放内存会影响系统的效率,以此,可以把要释放到的内存放到缓冲区中,直至超过一个阀值才把它释放至伙伴系统,这样可以在一定程度上缓减减伙伴系统的压力

4:为了缓减“内碎片”的产生,通常可以把小内存块按照2的倍数组织在一起,这一点和伙伴系统类似

二:slab分配器概貌:

Slab将缓存分为两种:一种是专用高速缓存,另外一种是普通高速缓存。请注意,这里所说的高速缓存和硬件没有必然的关系,它只是slab分配器中的一个软件概念。

专用高速缓存中用来存放内核使用的数据结构,例如:mm,skb,vm等等

普通高速缓存是指存放一般的数据,比如内核为指针分配一段内存

所有的高速缓存区都通过链表的方式组织在一起,它的首结点是cache_chain

另外,普通高速缓存将分配区分为32*(2^0),32*(2^1),32*(2^2) ….32*(2^12)大小,共13个区域大小,另外,每个大小均有两个高速缓存,一个为DMA高速缓存,一个是常规高速缓存。它们都存放在一个名这cache_size的表中.

Slab分配器把每一个请求的内存称之为对象(和oop设计方法中的对象类似,都有初始化与析构).对象又存放在slab中.slab又按照空,末满,全满全部链接至高速缓存中.如下图所示:

slab

对象

缓冲区

slab

三:slab分配器相关的数据结构:

高速缓存:

typedef struct kmem_cache_s kmem_cache_t;

struct kmem_cache_s {

struct array_cache *array[NR_CPUS];/*per cpu结构,每次分配与释放的时候都先从这里取值与存值*/

unsigned int batchcount; /*array[NR_CPUS]中没有空闲对象时,一次为数组所分配的对象数*/

unsigned int limit; //允许的空闲对象的最大值

unsigned int batchcount; //一次要填充给数组的对象数,或者一次要释放的对象数

unsigned int touched; //如果从该组中分配了对象,则把此值置为1

}

struct kmem_list3 {

struct list_head slabs_partial; /*末满的slab链 */

struct list_head slabs_full; /*满的slab链*/

struct list_head slabs_free; /*完全空闲的slab链*/

unsigned long free_objects; /*空链的对象数*/

int free_touched;

unsigned long next_reap;

struct array_cache *shared; /*全局shar数组。当array[NR_CPUS]满了之后,会将对象释放至此,array[NR_CPUS]请求对象时,会先在这里取得对象 */

}

Slab的数据结构

struct slab {

struct list_head list; /*用来构成链表*/

unsigned long colouroff; /*着色机制,后面会详解*/

void *s_mem; /* 首个对象的起始地址 */

unsigned int inuse; /* slab中的使用对象个数 */

kmem_bufctl_t free; /*slab中的第一个空闲对象的序号*/

};

四:slab中的着色机制

在我们分析详细的代码之前,有必要首先了解一下slab的着色机制。

Slab中引用着色机制是为了提高L1缓冲的效率。我们知道linux是一个兼容性很高的平台,但现在处理器的缓冲区方式多种多样,有的每个处理器有自己的独立缓存。有的很多处理器共享一个缓存。有的除了一级缓存(L1)外还是二级缓存(L2),因此,linux 为了更好的兼容处理平台,只优化了一级缓存

为了下面的分析,我们不妨假设一下:假设处理器每根缓存线为32字节,L1大小为16K (可以算出共有512根缓存线),每根缓存线与主存交互的大小也被称为cache line ,在这个例子中cache line是32字节

只有当处理器检测到缓存线冲突时(读或者写失效),才会与主存交互,例如当处理器检测到缓存读失效,会将相应地址所在的32字节读取到缓存。有这里有一点要注意的是,缓存与主存的交互是按照块大小来的,即一次读或者写32字节。而且每条缓存线所读取的地址不是任意的。例如:第0根缓存总线只能读取 0~32 16K ~ 16K+32 32K~32K+32的地址

Slab分配器要求对象按照cache line对齐,我们来看一下,如果没有对齐,会造成什么样的影响:

假设对象为20个字节,一个对象的起始地址是0 位于第0条缓存线。第二个地址的0~9位于第0条缓存线,10~19位于第1条缓存线。可以想象一下,如果要读入第二个对象,就会刷新二个缓存,共64个字节的数据。若是按照cache line对齐,则只要刷新一次高速缓存,只要交互32字节的数据。

当然,如果对象大小太小,我们是以cache line折半来对齐的,这我们在后面的代码中可以看到

讨论完cache line对齐之后,我们再来看看什么叫着色。

假设现在有这样的两个对象A,B A位于0~64于,第0条缓存线。B位于16K之后的64个字节,也是第0条缓存线。我们在上面的分析可以看到,常用的数据结构经常放在结构体的前面。此时就会有高32位的访问频率大大高于低32位的访问频率。假设此时,访问A之后再来访问B。高位访问50次,低位访问10次。

我们来看看这时的情况:

处理器在访问完A后,再访问B的地址,发现B需要缓冲线0,则把缓冲线0的数据写回主存,再读入B的值,访问完B后,发现又要访问A,此时,又把B的值写回主存,再读入A的值…

按这样计算,共需要和主存交互50*2 + 10*2 = 120次

我们不妨把B后移32字节,这样B的高32位就位于缓存线1 低32位处于缓存线2。这时,访问完A后,访问B只需要把B的数据读科第1,第2缓存线,直接交互就行了。

如果经常有这样的情况发生,就会产生极大的“颠簸”,极度影响系统效率

基于这样的情况。Slab 分器配把每一个slab都错开了,都往后移了一个或者是多个cache line

Linux 内存管理之slab 分配器分析(续二)

Linux内存管理之slab分配器分析(续三)

Linux内存管理之slab分配器分析(续四)

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

操作系统内存管理

操作系统内存管理 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/1414146540.html, 新浪博客地址:https://www.doczj.com/doc/1414146540.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。而操作系统也必须能感知硬件的拓扑结构,优化系统的访存。

分支器、分配器

分支器、分配器介绍 (福建金钱猫公司) 分支/分配器是一种高频宽带信号功率分配的无源器件。它的带宽目前已达到5—1000MHz,其结构简单,价格低廉,工作不需要电源,广泛用于HFC有线电视领域。器件分为室内型和野外型两种结构,以适应不同环境的需要。野外型器件除具有防水功能外,通常还具有过流功能,以适应需要通过电缆供电的网络。 分配器 能将卫星天线上高频头接收到的信号,经同轴电缆均等地分成多路的电子电路,我们称它为分配器,或叫功率分配器。常见的有两种:一种是有源的,其供电取自于卫星接收机向天线高频头的供电,有源分配器多见于六分配器、八分配器和少数四分配器。另一种是无源分配器,它是通过电感、电阻和电容进行无源分配的。分配器是CATV网络前端设备中一个重要组成部件(后端常用分支器)。 分支器 分支器是在一个主输出信号顺利通过的情况下,能分出一部分低于主输出信号电平的一个或几个相等信号的电子电路,它也具有很好的隔离性。只要在主输出口接有标准阻抗的同轴电缆线或终端匹配电阻,分支口开路或短路对输入口阻抗和网络传输影响不大。有线电视网络运用这个特性来连接各用户终端主输入口。但要求每条线路终端主输出口必须接75Ω标准负载,既不能开路也不能短路,也不允许接用。 分支分配器区别 1、分配器的端口标识为:IN、OUT、OUT这是一分二的分配器。分支器的端口标识为:IN、OUT、TAP、TAP这是一分二的分支器。 2、分配器出来的信号都一样的比如说306分配器就是说有一个进口(IN)三个出口(OUT) 每个出口衰减的DB数是6DB。分支器可以连级接,而分配器则不能连级接,因为分配器连级接衰减大。放大器后接一个分配器到电视,两个以上才能到电视的,中间请用分支器。

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。 了解系统内存被分配到了什么地方,系统在什么情况下进行内存整理是系统管理的重

有线电视分支器 分配器 放大器 区别

有线电视(CATV)分支器,分配器,放大器区别 分配器:普通家庭有多台电视,可以用这种。它可以将一路入户的有线信号分成多路信号输出到电视,输出信号相互隔离,不会发生串扰的现象。各路输出的信号对比输入信号会有一定的衰减,衰减也都相同。 分支器:TAP口又叫BR口,意思为分支,如果有将分支设备串联需要的时候,就要用到分支器。它的形式与分配器类似。但它的输出只有一个OUT口,其余为若干个BR口,OUT口的衰减很小,为分支器与分支器之间的连接接口。BR口的信号衰减较大,不可再作为分支器串联的干路连接,一般直接连接到终端。 放大器:如果入户信号不强,分配给多个电视后,由于分配器会产生对信号衰减的副作用,电视画面会出现较大的雪花。这时可以在分配器前加一个放大器,增强信号增益,减少画质劣化。 即使不使用分配器,也可以使用放大器放大信号。 南京中卫1.5M正馈天线城市有线电视网络通到每个用户家里的信号,一般可以保证达到一个终端的收看标准,当您家中有多台电视机时,就要加装分配器,以保证多台电视机的收看。分配器是有衰减的,但是它的衰减也是平均的,以三分配器为例,它的三个分配端口的衰减量都是一样的6dB, 而您现在使用的是分支器,它的各输出端的衰减是不一样的,OUT端是主输出端,它的衰减叫插入损耗,仅仅只有1-2dB,而BR(branch)端是分支端,它的衰减量叫分支衰减量,依型号不同在6-24dB,这也就是您接OUT清楚而接BR不行的原因。所以您只要将分支器换成分配器就可以了,只要您家信号强度比较好,接入分配器也是看不出什么衰减的。你需要分四路,就选择四分配器。不要留富余,因为分配数量与衰减量是成正比的。 举个例子:一路信号有80dB通过二分配器204,每个输出口衰减了4dB,成为2路76dB的信号,同样80dB信号通过一分支器108,分支口输出衰减8dB,成为72dB,另一路主路输出衰减2dB,成为78dB。如果通过一分支器112,分支口输出衰减12dB,成为68dB,另一路主路输出衰减1dB,成为79dB。这就是分支器和分配器的区别,分配器是平均分配,分支器可以根据需要分得合适的电平。另外在使用时分配器输出口必须阻抗匹配(不能悬空也不能短路)否则会产生反射,干扰其他用户;分支器的主路输出也必须阻抗匹配,但是分支口可以开路或短路。高斯贝尔高频头 结论:分支器一般用在用户接入口,分配器一般用在分配网络。 1、分支器:常用分为1分支~4分支。例如2FZ08指的是一个输入(in),一个输出(out)插入损耗大约4DB,2个分支口(BR)每个口大约衰减8DB。 分配器:常用为2~4分配,例如2FP,两个输出口衰减是一样的。 2、分配器就是把一路信号平均分成几路相等的信号输出,即每个输出口的衰减 值一样大。

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/1414146540.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位指针来寻址所有的代码和数据,而不需要分段。在内部,当然,分段仍然在起作用,就像我在前面提及的那样。不过管理段的所有责任都被移给了操作系统。

分支器和分配器的区别

1、分配器的端口标识为:IN、OUT、OUT这是一分二的分配器 2、分支器的端口标识为:IN、OUT、TAP、TAP这是一分二的分支器 3、分配器出来的信号都一样的比如说306分配器就是说有一个进口(IN)三个出口(OUT) 每个出口衰减的DB数是6DB。 4、分支器可以连级接,而分配器则不能连级接,因为分配器连级接衰减大。放大器后接一个分配器到电视,两个以上才能到电视的,中间请用分支器。 5、分支器与分配器最大的区别就在于输出到电视的输出口不同,分支器输出到电视的是BR输出口,而分配器是OUT 输出口。 6、分配器对信号进行同等的分配,在有线电视经常用到,2 3 4 6 8分配器或更大。 7、分支器从主路上取出少部分信号送到分支口的功率电平

分配器件称为分支器。 8、分支器不一样,比如说410分支器是一个进口(IN) 5个出口其中只有一个(OUT)口其余4个是BR(分支)口BR 口衰减是10DB OUT口衰减是2DB 也就是我们常说的插入损耗。在安装时,分配器的每个输出口子,绝对不可以空载,否则会由于阻抗不匹配的原因造成重影,一般都要求加上阻抗匹配器。而对于某几级的分支器的分支输出口,则关系不大。 9、分支/配器区别:分支器输出、输入的电平不相等,分配器输出、输入的电平完全相等。 10、分支器的OUT输出口是输出给下路需要接分支分配器用的输出口,因为分支器的OUT输出口的衰减很小,所以作为干路的分支设备,使后面串联线路中的电视信号衰减减小,配合干路放大器使整个线路中的信号均衡。 分支器是在一个主输出信号顺利通过的情况下,能分出一部分低于主输出信号电平的一个或几个相等信号的电子电路,它也具有很好的隔离性,只要在主输出口接有标准阻抗的同轴电缆或终端匹配电阻,分支口开路或短路对输入口的网络

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<<"没有那么多虚拟空间!"<

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