本文主要是介绍虚拟内存解疑,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
虚拟内存别称 虚拟存储器 (Virtual Memory)。 电脑 中所运行的
虚拟内存是Windows 为作为内存使用的一部分硬盘空间。虚拟内存在硬盘上其实就是为一个硕大无比的文件,文件名是 PageFile.Sys,通常状态下是看不到的。必须关闭资源管理器对系统文件的保护功能才能看到这个文件。虚拟内存有时候也被称为是“页面文件”就是从这个文件的文件名中来的。
内存在计算机中的作用很大,电脑中所有运行的程序都需要经过内存来执行,如果执行的程序很大或很多,就会导致内存消耗殆尽。为了解决这个问题,WINDOWS运用了虚拟内存技术,即拿出一部分硬盘空间来充当内存使用,这部分空间即称为 虚拟内存,虚拟内存在硬盘上的存在形式就是 PAGEFILE.SYS这个页面文件。
NT/2000的每一个进程都在启动时分配了4GB(0xFFFFFFFF)的虚拟内存。其中的某些部份实际上是由所有进程共享的,例如核心和设备驱动程序区域。但它们都会被映射到每个进程的虚拟地址空间里。实际上没有进程分配到4GB的物理内存,而是仅当需要时才分配物理内存。因此每一个进程都有各自的4GB虚拟内存,编址范围从0x00000000到0xFFFFFFFF。其中,0x00000000-0x0000FFFF是为NULL指针分配而保留的。访问该区域内存将导致“非法访问”错误。0x00010000-0x7FFEFFFF是用户进程空间。EXE文件的映像被加载到其中(起始地址0x00400000),DLL(动态链接库)也被加载到这部份空间。如果DLL或EXE的代码被装入到该范围的某些地址,就能够被执行。访问该区域中没有代码装入的地址将导致“非法访问”错误。0x7FFF0000-0x7FFFFFFF是保留区域,对此区域的任何访问都将导致“非法访问”错误。0x80000000-0xFFFFFFFF仅供操作系统使用。用于加载设备驱动程序和其它核心级代码。从用户级应用程序(ring 3)访问此区域将导致“非法访问”错误。
虚拟内存可以说是两个不同的概念。从编程的角度来说,每个应用程序运行在独立的寻址空间,由操作系统通过页表机制,映射到真正的物理内存上边。程序请求内存时,如果请求不到指定大小的连续内存,就会报错。题主的问题应该就是这种情况 另一种概念是交换文件,也就是Linux swap的概念。内存访问速度快,但容量有限的,操作系统会把暂时用不到的内存数据,以文件的形式写到硬盘,节省的空间用来存储更多的必要数据。虚拟空间可以提高使用体验,但是有一种情况要注意,如果应用程序运行需要5G的内存,而机器只有4G内存,操作系统需要不停的将数据在内存和硬盘之类写入写出,体验很差。结论是,能加内存加内存,能上固态上固态。
虚拟内存可以说是两个不同的概念。从编程的角度来说,每个应用程序运行在独立的寻址空间,由操作系统通过页表机制,映射到真正的物理内存上边。程序请求内存时,如果请求不到指定大小的连续内存,就会报错。题主的问题应该就是这种情况 另一种概念是交换文件,也就是Linux swap的概念。内存访问速度快,但容量有限的,操作系统会把暂时用不到的内存数据,以文件的形式写到硬盘,节省的空间用来存储更多的必要数据。虚拟空间可以提高使用体验,但是有一种情况要注意,如果应用程序运行需要5G的内存,而机器只有4G内存,操作系统需要不停的将数据在内存和硬盘之类写入写出,体验很差。结论是,能加内存加内存,能上固态上固态。
因为windows进程间共享数据是用内存映射文件实现的,包括RPC、COM、OLE、DDE、DDE、WINDOWS消息、剪贴板、套接字等最底层的机制就是内存映射文件。
所以要是不用业交换文件来实现进程间通信难道用临时磁盘文件实现吗
题主你还没有搞清楚页面文件(交换空间)与虚拟内存的正确含义,我想你是想表达,为什么大内存还要设置页面文件?事实上,大内存根本无需设置页面文件,尤其是大于8G的情况下,页面文件是以前内存小的一个不得已的解决方案,用硬盘的一块空间来当作内存使用。操作系统把处于不活跃的进程所占用的内存页保存到硬盘上,留出更多的内存给活跃的进程使用,这样做的后果就是,由于硬盘速度很慢,尤其是机械硬盘,使得当这些不活跃的程序激活的时候,操作系统需要大量读写硬盘,造成系统响应速度严重下降!如今内存容量已不再是瓶颈,题主应该仔细看看是哪些用不上的进程占用了宝贵的系统资源,及时清理后台资源,把有限的资源用在正在使用的程序上才是硬道理。页面文件可以一时用来救急,如果你一直需要开启页面文件,那么就应当考虑增加物理内存,并在物理内存足够的情况下关闭页面文件,否则你的灵感将会消失在系统的卡顿和等待中!
一个应用程序为什么会使用内存同时有使用虚拟内存呢
楼主,你这个问题。。。。问的有点让人无语。。。。
应用程序(我以游戏为主,因为通常一般程序是不会占用很多虚拟内存的)
如果计算机缺少运行程序或操作所需的随机存取内存 (RAM),则 Windows 使用虚拟内存)进行补偿。 不知楼主有没有发现,在Windows2000(XP)目录下有一个名为pagefile.sys的系统文件,它的大小经常自己发生变动,小的时候可能只有几十兆,大的时候则有数百兆,这种毫无规律的变化实在让很多人摸不着头脑。其实,pagefile.sys是Windows下的一个虚拟内存,它的作用与物理内存基本相似,但它是作为物理内存的“后备力量”而存在的,但是,它并不是在只有物理内存不够用时才发挥作用的,也就是说在物理内存够用时也有可能使用虚拟内存,如果你虚拟内存设置过小则会提示“虚拟内存不足”。
Windows内存结构梳理
多字节数据是按怎样的顺序存放的呢?实际情况和CPU有关,微处理中的存放顺序有正序和逆序之分。正序(big-endian) 逆序(little-endian)
两种编码的区别:
big-endian:高位字节存入低字节,低位字节存入高地址,一次排列
little-endian:低位字节存入低地址,高位字节存入高地址。反序排列
unicode是asc字符编码的一个扩展,只不过在WINDOWS中,用两个字节对其进行编码,也称为宽字符集
unicode中,所有的字符都是16位,包括所有的7为asc码都被扩充为16位(注意高位扩充的是〇)
intel处理器在内存中,一个字存入存储器要占有相继的两个字节,这个字存放时就按little-endian方式存入,即低位字节存入低地址,高位字节存入高地址
API函数,这些函数提供应用程序运行所需要的窗口管理、图形设备接口、内存管理等各项服务功能。这些功能以函数库的形式组织在一起,形成饿了WINDOWS应用程序编程接口(API),简称win api。win api子系统负责将api调用转换成WINDOWS操作系统的系统服务调用,所以,可以认为API函数是构筑整个WINDOWS框架的基石,在他的下面是WINDOWS的操作系统核心,而在他的上面则是WINDOWS应用程序,对于应用程序开发人员而言,所看到的WINDOWS操作系统实际上就是win API,操作系统的其他部分对开发人员来说是完全透明的
WINDOWS运转的核心是一个称作“动态链接”的概念,WINDOWS提供了应用程序可利用的丰富的函数调用,这些函数采用动态链接即DLL实现
win32API 是一个基于c语言的接口,但是win32API中的函数可以由用不同语言编写的程序调用,只要在调用时遵循调用的规范即可
API函数是区分字符集的:A表示ANSI;W表示Widechars,即unicode。前者是通常使用的单字节方式,后者是宽字节方式,以便处理双字节字符。
句柄是WINDOWS标识,由应用程序建立或使用的对象所使用的一个唯一的整数值(通常是32位)。WINDOWS要使用各种各样的句柄来标识诸如应用程序实例、窗口、图标、菜单、输出设备、文件等对象。程序通过调用WINDOWS函数获取句柄,然后在其他WINDOWS函数中使用这个句柄,以引用他代表的对象。句柄的实际值对程序来说无关紧要,这个值是被WINDOWS模块内部用来引用相应对象的
当一个进程被初始化时,系统要为他分配一个句柄表,句柄值是放入进程的句柄表中的索引
unicode影响到计算机工业的每个部分,对操作系统和编程语言的影响最大
在NT架构下,win32API能接受unicode和ASCI字符串,而其内核则只能使用unicode ,所有这些操作对用户来说都是透明的,但进行这些字符串的转换需要占用系统资源。
WINDOWS是一个消息驱动式系统,WINDOWS消息提供应用程序与应用程序之间、应用程序与WINDOWS系统之间进行通信的手段。应用程序想要实现的功能由消息来触发,并且靠对消息的响应和处理来完成。
WINDOWS系统中有两种消息队列:一种是系统消息队列,另一种是应用程序消息队列。计算机的所有输入设备由WINDOWS监控。当一个事件发生时,WINDOWS先将输入的消息放入系统消息队列中,再将输入的消息拷贝到相应的应用程序队列中,应用程序中的消息循环从他的消息队列中检索每个消息并且发送给相应的窗口函数中。一个事件的发生,到达处理他的窗口函数必须经历上述过程。值得注意的是消息的非抢先性,即不论事件的急与缓,总是按到达的先后顺序排队(一些系统消息除外)
由于WINDOWS本身是由消息驱动的,所以调试程序时跟踪一个消息会得到相当底层的答案。
一般来说,80X86及其以后的各代CPU可在实模式、保护模式、虚拟86模式下运转
在保护模式下程序可以利用更多的内存,可以实现多任务系统
在保护模式下,CPU的寻址方式与实模式不同,实模式下的寻址方式是“段基址+段偏移”,段的默认大小为64kB,所有段都是可读/写的,唯有代码段是可执行的,段的特权级为0.而在保护模式下内存是“线性”的,因为这时段寄存器的意义不同,他里面存放的不再是段基地址,二十存放着段选择子,这呃值是不直接参与寻址的,只是全局描述表(global descriptor table ,GDT)或本地描述表(local descriptor table,LDT)的一个指针,不同段寄存器有不同的属性(读、写、执行、特权级等)
虚拟内存(virtual memory)不是真正的内存,他通过映射(map)的方法,使可用的虚拟地址达到4GB,每个应用程序可以被分配2GB的虚拟地址,剩下的2GB留给操作系统自己用。WINDOWS是一个分时多任务操作系统,CPU时间被分成一个个的事件片后分配给不同程序,在一个时间片里,和这个程序执行不无关的东西并不映射到线性地址中。因此每个程序都有自己的4GB寻址空间,互补干扰。在物理内存中,操作系统和系统DLl代码需要供每个应用程序调用,所以在所有的时间必须映射;用户exe程序只在自己所属的时间片内被映射,而用户DLL则有选择地被映射。
简单地说,虚拟内存的实现方法和过程如下:
1、当一个应用程序被启动时,操作系统就创建一个新进程,并给每个进程分配2GB的虚拟地址(不是内存,只是地址)
2、虚拟内存管理器将应用程序的代码映射到那个应用程序的虚拟地址中的某个位置,并把当前所需要的代码读取到物理地址中(注意:虚拟地址和应用程序代码在物理内存中的位置是没有关系的)
3、如果使用动态链接库DLL,DLL也被映射到进程的虚拟地址空间,在需要的时候才被读入物理内存
4、其他项目(例如数据、堆栈)的空间是从物理内存中分配的,并被映射到虚拟地址空间中
5、应用程序通过使用他的虚拟地址空间中的地址开始执行,然后虚拟内存管理器把每次的内存访问映射到物理位置
关于虚拟内存,要明白一下几点:
1、应用程序是不会直接访问物理地址的
2、虚拟内存管理器通过虚拟地址的访问请求,控制所有的物理地址访问
3、每个应用程序都有相互独立的4GB寻址空间,不同应用程序的地址空间是隔离的
4、DLL程序没有自己的“私有”空间,他们总是被映射到其他应用程序的地址空间中,作为其他应用程序的一部分运行。因为如果他不和其他程序同属一个地址空间,应用程序就无法调用他
使用虚拟内存的好处是:简化了内存的管理,并可弥补物理内存的不足;可以防止多任务环境下各个应用程序之间的冲突
在保护模式下,所有的应用程序都有权限级别,这个权限级别按优先次序分为4等
0等级权限可以执行所有的指令并访问所有数据,操作系统核心层是运行在ring0级的,而win32子系统(如动态链接库)是运行在ring3级的,以提供与应用程序的接口
保护模式使应用程序没有权限去破坏操作系统,只能规矩地使用win32API接口函数与系统打交道。如果想控制系统,就必须取得0特权级,比如调试工具softICE就是工作在0特权级上的
WINDOWS的可执行文件(EXE、DLL)是PE格式
PE文件使用的是一个平面地址空间,所有代码和数据都被合并在一起,组成一个很大的结构。文件的内容被分割为不同的区块(section,又称区段、节等),块中包含代码或数据。每个块都有他自己在内存中的一套属性,比如:这个块是否包含代码、是否只读或可读/写等
每个块都有不同的名字,这个名字用来表示区块的功能。常见的快的有.text,.rdata,.data,.idata,.rsrc等。各种块的含义如下:
.text:实在编译或汇编结束时产生的一种块,他的内容全是指令代码;
.rdata:是运行期只读数据;
.data:是初始化的数据块;
.idata:包含其他外来的DLL的函数及数据信息,即输入表;
.rsrc:包含模块的全部资源,如图标、菜单、位图等。
PE文件非常好的一个地方就是在磁盘上的数据结构与在内存中的结构是一致的,装载一个可执行文件到内存中,主要就是将一个PE文件的某一部分映射到地址空间中。这样,PE文件的数据结构在磁盘和内存中是一样的
程序访问存储器所使用的逻辑地址称为虚拟地址,又称为内存偏移地址(memory offset)。与实地址模式下的分段地址类似,虚拟地址也可以写成“段:偏移量”的形式,这个的段是指段选择子。例如“0167:00401000”就是这个表示方法(0167:这个是段选择子,其数据保存在CS段选择器里。同一程序在不同系统环境下,此值可能不同,一般也不需要关心此值)
基地址:文件执行时将被映射到指定内存地址中,这个初始内存地址称为基地址(imagebase)。这个值是由PE文件本身设定的
这篇关于虚拟内存解疑的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!