当前位置:文档之家› Windows内存管理机制

Windows内存管理机制

Windows内存管理机制
Windows内存管理机制

Windows 2000/XP内存管理机制

冯秋2004-9-27

1 概述 (1)

2 地址空间的布局 (1)

3 地址转换机制 (2)

4 用户空间内存分配方式 (4)

5 系统内存分配 (5)

6 缺页处理 (5)

7 工作集 (6)

8 物理内存管理 (7)

9 其他内存相关机制 (8)

1概述

Windows 2000/XP内存管理器位于Ntoskrnl.exe文件中,硬件抽象层中没有内存管理器

的任何部分。

内存管理器是完全可重入的,支持多进程并发执行。

内存管理器组成部分:

1)一组执行体系统服务程序:用于虚拟内存的分配、回收和管理。

2)一个转换无效和访问错误陷阱处理程序:用于解决硬件检测到的内存管理异常,并代表进程将虚拟页面装入内存。

3)运行在六个不同的核心态系统线程上下文中的几个关键组件:

——工作集管理器:优先级16,每秒钟被平衡集管理器(一个内核创建的系统线程)调用一次。

——进程/堆栈交换程序:优先级23,完成进程和内核线程堆栈的换入和换出操作。

——已修改页面写入器:优先级17,将修改链表上的脏页写回到适当的页文件。

——映射页面写入器:优先级17,将映射文件中脏页写回磁盘。

——废弃段线程:优先级18,负责系统高速缓存和页面文件的扩大和缩小。

——零页线程:优先级0,将空闲链表中的页面清零。

2地址空间的布局

Win32环境下,32位的地址空间转化为4GB的虚拟内存。默认情况下,将一半(2GB)

分配给用户进程,另一半(2GB)分配给操作系统。

Windows 2000/XP Advanced Server版本和Windows 2000/XP Data Center版本支持一个

引导选项(Boot.ini中通过/3GB标识激活),允许用户拥有3GB地址空间,留1GB给操作系统。

对于要访问整个3GB地址空间的进程,进程映像文件必须在映像头设置

IMAGE-FILE-LARGE-ADDRESS-AWARE标识,否则系统将保留第3个GB的地址空间。可以通过指定链接标识/LARGEADDRESSAW ARE来设置该标识。如果与此链接程序开关相链接,则可以使用3GB用户方式地址空间。

2GBWindows 2000/XP用户地址空间分布

——NULL指针分配的分区:0x0~0xFFFF

——进程私有地址空间:0x10000~0x7FFEFFFF

——64KB拒绝访问区域:0x7FFF0000~0x7FFFFFFF,阻止线程跨过用户/系统边界传送缓冲区。

Windows 2000/XP用户地址空间系统变量

——MmHighestUserAddress:描述最高用户地址(对于x86 2GB用户空间为0x7FFEFFFF)

——MmUserProbeAddress:描述最高用户地址+1

性能计数器:Windows 2000/XP中可利用性能计数器得到系统虚拟内存的使用信息,和

单个进程地址空间的使用情况。

x86系统地址空间分布

——0x80000000~0x9FFFFFFF:引导系统(Ntoskrnl.exe和Hal.dll)和非分页缓冲池初始部分的系统代码。

——0xA0000000~0xA3FFFFFF:系统映射视图(如Win32k.sys)或者会话空间。

——0xA4000000~0xBFFFFFFF:附加系统页表项(PTE)或附加系统高速缓存。

——0xC0000000~0xC03FFFFF:进程页表和页目录,描述虚拟地址映射的结构。

——0xC0400000~0xC07FFFFF:超空间和进程工作集列表。

——0xC0800000~0xC0BFFFFF:未使用区域,不可访问。

——0xC0C00000~0xC0FFFFFF:系统工作集链表,描述系统工作集的工作集链表数据结构。

——0xC1000000~0xE0FFFFFF:系统高速缓存,用来映射在系统高速缓存中打开的文件的虚拟空间。

——0xE1000000~0xEAFFFFFF:分页缓冲池,可分页系统内存堆。

——0xEB000000~0xFFBDFFFF:系统页表项和非分页缓冲池。

——0xFFBE0000~0xFFFFFFFF:系统性故障转储信息和硬件抽象层(HAL)使用区域。

会话空间:用来映射一个用户的会话信息。

——进程创建时,会将会话空间映射到属于该进程会话的页面。

——会话是由进程和其他系统对象组成,每个会话有私有的GUI数据结构,以及Win32子系统进程(Csrss.exe)和登录进程(Winlogon.exe)的拷贝。

——会话管理器进程(Smss.exe)负责创建新的会话。

3地址转换机制

用户应用程序以32位虚拟地址方式编址,每个虚拟地址与一个称作“页表项”(PTE)

的结构有关,它包含了虚拟地址映射的物理地址。

1.虚拟地址变换

x86系统利用二级页表结构实现虚拟地址向物理地址的变换。

x86系统中,32位虚拟地址分成三个部分:页目录索引(10 bit)、页表索引(10 bit)、

字节索引(12 bit)。

虚拟地址变换的基本步骤:

——内存管理的硬件设备定位当前进程的页目录;

——页目录索引指出页目录项在页目录中的位置,页目录项中的页框号描述了映射

虚拟地址所需页表的位置;

——页表索引指出页表项在页表中的位置,页表项描述了虚拟页面在物理内存的位

置;

——当页表项指向的页面有效时,字节索引指明物理页内所需数据的地址;若所指

页面无效,则交由内存管理器的故障处理程序处理。

2.页目录

每个进程都有一个单独的页目录,用来映射进程所有页表的位置,其物理地址被保

存在核心进程(KPROCESS)块中。

进程切换时,操作系统设置一个专用的CPU寄存器来通知硬件设备新进程页目录

所在地址。

页目录是由页目录项(PDE)组成,每个页目录项4字节。x86中,描述4GB虚拟

地址空间需要1024张页表,因此页目录索引10位。

3.进程页表与系统页表

进程页表是每个进程私有的,而系统页表被所有进程共享。

当进程创建时,系统空间的页目录项初始化为指向现存的系统页表,但各个进程的

系统空间不完全相同。当系统页表更新时,内存管理器不会立刻更新所有进程页目

录,而是当进程访问新的虚拟地址时才更新进程页目录。

性能监视器中的空闲系统页表项计数器表示了可用系统页表项的数目,也可在

HKLM\SYSTEM\CurrentControlSet\Control\SessionManager\MemoryManagement\Sys

temPages中设置需要的页表项数量。

4.页表项

有效的页表项有两个主要的域:

(1)包含数据的物理页面的页框号,或内存中某页面的物理地址的页框号;

(2)一些描述页的状态和保护限制的标志位。

——访问位:某页首次被读写时,置为“1”

——修改位:某页首次被写时,置为“1”

——写位:为0时,对应页只读,为1时,对应页可读写

——多处理器的x86系统中,有个附加的由软件实现的写位,用来表示某页已

经被一个运行在多个处理器上的线程写入。

x86中(非PAE系统),映射4GB地址空间需要1024张页表,每个页表含1024个

页表项,每个页表项4字节,因此页表索引为10 bit。

5.快表TLB

x86提供了关联存储器数组形式的高速缓存,称为快表。它是一个向量,其存储单

元能被同时读取并与目标值比较。

快表中每个项的标志符部分保存了虚拟地址的一部分,数据部分保存了物理页号及

对应页的保护类型和状态。

将常用的虚拟地址记录在快表项中,减少了对内存的访问,加快了虚拟地址到物理

地址的变换。

如果一个虚拟地址不在快表中,它可能仍在内存中,需要对内存多次访问来找到它。

当一个页表项由无效变为有效时,内存管理器会调用内核例程将新页表项装入快

表,x86中,装入快表不需要软件干预。

4用户空间内存分配方式

首先介绍两个与内存分配相关的数据结构(虚拟地址描述符和区域对象),然后介绍三种管理应用程序内存的方法。

1.虚拟地址描述符

虚拟地址描述符(V AD)用来描述哪些虚拟地址已经在进程地址空间中被保留。对

个进程,内存管理器都维持一棵虚拟地址描述信息树,用来描述进程地址空间状态。

当进程保留地址空间,或映射一个内存区域时,就创建一个V AD来保存分配请求

所提供的信息。当线程首次访问一个地址时,需找到一个包含被访问地址的V AD,

利用所得信息填充页表项。

2.区域对象

区域对象在Win32中也称文件映射对象,表示可以被两个或多个进程共享的内存

块,也可被映射到页文件或外存文件。

主要作用

——将可执行映像装入内存

——访问高速缓存文件中的数据

——将文件映射到进程地址空间,不必进行文件I/O

每个打开文件都有一个单独的区域对象指针结构,由三个32位指针组成:指向数

据控制区域的指针、指向共享的高速缓存映射的指针、指向映像控制区域的指针。

CreatFileMapping函数可以创建区域对象;OpenFileMapping打开有名字的区域;

可通过句柄继承或句柄复制访问区域对象;设备驱动程序可使用ZwOpenSection,

ZwMapViewOfSection,ZwUnmapOfSection函数操纵区域对象。

3.以页为单位的虚拟内存分配方式

适合于大型对象或结构数组

进程地址空间的页面有三种状态:空闲、被保留、被提交;保留和提交功能是通过

Win32 VirtualAlloc和VirtualAllocEx函数实现的。

应用程序可以同时进行保留和提交,也可以先保留地址空间,当需要时再向地址空

间提交物理页面,这样可以减少内存的使用。

VirtualFree或VirtualFreeEx函数用来回收页面或释放地址空间。回收的内存仍然被

保留,而释放的内存是空闲的。

4.内存映射文件

适合于大型数据流文件以及多个进程之间的数据共享

内存映射文件用来保留一个地址区域,并将磁盘文件提交给该区域,用于3个目的

——加载和执行.exe和.dll文件,可节省应用程序启动所需时间

——访问磁盘数据文件,减少文件I/O

——实现多个进程间的数据共享

利用区域对象实现这些功能,因为区域对象可以链接到打开的磁盘文件(映射文

件),或已提交的内存(提供共享内存)。

进程要访问非常大的区域对象,可以通过调用MapViewOfFile函数映射区域对象的

一部分(区域视图),并指定映射范围。

5.堆功能

内存堆的应用程序内存管理方法适合于大量的小型内存申请

堆是保留的地址空间中一个或多个页组成的区域,可由堆管理器进一步划分和分配

堆管理器用来分配和回收可变内存,其函数位于Ntdll.dll和Ntoskrnl.exe中。

进程启动时有一个缺省堆,通常为1MB,它在进程生命周期中不能被释放;而

HeapCreat函数创建的私有堆可以用HeapDestroy来释放。

从缺省堆中分配内存时,先调用GetProcessHeap函数得到句柄,再调用HeapAlloc

和HeapFree来分配和回收内存块。

5系统内存分配

系统初始化时,创建了两种动态大小的内存缓冲池来分配系统内存,ExAllocatePool函

数可从缓冲池中分配和回收内存:

——非分页缓冲池:由长驻物理内存的系统虚拟地址区域组成。

——分页缓冲池:系统空间中可以被分页和换出的虚拟内存区域。

两种非分页缓冲池:一般情况下使用;4页缓冲池在非分页缓冲池已漫且不允许分配失

败时使用。

分页缓冲池:单处理器系统3个,多处理器系统5个

分页/非分页缓冲池初始大小依赖于系统物理内存大小,可设置

HKLM\SYSTEM\CurrentControlSet\Control\SessionManager\MemoryManagement的Nonpaged PoolSize和PagedPoolSize值改变缓冲池大小。

快速内存分配机制——后备链表:仅包含固定长度的块,因此不必查找适合分配大小的

空闲内存。

若后备链表为空时,必须从分页或非分页缓冲池中进行分配。可使用

ExInitializeNpagedLookasideList和ExInitializePagedLookasideList函数按照频繁分配的数据结构大小创建后备链表。

6缺页处理

对无效页面的一次访问称为缺页错误,由内存管理故障处理程序解决。

1.四个基本类型的无效页表项

页文件:所需页没有驻留在内存,而是驻留在页文件中,并引发页面调入操作。

请求零页:所需页是零页面,此时会给进程工作集添加一个由零初始化的页。

转换:所需页面在内存中的后备链表、修改链表或修改尚未写入链表。此时从链表

中删除此页,并添加到工作集。

未知:页表项为0,或页表不存在。此时需检查V AD以确定虚拟地址是否被提交。

2.一个特例——原型页表项

区域对象第一次被创建时,同时创建原型页表项,它用于实现页面共享。

当共享页面为有效时,进程页表项和原型页表项都指向包含数据的物理页。

当共享页面无效时,进程页表项指向原型页表项,而原型页表项描述被访问的页面的状

态(活动/有效、转换、修改尚未写入、请求零页、页文件、映射文件6种)

3.页面调入I/O

当必须向文件(页或映射文件)发出读操作来解决缺页问题时,将产生页面调入I/O。

页面调入I/O操作是同步的,线程会一直等待I/O完成。

当进行调页I/O时,进程中的其他线程仍可以同时处理缺页错误,因此在I/O结束

时页面调度程序必须识别如下情况:冲突页错误、页面从虚拟地址空间中被删除、

页面保护限制发生变化、原型页表项引发错误。

4.冲突页错误

同一进程中的另一线程或另一进程也对正在被调入的页面产生缺页错误,称为冲突

页错误。

页面调度程序检测到冲突页错误时,会对页框号数据库项中的特定事件发出等待操

作。当I/O完成后,第一个获得页框号数据库锁的线程负责执行完成页面调入操作。5.页文件

虚拟存储器在磁盘上的部分称为页文件。内存=物理内存+页文件。

性能计数器可以检查被提交的进程私有内存使用情况,但无法确切知道一个进程提交的

私有内存中有多少常驻内存,多少在页文件中。

Windows 2000/XP最多支持16个页文件。

系统启动时,会话管理器进程读取页文件链表,并检查

HKLM\SYSTEM\CurrentControlSet\Control\SessionManager\MemoryManagement\Paging Files打开页文件,如果没有,则创建一个缺省的20MB页文件。系统运行期间不能删除打开的页文件。

系统进程为每个页文件都维持一个打开的句柄,Ntdll.dll中的NtCreatePagingfile系统服

务程序可增加一个新页文件。

7工作集

工作集即在物理内存中保持的虚拟页面的子集,分进程工作集和系统工作集。

1.页面调度策略

取页策略:内存管理器利用请求式页面调度算法及簇方式将页面装入内存。当缺页

中断时,将出错页面和它附近的一些页面装入内存,这样可减少读取外存的次数。

置页策略:当线程收到页错误时,内存管理器要使用“置页策略”来确定在物理内

存中放置虚拟页面的最佳位置。

如果当页错误发生时物理内存已满,“置页策略”要决定哪一个虚拟页面必须从内

存中删去来为新的页面腾出空间。多处理器系统中,采用局部先进先出(FIFO)策

略,而单处理器系统中,采用最近最久未使用(LRU)替换策略。

2.工作集管理

系统初始时,所有进程缺省的工作集最大最小值相同。有“增大调度优先级”权限

的进程可用SetProcessWorkingSet函数来更改缺省值,但不能超过内核变量

MmMaximumWorkingSetSize中的最大值。

当物理内存变得很低时,工作集管理器自动修剪工作集,以增加可用空闲内存数量。

有一系列内核控制变量描述工作集扩展和修剪,但这些值是确定的,不能被注册值

调整。

3.平衡集管理器和交换程序

系统初始化时创建平衡集管理器,用来对工作集进行调整。工作集管理器也是运行在平

衡集管理器线程环境下的一个例程。

平衡集管理器等待两个事件对象

——1秒周期计时器到期后产生事件,并经历以下4步

平衡集管理器每被唤醒4次就唤醒交换程序;检查后备链表,必要时调整其深度;

寻找处于CPU饥饿状态而需提高其优先级的线程;调用工作集管理器。

——内部工作集管理器事件,即工作集需要调整时

交换程序:即KeSwapProcessOrStack例程,用来寻找一段时间内一直处于等待状态的

线程,将其内核堆栈转移以收回物理内存。

4.系统工作集

系统工作集用来管理操作系统中可分页的代码和数据,其中可驻留5种页面:系统

高速缓存页面;分页缓冲池;Ntoskrnl.exe中可分页的代码和数据;设备驱动程序

中可分页的代码和数据;系统映射视图。

系统工作集最大最小值是在系统初始化时计算的,基于物理内存数量和系统是

professional或server。

8物理内存管理

页框号数据库用来描述物理内存中各页面的状态,有效页表项指向页框号数据库中的

项,页框号数据库项又指回此页表。原型页框号指回原型页表项。

页面可处于活动、过渡、后备、修改、修改不写入、空闲、零初始化和损坏不可用8

种状态,除活动和过渡之外,其余6种组成了链表。

1.动态页链表

当需要一个零初始化的页面时,首先访问零页链表,若为空,则从空闲链表中选取

一页并零初始化,若也为空,则从后备链表中选取一页并零初始化。

——零页链表是由零页线程(优先级为0)从空闲链表中移过来的,当空闲链表中

有8个或8个以上页时激活零页线程。

当不需要零初始化页面时,首先访问空闲链表,若为空,则访问后备链表。

当进程放弃一个页面时,如果页面未修改过,则加入后备链表;如果修改过,则加

入修改链表。

进程撤销时,将所有私有页面加入空闲链表。对页文件支持的区域最后一次访问结

束时,页面加入空闲链表。

当修改页链表太大,或零初始化和后备链表的大小低于最小值时,唤醒“修改页面

写回器”线程,将页面写回外存,并将页面移入后备链表。

2.修改页面写回器

由两个系统线程组成,优先级都为17

——MiModifiedPageWriter:将修改页写回页文件

——MiMappedPageWriter:将修改页写入映射文件

触发修改页面写回器的事件

——修改页面数量大于内核变量MmModifiedPageMaximum指定值

——可利用页数量小于内核变量MmMinimumFreePages指定值

——MiMappedPagesTooOldEvent事件:该事件在预定的数秒后(缺省为300秒,

可用注册值修改)产生,将映射页面写入外存

若页面写入外存时正在被另一线程共享,则I/O完成后不会将此页移入后备链表。

3.页框号数据结构

页框号数据库项是定长的,不同页框号类型,包含的域也不同(参见图4-28)

几个基本的域

——页表项地址:指向此页页表项的虚拟地址

——访问计数:对此页的访问数量

——类型:该页框号表示的页面状态(8种)

——标识:包含修改状态、原型页表项、奇偶校验错误、正在读取或写入等信息。

——初始页表项的内容

——页表项的页框号:指向该页面页表项的页表页的物理页号

9其他内存相关机制

1.锁内存

可以通过两种方式将页面锁在内存中

——设备驱动程序调用核心态函数MmProbeAndLockPages,MmLockPagableCodeSection,mLockPagableDataSection,LockPagableSectionByHandle。解锁之前锁定的页面一直在内存中。

——Win32应用程序调用VirtualLock函数锁住工作集中页面,但不能防止调页。

2.分配粒度

系统按照分配粒度定义的整型边界对齐每个保留的进程地址空间区域,系统分配粒

度值可通过GetSystemInfo函数找到,目前为64KB。

保留地址空间时,保证区域大小是系统页大小倍数。

3.内存保护机制

4种基本方式

——所有系统范围内核心态组件使用的数据结构和缓冲池只能在核心态下访问,用户线程不能访问。

——每个进程有独立私有的地址空间,其他进程的线程不能访问。(与其他进程共享页面或另一进程具有对进程对象的虚拟内存读写权限时除外)

——除虚拟到物理地址转换的隐含保护外,还提供一些硬件内存保护措施。

——利用共享内存区域对象的存取控制表(ACL)将对共享内存的访问限制在适当权限的进程中。

4.写时复制

当进程映射区域对象的写时复制视图时,内存管理器直到页面修改时才进行复制,

而不是在映射视图的同时,这样可以节约物理内存。

5.地址窗口扩充

地址窗口扩充(AWE)函数集可使进程能够访问更多的物理内存,步骤如下:

——分配要使用的物理内存:AllocateUserPhysicalPages函数(需锁内存页面的权限)——创建一个虚拟地址空间作为窗口用来映射分配好的物理内存:VirtualAlloc函数

和MEM_PHYSICAL标识

——将内存映射到窗口:MapUserPhysicalPages或MapUserPhysicalPagesScatter函

AWE函数分配和映射内存的限制

——页面不能在进程间共享

——同一物理页面不能映射到同一进程的多个虚拟地址上

——页保护可读/写

6.物理地址扩展

物理地址扩展(PAE)的内存映射模式允许访问64GB物理内存。

物理地址扩展模式下,虚拟地址划分为4个域:页目录指针索引(2 bit)、页目录索

引(9 bit)、页表索引(9 bit)、页内字节偏移(12 bit)。

物理地址扩展模式之所以能对更大范围的内存编址,是因为页目录项和页表项都由

32位扩展到了64位。

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

操作系统内存管理

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

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

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

北理工操作系统内存管理实验报告

实验三:内存管理 班级: 学号:

姓名: 一、实验目的 1.通过编写和调试存储管理的模拟程序以加深对存储管理方案的理解; 2.熟悉虚存管理的页面淘汰算法; 3.通过编写和调试地址转换过程的模拟程序以加强对地址转换过程的了解。 二、实验要求 1.设计一个请求页式存储管理方案(自己指定页面大小),并予以程序实现。 并产生一个需要访问的指令地址流。它是一系列需要访问的指令的地址。为不失一般性,你可以适当地(用人工指定地方法或用随机数产生器)生成这个序列。 2.页面淘汰算法采用FIFO页面淘汰算法,并且在淘汰一页时,只将该页在页 表中抹去。而不再判断它是否被改写过,也不将它写回到辅存。 3.系统运行既可以在Windows,也可以在Linux。 三、实验流程图

图1 页式存储管理程序参考流程 四、实验环境 硬件设备:个人计算机。 系统软件:windows操作系统,Visual C++6.0编译环境。 五、实验结果

说明:模拟产生35个指令地址,随机产生20个指令地址进行排队,假设主存中共有10个工作集页帧。将前9个指令调入内存,因为前9个指令中,页号为13的指令有两个,所以调入内存中共有8页。此时主存中还有两个空闲帧。此时按刚才随机顺序进行访问指令工作。前9页因都在主存中可直接调用。第10个随机地址为页号为5的指令,也在主存中,也可直接调用。页号为24,3因不在主存中,需要调用进主存。此时主存已满。然后主存需要进行调用页号为27号的指令,因主存已满,需要执行FIFO算法,将最先进入主存的页号为30的指令调出,将27号放入第1000000帧。以后需要调用的页面按照存在就无需调用,否则按FIFO原则进行调页工作。 六、实验感想 七、实验代码 #include

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+逻辑地址的偏移部分(注意!!)(段与段可能会重叠)

全面介绍Windows内存管理机制

全面介绍Windows内存管理机制及C++内存分配实例 文章整理: https://www.doczj.com/doc/491559051.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高速缓存、非页面内存池的分配、进程目表和页表等。 例子: 这段地址各进程是可以共享的。

操作系统课程设计--连续动态分区内存管理模拟实现

(操作系统课程设计) 连续动态分区内存 管理模拟实现

目录 《操作系统》课程设计 (1) 引言 (3) 课程设计目的和内容 (3) 需求分析 (3) 概要设计 (3) 开发环境 (4) 系统分析设计 (4) 有关了解内存管理的相关理论 (4) 内存管理概念 (4) 内存管理的必要性 (4) 内存的物理组织 (4) 什么是虚拟内存 (5) 连续动态分区内存管理方式 (5) 单一连续分配(单个分区) (5) 固定分区存储管理 (5) 可变分区存储管理(动态分区) (5) 可重定位分区存储管理 (5) 问题描述和分析 (6) 程序流程图 (6) 数据结构体分析 (8) 主要程序代码分析 (9) 分析并实现四种内存分配算法 (11) 最先适应算 (11) 下次适应分配算法 (13) 最优适应算法 (16)

最坏适应算法......................................................... (18) 回收内存算法 (20) 调试与操作说明 (22) 初始界面 (22) 模拟内存分配 (23) 已分配分区说明表面 (24) 空闲区说明表界面 (24) 回收内存界面 (25) 重新申请内存界面..........................................................26. 总结与体会 (28) 参考文献 (28) 引言 操作系统是最重要的系统软件,同时也是最活跃的学科之一。我们通过操作系统可以理解计算机系统的资源如何组织,操作系统如何有效地管理这些系统资源,用户如何通过操作系统与计算机系统打交道。 存储器是计算机系统的重要组成部分,近年来,存储器容量虽然一直在不断扩大,但仍不能满足现代软件发展的需要,因此,存储器仍然是一种宝贵而又紧俏的资源。如何对它加以有效的管理,不仅直接影响到存储器的利用率,而且还对系统性能有重大影响。而动态分区分配属于连续分配的一种方式,它至今仍在内存分配方式中占有一席之地。 课程设计目的和内容: 理解内存管理的相关理论,掌握连续动态分区内存管理的理论;通过对实际问题的编程实现,获得实际应用和编程能力。

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

操作系统课程设计内存管理

内存管理模拟 实验目标: 本实验的目的是从不同侧面了解Windows 2000/XP 对用户进程的虚拟内存空间的管理、分配方法。同时需要了解跟踪程序的编写方法(与被跟踪程序保持同步,使用Windows提供的信号量)。对Windows分配虚拟内存、改变内存状态,以及对物理内存(physical memory)和页面文件(pagefile)状态查询的API 函数的功能、参数限制、使用规则要进一步了解。 默认情况下,32 位Windows 2000/XP 上每个用户进程可以占有2GB 的私有地址空间,操作系统占有剩下的2GB。Windows 2000/XP 在X86 体系结构上利用二级页表结构来实现虚拟地址向物理地址的变换。一个32 位虚拟地址被解释为三个独立的分量——页目录索引、页表索引和字节索引——它们用于找出描述页面映射结构的索引。页面大小及页表项的宽度决定了页目录和页表索引的宽度。 实验要求: 使用Windows 2000/XP 的API 函数,编写一个包含两个线程的进程,一个线程用于模拟内存分配活动,一个线程用于跟踪第一个线程的内存行为,而且要求两个线程之间通过信号量实现同步。模拟内存活动的线程可以从一个文件中读出要进行的内存操作,每个内存操作包括如下内容: 时间:操作等待时间。 块数:分配内存的粒度。 操作:包括保留(reserve)一个区域、提交(commit)一个区域、释放(release)一个区域、回收(decommit)一个区域和加锁(lock)与解锁(unlock)一个区域,可以将这些操作编号存放于文件。保留是指保留进程的虚拟地址空间,而不分配物理 存储空间。提交在内存中分配物理存储空间。回收是指释放物理内存空间,但在虚拟地址空间仍然保留,它与提交相对应,即可以回收已经提交的内存块。释放是指将物理存储和虚拟地址空间全部释放,它与保留(reserve)相对应,即可以释放已经保留的内存块。 大小:块的大小。 访问权限:共五种,分别为PAGE_READONLY,PAGE_READWRITE ,PAGE_EXECUTE,PAGE_EXECUTE_READ 和PAGE EXETUTE_READWRITE。可以将这些权限编号存放于文件中跟踪线程将页面大小、已使用的地址范围、物理内存总量,以及虚拟内存总量等信息显示出来。

操作系统-页式虚拟存储管理程序模拟

操作系统-页式虚拟存储管理程序模拟

FIFO页面置换算法 1在分配内存页面数(AP)小于进程页面数(PP)时,当然是最先运行的AP个页面放入内存。 2这时有需要处理新的页面,则将原来内存中的AP个页面最先进入的调出(是以称为FIFO),然后将新页面放入。 3以后如果再有新页面需要调入,则都按2的规则进行。 算法特点:所使用的内存页面构成一个队列。LRU页面置换算法 1当分配内存页面数(AP)小于进程页面数(PP)时,当然是把最先执行的AP个页面放入内存。2当需要调页面进入内存,而当前分配的内存页面全部不空闲时,选择将其中最长时间没有用到的那个页面调出,以空出内存来放置新调入的页面(称为LRU)。 算法特点:每个页面都有属性来表示有多长时间未被CPU使用的信息。 结果分析

#include #include using namespace std; const int MaxNum=320;//指令数 const int M=5;//内存容量 int PageOrder[MaxNum];//页面请求 int Simulate[MaxNum][M];//页面访问过程 int PageCount[M],LackNum;//PageCount用来记录LRU算法中最久未使用时间,LackNum记录缺页数 float PageRate;//命中率 int PageCount1[32]; bool IsExit(int i)//FIFO算法中判断新的页面请求是否在内存中 { bool f=false; for(int j=0;j

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新生代,正常情况下新创建的对象会被分配到新生代,但如果对象占据的内存足够大以致超过了新生代的容量限 制,也可能被分配到老年代;新生代对象的一个特点是最 新、且生命周期不长,被回收的可能性高;

操作系统内存管理原理

内存分段和请求式分页 在深入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.实验目的 通过本次课程设计,掌握了如何进行内存的分区管理,强化了对首次适应分配算法和分区回收算法的理解。 2.实验内容 (1)建立相关的数据结构,作业控制块、已分配分区及未分配分区 (2)实现一个分区分配算法,如最先适应算法、最优或最坏适应分配算法 (3)实现一个分区回收算法 (4)给定一个作业/进程,选择一个分配或回收算法,实现分区存储的模拟管理 图1.流程图

3.实验步骤 首先,初始化函数initial()将分区表初始化并创建空闲分区列表,空闲区第一块的长度是30,以后的每个块长度比前一个的长度长20。 frees[0].length=30 第二块的长度比第一块长20,第三块比第二块长20,以此类推。 frees[i].length=frees[i-1].length+20; 下一块空闲区的首地址是上一块空闲区的首地址与上一块空闲区长度的和。frees[i].front=frees[i-1].front+frees[i-1].length; 分配区的首地址和长度都初始化为零occupys[i].front=0;occupys[i].length=0; 显示函数show()是显示当前的空闲分区表和当前的已分配表的具体类容,分区的有起始地址、长度以及状态,利用for语句循环输出。有一定的格式,使得输出比较美观好看。 assign()函数是运用首次适应分配算法进行分区,从链首开始顺序查找,直至找到一个大小能满足要求的空闲分区为止;然后再按照作业的大小,从该分区中划出一块内存空间分配给请求者,余下的空闲分区仍留在空闲链中。若从链首直至链尾都不能找到一个能满足要求的分区,则此次内存分配失败,返回。这个算法倾向于优先利用内存中低址部分被的空闲分区,从而保留了高址部分的的大空闲区。着给为以后到达的大作业分配大的内存空间创造了条件。它的缺点是低地址部分不断被划分,会留下很多难以利用的、很小的空闲分区,而每次查找又都是从低址部分开始,这样无疑会增加查找可用空闲分区的开销。 分配内存,从空闲的分区表中找到所需大小的分区。设请求的分区的大小为job_length,表中每个空闲分区的大小可表示为free[i].length。如果frees[i].length>=job_length,即空闲空间I的长度大于等于作业的长度将空闲标志位设置为1,如果不满足这个条件则输出:“对不起,当前没有满足你申请长度的空闲内存,请稍后再试!”。如果frees[i].length>=job_length空闲区空间I的长度不大于作业长度,I的值加1判断下一个空闲区空间是否大于作业的长度。把未用的空闲空间的首地址付给已用空间的首地址,已用空间的长度为作业的长度,已用空间数量加1。如果(frees[i].length>job_length),空间的长度大于作业的长度,frees[i].front+=job_length; 空闲空间的起始首地址=原空闲区间的起始长度加作业长度frees[i].length-=job_length;空闲区间的长度=原空闲区间的长度-作业的长度。如果空间的长度与作业的长度相等,空闲区向前移一位,空闲区的数量也减一。这样判断所有情况并相应分配之后,内存空间分配成功。 第二个操作为:撤消相应作业。在这个操作中,进行了以下步骤: (1)按照系统提示输入将要撤消的作业名; (2)判断该作业是否存在 若不存在:输出“没有这个作业名,请重新输入作业名”; 若存在:则先分别用flag,start,len保存该作业在分配区表的位置i,内存空间的首地址以及长度。接着根据回收区的首地址,即该作业的首地址,从空闲区表中找到相应的插入点,将其加入空闲表,此时可能出现以下三种情况之一: 1 .回收区只与插入点前一个空闲分区F1相邻接即(frees[i].front+frees[i].length)==start),此时判断其是否与后一个空闲分区F2相邻接,又分两种情况: 若相邻接,则将三个分区合并,修改新的空闲分区的首地址和长度。新的首地址为F1的首地址,长度为三个分区长度之和,相应的代码为:

Windows虚拟内存管理

基本概念【摘录】 每个进程都被赋予它自己的虚拟地址空间。对于32位进程来说,这个地址空间是4GB,因为32位指针可以拥有从0x000000000至0xFFFFFFFF之间的任何一个值。这使得一个指针能够拥有4 294 967 296个值中的一个值,它覆盖了一个进程的4GB虚拟空间的范围。这是相当大的一个范围。由于每个进程可以接收它自己的私有的地址空间,因此当进程中的一个线程正在运行时,该线程可以访问只属于它的进程的内存。属于所有其他进程的内存则隐藏着,并且不能被正在运行的线程访问。 注意在Windows 2000中,属于操作系统本身的内存也是隐藏的,正在运行的线程无法访问。这意味着线程常常不能访问操作系统的数据。Windows 98中,属于操作系统的内存是不隐藏的,正在运行的线程可以访问。因此,正在运行的线程常常可以访问操作系统的数据,也可以破坏操作系统(从而有可能导致操作系统崩溃)。在Windows 98中,一个进程的线程不可能访问属于另一个进程的内存。 前面说过,每个进程有它自己的私有地址空间。进程A可能有一个存放在它的地址空间中的数据结构,地址是0x12345678,而进程B则有一个完全不同的数据结构存放在它的地址空间中,地址是0x12345678。当进程A中运行的线程访问地址为0x12345678的内存时,这些线程访问的是进程A的数据结构。当进程B中运行的线程访问地址为0x12345678的内存时,这些线程访问的是进程B的数据结构。进程A中运行的线程不能访问进程B的地址空间中的数据结构。反之亦然。 记住,这是个虚拟地址空间,不是物理地址空间。该地址空间只是内存地址的一个范围。在你能够成功地访问数据而不会出现违规访问之前,必须赋予物理存储器,或者将物理存储器映射到各个部分的地址空间。 每个进程的虚拟地址空间都要划分成各个分区。地址空间的分区是根据操作系统的基本实现方法来进行的。不同的Windows内核,其分区也略有不同。

北大操作系统高级课程-陈向群作业-虚拟内存管理实习报告

虚拟内存管理实习报告

目录 内容一:总体概述 (3) 内容二:任务完成情况 (3) 任务完成列表(Y/N) (3) 具体Exercise的完成情况 (3) 内容三:遇到的困难以及解决方法 (11) 内容四:收获及感想 (11) 内容五:对课程的意见和建议 (11) 内容六:参考文献 (11)

内容一:总体概述 本次lab主要是针对操作系统内存管理的学习,内存管理主要有固定分区、可变分区、页式和段式管理。现代操作系统主要采用页式内存管理,它把用户程 序地址空间划分成大小相等的部分,称为页。内存空间按页的大小划分为大小相 等的区域,称为内存块(物理页面,页框,页帧)。以页为单位进行分配,逻辑 上相邻的页,物理上不一定相邻。 虚拟内存的基本思想:每个程序拥有自己的地址空间,这个空间被分割成多个块,每一块称作一页或者页面,每一页有连续的地址范围。这些页被映射到物 理内存,但并不是所有页都必须在内存中才能运行。当程序引用到一部分在物理 内存中的地址空间时,由硬件立即执行必要的映射。当程序引导到一部分不在物 理内存中德的地址空间时,由操作系统负责将缺失的部分装入屋里内存并重新执 行失效的指令。 内容二:任务完成情况 任务完成列表(Y/N) Exercise1 Exercise2 Exercise3 Exercise4 Exercise5 Exercise6 Exercise7 Challange 完成情况Y Y Y Y Y Y N N 具体Exercise的完成情况 一、TLB异常处理 目前,Nachos系统对于内存的管理是基于软件模拟的TLB机制。其工作原理、异常处理、替换算法等方面,与分页式内存管理非常相像。 Exercise 1 源代码阅读 ?阅读code/userprog/https://www.doczj.com/doc/491559051.html,,着重理解nachos执行用户程序的过程,以及该过 程中与内存管理相关的要点。 ?阅读code/machine目录下的machine.h(cc),translate.h(cc)文件和code/userprog目 录下的exception.h(cc),理解当前Nachos系统所采用的TLB机制和地址转换机制。 解答:https://www.doczj.com/doc/491559051.html,中有2个主要的方法,分别是StartProcess和ConsoleTest,它们的作用是给用 户进程分配内存空间并且执行用户进程和测试控制台输入。StartProcess方法中首先通过 OpenFile *executable = fileSystem->Open(filename);打开文件,然后通过 space = new AddrSpace(executable); currentThread->space = space; 为文件分配内存空间并且把内存空间给当前进程。

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

相关文档 最新文档