- kven
-
早期的计算机由于结构较为简单,存储容量小,并不需要过多的的存储管理。
随着计算机和程序越来越复杂,使得存储管理成为必要。
单一连续分配是最简单的内存分配方式
只能在单用户、单进程的操作系统中使用
固定分区分配是支持多道程序的最简单存储分配方式
内存空间被划分为若干固定大小的区域
每个分区只提供给一个程序使用,互不干扰
根据进程实际需要,动态分配内存空间
不需要新建空闲链表节点
只需要把空闲区的容量增大为包括回收区的容量即可
将回收区和空闲区合并
新的空闲区使用原来回收区的地址
将两个空闲区和中间的回收区合并
新的空闲区使用空闲区1的地址
为回收区创建新的空闲节点
将该节点插入到相应的空闲区链表中
上面的部分主要是从物理的角度讲解内存管理,这部分主要是讲解操作系统是怎么管理进程的内存空间。
字块 是相对于物理设备的定义, 页面 是相对逻辑空间的定义。
页式存储管理主要是将进程逻辑空间等分成若干大小的页面,相应的把物理内存空间分成与页面大小的物理块,以页面为单位把进程空间装进物理内存中分散的物理块。
页面大小应该适中,过大难以分配,过小内存碎片过多,通常是512B~8K。
页表 记录进程逻辑空间于物理空间的映射
在页式存储管理, 页地址 = 页号 + 页内偏移
现代计算机系统中,可以支持非常大的逻辑 地址空间(2 32~2 64),这样,页表就 变得非常大,要占用非常大的内存空间,如, 具有32位逻辑地址空间的分页系统,规定页 面大小为4KB,则在每个进程页表中的页表 项可达1M(2^20)个,如果每个页表项占用 1Byte,故每个进程仅仅页表就要占用1MB 的内存空间。
为了解决这个问题,引入了多级页表。
多级页表有一个根页表,每一个字块指向了内存中的一片空间,这块空间存储的是二级页表。以此类推,最后一级页表指向的字块才是进程实际使用的内存。通过这种分级机制,大大减少了进程中页表数占用的空间。
段式存储管理将进程逻辑空间划分成若干段(非等分),段的长度由连续逻辑的长度决定。
例如一个程序有主函数MAIN、子程序段X、子函数Y等,这个时候会根据每一个函数的逻辑长度来分配逻辑空间。
页表由 页号 和 基址 组成,但在段式存储管理中由于每一段的长度是不固定的,段表由 段号 、 基址 以及 段长 组成。
在段式存储管理, 段地址 = 段号 + 段内偏移
分页可以有效提高内存利用率(虽然说存在页内碎片)
分段可以更好满足用户需求
两者结合,形成段页式存储管理
先将逻辑空间按段式管理分成若干段,再把段内空间按页式管理等分成若干页。
在段页式存储管理中, 段页地址 = 段号 + 段内页号 + 页内地址
有些进程实际需要的内存很大,超过物理内存的容量。
由于操作系统的多道程序设计,使得每个进程可用物理内存更加稀缺。
不可能无限增加物理内存,物理内存总有不够的时候,于是便有了虚拟内存的概念。
虚拟内存是操作系统内存管理的关键技术,使得多道程序运行和大程序运行成为现实,她通过将进程所使用的内存进行划分,将部分暂时不使用的内存放置在辅存。
根据局部性原理,程序运行时,无需全部装入内存,装载部分即可。如果访问页不在内存,则发出缺页中断,发起页面置换。
从用户层面看,程序拥有很大的空间,即是虚拟内存。
虚拟内存实际是对物理内存的补充,速度接近于内存,成本接近于辅存。
置换算法一般有先进先出算法(FIFO)、最不经常使用算法(LFU)、最近最少使用算法(LRU)。
从计算机组成原理篇章中,我们可以知道,CPU的高速缓存没有数据时,需要从主存中加载数据。此时若主存中也没有数据,则需要从辅存中载入页面数据。
内存替换策略发生在Cache-主存层次、主存-辅存层次。Cache-主存层次的替换策略主要是为了解决 速度问题 ,
主存-辅存层次则。主要是为了解决 容量问题 。
顺序文件是指按顺序存放在存储介质中的文件,例如磁带的存储特性使得磁带文件只能存储顺序文件。
顺序文件是所有逻辑文件当中存储效率最高的。
可变长文件不适合使用顺序文件格式存储,索引文件是为了解决可变长文件存储而发明的一种文件格式,索引文件需要配合索引表完成存储的操作。
目录的层级结构是树状的,成为目录树。
目录树中任何文件或目录都只有唯一路径。
对CPU而言,凡是对CPU进行数据输入的都是输入设备,凡是CPU进行数据输出的都是输出设备。
缓冲区主要是解决CPU与IO设备的速率不匹配的问题,减少CPU处理IO请求的频率,提高CPU与IO设备之间的并行性。
专用缓冲区只适用于特定的IO进程,当这样的IO进程比较多时,对内存的消耗也很大,所以操作系统划出可供多个进程使用的公共缓冲区,称之为缓冲池。
SPOOLing技术是关于慢速字符设备如何与计算机主机交换信息的一种技术,利用高速共享设备将低速的独享设备模拟为高速的共享设备,逻辑上,系统为每一个用户都分配了一台独立的高速独享设备,是一种虚拟设备技术。
SPOOLing技术把同步调用低速设备改为异步调用。在输入、输出之间增加了排队转储环节(输入井、输出井),SPOOLing负责输入(出)井与低速设备之间的调度,逻辑上,进程直接与高速设备交互,减少了进程的等待时间。
相关推荐
操作系统的存储管理功能包括
操作系统的存储管理功能包括内存分配、内存保护、地址映射和虚拟内存等方面。内存分配是指为进程分配空间并管理内存使用情况。内存保护是指防止一个进程访问另一个进程的内存空间,保护内核代码和数据不被非法访问。地址映射是将逻辑地址映射到物理地址,以便进程能够访问内存。虚拟内存是一种存储管理技术,它可以将进程需要的部分数据存储在内存中,将不需要的数据存储在硬盘上,从而可以有效地扩展内存,提高系统性能。 操作系统可以通过多种算法来管理内存,如固定分区、可变分区、伙伴系统和页式管理等。其中,页式管理是最常用的一种内存管理技术,它将内存划分为大小相等的页面,并将进程的逻辑地址映射到物理地址。当进程需要访问一个页面时,操作系统会将该页面从硬盘上加载到内存中。当内存不足时,系统会将不常用的页面置换到硬盘上,以便为更重要的页面腾出空间。 虚拟内存是一种重要的存储管理技术,它可以将进程需要的部分数据存储在内存中,将不需要的数据存储在硬盘上,从而可以有效地扩展内存,提高系统性能。虚拟内存的主要作用是提供更大的地址空间,使得进程可以访问比实际内存更多的数据。虚拟内存的实现需要硬件和操作系统的支持,其中最重要的是页面置换算法和页面调度算法。 在实际应用中,操作系统的存储管理功能对系统的性能和稳定性起着至关重要的作用。通过合理的内存管理策略,可以避免进程之间的互相干扰,提高系统的响应速度。同时,也可以避免内存泄露等问题,确保系统的稳定性和安全性。2023-08-30 08:24:141
华为手机怎么看内存
随着手机使用时间的增长,手机内存的使用情况也逐渐变得复杂起来。因此,了解如何查看华为手机内存的使用情况是非常重要的。在本文中,我们将介绍华为手机如何查看内存。打开设置应用要查看华为手机的内存使用情况,首先需要打开设置应用。这可以通过在手机主屏幕上找到“设置”图标来实现。在打开设置应用后,您可以通过向下滚动找到“存储”选项。查看内存使用情况在“存储”选项下,您可以看到手机内存使用情况的详细信息。在这里,您可以看到手机内存的总容量、已用容量和可用容量。此外,您还可以查看手机内存中各个应用程序的使用情况。如果您发现手机内存不足,可以通过清除应用程序缓存或卸载不需要的应用程序来释放一些内存。使用内存管理工具华为手机还提供了一个内存管理工具,可以帮助您更好地管理手机内存。在“存储”选项下,您可以找到“内存管理”选项。在这里,您可以查看当前内存使用情况,并通过清除后台应用程序、关闭不必要的系统应用程序和优化内存来释放内存。了解如何查看华为手机内存使用情况是非常重要的。通过使用上述方法,您可以更好地管理手机内存,确保手机始终运行流畅。2023-08-30 08:24:221
操作系统是怎样管理内存和管理CPU的?
操作系统通过内存管理的方式来管理内存,包括虚拟内存、内存的分配与回收、内存保护和共享等。操作系统通过进程和线程的调度来管理CPU,包括将CPU分配给任务、控制任务的优先级和时间片轮转等。具体而言,操作系统通过内存映射表实现虚拟内存,通过调用内存分配函数和内存释放函数来管理内存,通过权限位来保护内存,同时允许进程间共享内存。而在CPU调度方面,操作系统通过多级反馈队列来调度任务,优先级高的进程或线程会先获得CPU的时间片,调度算法也会根据不同的策略进行调整。2023-08-30 08:24:291
操作系统的存储管理功能包括
操作系统的主要功能是什么?1、操作系统的主要功能是进程与处理机管理、作业管理、存储管理、设备管理、文件管理,具体如下:进程与处理机管理。由于程序的执行必须依靠处理机,任意时刻处理及都只能执行一个程序流。作业管理。2、简述操作系统的功能具体如下:一:提供人机交互接口。可以想象没有操作系统这层软件的话,使用计算机会是一个什么样子。计算机使用者将面临一堆计算机硬件进行操作,早期的计算机就是这样的,通过硬开关进行控制。3、操作系统的主要功能是进程管理、存储管理、设备管理、文件管理、作业管理。进程管理:其工作主要是进程调度,在单用户单任务的情况下,处理器仅为一个用户的一个任务所独占,进程管理的工作十分简单。*操作系统的存储管理的主要内容是什么?1、存储管理即是对主存的管理,它是操作系统的重要功能之一。主存储器是计算机系统中的一种宝贵资源,对主存的管理和有效使用是操作系统中十分重要的内容。2、操作系统中的存储管理主要是实现对计算机的主存的管理,存储管理的主要对象是内存管理,是除处理器外操作系统管理的最重要的资源。3、在操作系统中,存储管理主要是对内存的管理。存储器管理的对象是主存,其的主要功能包括分配和回收主存空间、提高主存利用率、扩充主存、对主存信息实现有效保护。4、操作系统的存储管理功能包括内存分配、内存保护、地址映射和虚拟内存等方面。内存分配是指为进程分配空间并管理内存使用情况。内存保护是指防止一个进程访问另一个进程的内存空间,保护内核代码和数据不被非法访问。5、存储管理的对象是主存储器(简称内存或主存)。存储管理子系统是操作系统中最重要的组成部分之一,它的目的是方便用户使用和提高存储器利用率。操作系统中的存储管理主要指1、内存的管理。存储管理是操作系统的一个重要任务,存储管理主要指对内存的管理,即如何分配内存给不同的进程。操作系统中存储管理的主要功能是负责主存空间分配和回收、提高主存利用率、扩充主存及对主存信息提供保护。2、内存管理。操作系统中的存储管理主要是实现对计算机的主存的管理,存储管理的主要对象是内存管理,是除处理器外操作系统管理的最重要的资源。3、操作系统的存储管理功能包括内存分配、内存保护、地址映射和虚拟内存等方面。内存分配是指为进程分配空间并管理内存使用情况。内存保护是指防止一个进程访问另一个进程的内存空间,保护内核代码和数据不被非法访问。简述存储管理的主要功能寻址空间操作系统让系统看上去有比实际内存大得多的内存空间。虚拟内存可以是系统中实际物理空间的许多倍。每个进程运行在其独立的虚拟地址空间中。这些虚拟空间相互之间都完全隔离开来,所以进程间不会互相影响。存储管理系统分内存和外存,都是用来存储资料的。内存是暂时存储资料,存取速度快,断电后存储器会释放空间所以资料会不见。而外存(也是常说硬盘)是_久性存储资料,断电后资料还在只要你不把资料删除就一直存在。存储管理子系统是操作系统中最重要的组成部分之一,它的目的是方便用户使用和提高存储器利用率。内存分配与回收、内存分配与回收、存储保护、虚拟存储。根据相关公开信息查询到:内存分配与回收。存储管理主要关注于存储管理方面的运行和维护工作。该流程用以对生产IT环境中的数据和数据资源进行定义、跟踪及维护。存储管理主要是指对内存的管理,目的是尽量提高内存的使用效率。存储器管理的对象是主存,也称内存。它的主要功能包括分配和回收主存空间、提高主存利用率、扩充主存、对主存信息实现有效保护。2023-08-30 08:24:541
linux四大基本功能?
一个Linux包含进程管理、内存管理、文件管理、输入输出管理四大基本功能。1.进程管理提到进程,首先要介绍进程映像的概念。进程映像由程序段、相关数据段和进程控制块(PCB)组成。所谓创建进程,本质上是创建进程映像中的PCB;而撤销进程,本质上是撤销进程的PCB。因此,PCB是进程存在的唯一标志。在Linux操作系统中,当一个进程被创建时,系统就为该进程建立一个task_struct任务结构体。当进程运行结束时,系统撤消该进程的任务结构体。进程的任务结构体是进程存在的唯一标志。进程的任务结构体为内核管理进程,提供了内核所需了解的进程信息。2.内存管理内存管理是操作系统设计中最重要和最复杂的任务之一。有效的内存管理不仅方便用户使用存储器,提高内存效率,还可以通过虚拟内存技术从逻辑上扩充存储器。在Linux操作系统中,每个进程都有独自的内存空间,使用虚拟内存技术。该操作系统为了保证物理内存能得到充分的利用,内核会在适当的时候将物理内存中不经常使用的数据块自动交换到虚拟内存中,而将经常使用的信息保留到物理内存。根据”最近最经常使用“算法,将一些不经常使用的页面交换到虚拟内存。3.文件管理文件是操作系统中的一个重要概念,是以计算机硬盘为载体存储在计算机上的信息集合。Linux支持多种文件系统,包括ext2、ext3、vfat、ntfs、iso9660、jffs、romfs和nfs等,为了对各类文件系统进行统一管理,Linux引入了虚拟文件系统(VFS),为各类文件系统提供一个统一的操作界面和应用编程接口。4.输入输出管理IO设备管理是操作系统中最凌乱也最具挑战性的部分。由于它包含了很多领域的不同设备及与设备相关的应用程序,很难有一个通用且一致的设计方案。输入输出设备的管理离不开中断这一操作系统最重要的机制。中断是指在CPU正常运行期间,由于内外部事件或由程序预先安排的事件引起的CPU暂时停止正在运行的程序,转而为该内部或外部事件或预先安排的事件服务的程序中去,服务完毕后再返回去继续运行被暂时中断的程序。Linux中通常分为外部中断和内部中断。2023-08-30 08:25:011
内存管理器如何跟踪哪些进程正在使用操作系统中的哪些内存区域?
1、首先,让我们打开任务管理器。右键单击任务栏,在弹出的菜单中选择“任务管理器”。2、其次在任务管理器界面,单击“更多详细信息”按钮。3、最后在任务管理器窗口中,导航到“进程”选项卡,点击“内存”列标题即可查看正在使用操作系统中的内存区。2023-08-30 08:25:081
内存管理有哪些主要功能?其主要任务是什么?
具体说说如下。1.你的可爱,治愈一切不可爱。2.你是爸爸妈妈不期而遇的温暖。3.愿时光能缓,愿你赤忱善良。4.谢谢你让我每天都元气满满。5.你总能成为我热爱生活的原因。6.我牵着你,你牵着我,长长的路陪你慢慢走。7.用心记录你生命里每个不可复制的瞬间。8.辛苦是幸福的、熬夜是值得的。9.我的岁月因你而暖,因你而乐。10.孩子是天生的表演。11.日夜相对,仍百处不腻。12.你就是上天赐给我最好的礼物。13.期待你长大以后的样子。14.你是妈妈的巧克力乖巧刻骨又努力。15.你成长的道路千姿百态,呆萌、可爱、调皮又搞怪。16.抱着软绵绵的你像是抱住了整个世界。17.你给我的甜,早已经多过了给我的苦。18.因为有了你的存在,欢声笑语不断、快乐幸福涌入19.终有一天你也会像个公主,所有梦都被满足。2023-08-30 08:25:151
操作系统的内部是如何分工的?
操作系统的内部在执行各种任务时会涉及多个组件和分工。以下是操作系统的一些常见组件和它们的职责:内核(Kernel):内核是操作系统的核心组件,负责管理和控制系统的各种资源。它提供了对硬件的访问和控制,并管理进程、内存、文件系统、设备驱动程序等。内核负责分配和调度系统资源,确保各个组件和应用程序之间的协调和安全性。进程管理:操作系统负责管理和调度运行在系统上的各个进程。它分配和回收进程所需的资源,例如内存、处理器时间片等。操作系统跟踪进程的状态、优先级和进程间的通信,以确保系统的稳定运行和资源的有效利用。内存管理:操作系统负责管理计算机的内存资源。它分配和回收内存,为进程提供所需的内存空间,并处理内存的页面置换和虚拟内存等机制。内存管理器确保不同进程之间的内存隔离和保护,以及有效地使用和管理系统内存。文件系统:操作系统提供了对存储设备(如硬盘、固态驱动器等)上数据的组织和访问方式。文件系统负责文件的创建、读取、写入和删除等操作,以及对文件和目录的管理。它提供了命名、权限控制和数据持久性等特性,使用户和应用程序能够方便地操作文件和数据。设备驱动程序:操作系统通过设备驱动程序与计算机硬件进行通信。设备驱动程序提供了对各种硬件设备(如打印机、键盘、鼠标、网络适配器等)的接口和控制。它们与内核交互,提供访问和操作硬件设备所需的功能。网络管理:操作系统提供网络通信的功能和管理。它包括网络协议栈、网络连接和通信接口等组件,允许应用程序通过网络进行数据传输和通信。操作系统管理网络配置、IP地址分配、路由表等,确保网络的连接和正常运行。2023-08-30 08:25:292
Python如何进行内存管理
Python是如何进行内存管理的?答:从三个方面来说,一对象的引用计数机制,二垃圾回收机制,三内存池机制。一、对象的引用计数机制Python内部使用引用计数,来保持追踪内存中的对象,所有对象都有引用计数。引用计数增加的情况:1,一个对象分配一个新名称2,将其放入一个容器中(如列表、元组或字典)引用计数减少的情况:1,使用del语句对对象别名显示的销毁2,引用超出作用域或被重新赋值Sys.getrefcount( )函数可以获得对象的当前引用计数多数情况下,引用计数比你猜测得要大得多。对于不可变数据(如数字和字符串),解释器会在程序的不同部分共享内存,以便节约内存。相关推荐:《Python视频教程》二、垃圾回收1,当一个对象的引用计数归零时,它将被垃圾收集机制处理掉。2,当两个对象a和b相互引用时,del语句可以减少a和b的引用计数,并销毁用于引用底层对象的名称。然而由于每个对象都包含一个对其他对象的应用,因此引用计数不会归零,对象也不会销毁。(从而导致内存泄露)。为解决这一问题,解释器会定期执行一个循环检测器,搜索不可访问对象的循环并删除它们。三、内存池机制Python提供了对内存的垃圾收集机制,但是它将不用的内存放到内存池而不是返回给操作系统。1,Pymalloc机制。为了加速Python的执行效率,Python引入了一个内存池机制,用于管理对小块内存的申请和释放。2,Python中所有小于256个字节的对象都使用pymalloc实现的分配器,而大的对象则使用系统的malloc。3,对于Python对象,如整数,浮点数和List,都有其独立的私有内存池,对象间不共享他们的内存池。也就是说如果你分配又释放了大量的整数,用于缓存这些整数的内存就不能再分配给浮点数。2023-08-30 08:26:362
258G的手机内存越来越不够用,日常使用中有哪些管理手机内存的技巧?
经常清理各个软件的缓存,图片内存可以备份到网盘里,可以删除一些没必要的软件2023-08-30 08:26:435
win7物理内存过高怎么办
1、启动"windows任务管理器",快捷键"alt+ctrl+delete"点击"性能"选项卡,查看系统内存和物理内存的使用情况。2、点击"开始"菜单,然后再输入msconfig命令。会弹出"系统配置"的对话框,然后选择"服务"这个选项卡。3、可以看到很多运行的服务,将前面的复选框的勾选上。然后点击"全部禁用"按钮,确定即可。物理内存,真实存在的插在主板内存槽上的内存条的容量的大小,看计算机配置的时候,主要看的就是这个物理内存。物理 内存是计算机上的最重要的资源之一。Windows的内存管理器负责给活动进程、设备驱动,和操作系统自己分配内存。因为绝大多数系统所能访问的数据和代码远比物理内存多,所以从本质上来说,物理内存是代码和数据在其中运行的窗口。所以内存容量对性能有影响,因为如果进程或者操作系统所需的代码或者数据不存在,内存管理器就需要从磁盘中读取这些内容。2023-08-30 08:27:401
安卓手机内存不足如何清理内存?
可以下载专门的软件,360手机卫士和腾讯手机管家都可以2023-08-30 08:28:053
内存管理的基本问题
内存管理是指软件运行时对计算机内存资源的分配和使用的技术。其最主要的目的是如何高效,快速的分配,并且在适当的时候释放和回收内存资源。一个执行中的程式,譬如网页浏览器在个人电脑或是图灵机(Turing machine)里面,为一个行程将资料转换于真实世界及电脑内存之间,然后将资料存于电脑内存内部(在计算机科学,一个程式是一群指令的集合,一个行程是电脑在执行中的程式)。一个程式结构由以下两部分而成:“本文区段”,也就是指令存放,提供CPU使用及执行; “资料区段”,储存程式内部本身设定的资料,例如常数字串。技术简介内存可以通过许多媒介实现,例如磁带或是磁盘,或是小阵列容量的微芯片。 从1950年代开始,计算机变的更复杂,它内部由许多种类的内存组成。内存管理的任务也变的更加复杂,甚至必须在一台机器同时执行多个进程。虚拟内存是内存管理技术的一个极其实用的创新。它是一段程序(由操作系统调度),持续监控着所有物理内存中的代码段、数据段,并保证他们在运行中的效率以及可靠性,对于每个用户层(user-level)的进程分配一段虚拟内存空间。当进程建立时,不需要在物理内存件之间搬移数据,数据储存于磁盘内的虚拟内存空间,也不需要为该进程去配置主内存空间,只有当该进程被被调用的时候才会被加载到主内存。可以想像一个很大的程序,当他执行时被操作系统调用,其运行需要的内存数据都被存到磁盘内的虚拟内存,只有需要用到的部分才被加载到主内存内部运行。2023-08-30 08:28:304
Linux进程内存如何管理
内存管理的主要工作就是对物理内存进行组织,然后对物理内存的分配和回收。但是Linux引入了虚拟地址的概念。虚拟地址的作用如果用户进程直接操作物理地址会有以下的坏处:1、 用户进程可以直接操作内核对应的内存,破坏内核运行。2、 用户进程也会破坏其他进程的运行CPU中寄存器中存储的是逻辑地址,需要进行映射才能转化为对应的物理地址,然后获取对应的内存。通过引入逻辑地址,每个进程都拥有单独的逻辑地址范围。当进程申请内存的时候,会为其分配逻辑地址和物理地址,并将逻辑地址和物理地址做一个映射。2023-08-30 08:28:371
操作系统内存管理发展史
内存是计算机很重要的一个资源,因为程序只有被加载到内存中才可以运行;此外,CPU所需要的指令与数据也都是来自内存的。可以说,内存是影响计算机性能的一个很重要的因素。 随着技术的发展,现在计算机的内存容量已经有了很大的增长,但是程序大小的增长速度比内存容量的增长速度要快得多。正如帕金森定律所指出,“不论存储器有多大,程序都可以把它填满”。所以问题来了,当一个程序大小超过内存容量时,如何把调入内存中?这篇文章将总结内存管理的一些技术。 在介绍内存管理的细节前,先要了解一下分层存储器体系(一图胜千言)。分层存储体系这个模型并不是一开始就有的,而是随着计算机的发展来一步步完善,最终才形成了现在的体系。所以,分层存储体系的发展历史也是这篇文章的一个线索。 早期的计算机是没有存储器抽象的,直接将物理内存暴露给程序。可以把内存想象成中医中放草药的盒子,每个盒子都有标记放的是哪种草药,当有两种草药同时放到一个盒子中去,就会出现医疗事故。 所以,这种情况下的内存管理是有问题的: 为了解决保护和重定位的问题,人们创造了一个新的内存抽象:地址空间。地址空间是一个进程可用于寻址内存的一套地址集合。每个进程都有一个自己的地址空间,并且这个地址空间独立于其他的地址空间。 地址空间在现实生活中有多的应用。比如电话的区号,北京是010,上海是021。这样即使同一个电话号码,区号不同也能区分开来。 考虑上个例子中的程序A、B,如果使用地址空间的话,B程序跳转28,就不会跳转到A程序的指令了。因为两个28分别属于不同地址空间。 了解地址空间这个概念,接下来看一下计算机是如何实现将两个28映射到不同地址空间里的。 经典的办法是给每个CPU配置两个寄存---基址寄存器和界限寄存器。基址寄存器记录程序的起始物理地址,界限寄存器记录程序的长度。 还是用这个图举例,程序A的基址为0,界限为16384,程序B基址为16384,界限值为32768。每次一个进程访问内存时,取一条指令,读或写一个数据字,CPU硬件会把地址发送到内存总线前自动把基址值加到进程发出的地址上。比如,进程A发出的访问地址是28,而A的基址是0,那么,A实际访问的物理地址就是28,而进程B的基址为16384,加上28,得到的地址为16412,进程B实际访问的地址是16412.这样就解决了之前提到过的绝对物理地址所带来的问题。 按照帕金森定律,“不论存储器有多大,程序都可以把它填满”。当程序大小超过内存容量时,计算机应该如何管理内存? 有两种处理内存超载的通用方法。一种是交换技术,即把一个进程完整调入内存,使该进程运行一段数据啊in,然后存回磁盘。空闲进程主要存在于磁盘上,所以,当他们不运行的时候不会占用内存。另一种是虚拟内存,该策略允许程序在只有一部分被调入内存的情况下运行。 我们重点关注虚拟内存。大体包含以下内容: 虚拟内存基本思想是每个程序都有自己的地址空间,这个空间被分割成多个块。每个块称作一页或页面。每一页有连续的地址范围。这些页被映射到物理内存,但是并不是所有的页都必须在内存中才能运行程序。当程序引用到一部分在物理内存中的地址空间时,由硬件执行必要的映射。当程序引用到一部分不在物理内存中的的地址空间时,由操作系统负责将缺失的部分装入物理内存并重新执行失败的指令。 至此,对操作系统中的内存管理有了一个大体的了解,如内存模型对象的发展过程,每种内存管理的优缺点。同时我感受到了提出问题,解决问题这条线索也是阅读计算机书籍的一个思路。2023-08-30 08:28:441
内存管理的功能主要体现在哪些方面?
分配、收回。2023-08-30 08:28:592
常用的内存管理方法有哪几种
常用的内存管理 方法 有哪几种?下面是我给大家收集整理的一些相关方法技巧,希望对大家有帮助! 常用的内存管理方法 传统的内存整理软件工作原理大概是:先申请一块“巨大内存”。因为物理内存几乎全被内存整理软件占用,因此Windows被迫把其他软件的内存数据转移到硬盘上的“虚拟内存交换文件”(PageFile)中,完成这一过程之后内存整理软件就会释放掉刚刚申请的内存,至此整理过程完成,可用物理内存显著增加。 大体上都是那么回事,就是通过辅助空间,重新安排内存内容 .... 但是其中使用的算法,效率是有很大的区别的 ~~ <script type="text/javascript"><!-- google_ad_client = "pub-4403405132739389"; google_ad_width = 250; google_ad_height = 250; google_ad_format = "250x250_as"; google_ad_type = "text"; //2007-10-22: 250*250 google_ad_channel = "7687946060"; google_ui_features = "rc:10"; //--> </script><script type="text/javascript" src=pagead2.googlesyndication/pagead/show_ads.js"> </script> 拓荒时代 国内的程序员大多是在 Java 语言中第一次感受到垃圾收集技术的巨大魅力的,许多人也因此把 Java 和垃圾收集看成了密不可分的整体。但事实上,垃圾收集技术早在 Java 语言问世前 30 多年就已经发展和成熟起来了, Java 语言所做的不过是把这项神奇的技术带到了广大程序员身边而已。 如果一定要为垃圾收集技术找一个孪生兄弟,那么, Lisp 语言才是当之无愧的人选。 1960 年前后诞生于 MIT 的 Lisp 语言是第一种高度依赖于动态内存分配技术的语言: Lisp 中几乎所有数据都以“表”的形式出现,而“表”所占用的空间则是在堆中动态分配得到的。 Lisp 语言先天就具有的动态内存管理特性要求 Lisp 语言的设计者必须解决堆中每一个内存块的自动释放问题(否则, Lisp 程序员就必然被程序中不计其数的 free 或 delete 语句淹没),这直接导致了垃圾收集技术的诞生和发展——说句题外话,上大学时,一位老师曾告诉我们, Lisp 是对现代软件开发技术贡献最大的语言。我当时对这一说法不以为然:布满了圆括号,看上去像迷宫一样的 Lisp 语言怎么能比 C 语言或 Pascal 语言更伟大呢?不过现在,当我知道垃圾收集技术、数据结构技术、人工智能技术、并行处理技术、虚拟机技术、元数据技术以及程序员们耳熟能详的许多技术都起源于 Lisp 语言时,我特别想向那位老师当面道歉,并收回我当时的幼稚想法。 知道了 Lisp 语言与垃圾收集的密切关系,我们就不难理解,为什么垃圾收集技术的两位先驱者 J. McCarthy 和 M. L. Minsky 同时也是 Lisp 语言发展史上的重要人物了。 J. McCarthy 是 Lisp 之父,他在发明 Lisp 语言的同时也第一次完整地描述了垃圾收集的算法和实现方式; M. L. Minsky 则在发展 Lisp 语言的过程中成为了今天好几种主流垃圾收集算法的奠基人——和当时不少技术大师的经历相似, J. McCarthy 和 M. L. Minsky 在许多不同的技术领域里都取得了令人艳羡的成就。也许,在 1960 年代那个软件开发史上的拓荒时代里,思维敏捷、意志坚定的研究者更容易成为无所不能的西部硬汉吧。 在了解垃圾收集算法的起源之前,有必要先回顾一下内存分配的主要方式。我们知道,大多数主流的语言或运行环境都支持三种最基本的内存分配方式,它们分别是: 一、静态分配( Static Allocation ):静态变量和全局变量的分配形式。我们可以把静态分配的内存看成是家里的耐用家具。通常,它们无需释放和回收,因为没人会天天把大衣柜当作垃圾扔到窗外。 二、自动分配( Automatic Allocation ):在栈中为局部变量分配内存的方法。栈中的内存可以随着代码块退出时的出栈操作被自动释放。这类似于到家中串门的访客,天色一晚就要各回各家,除了个别不识时务者以外,我们一般没必要把客人捆在垃圾袋里扫地出门。 三、动态分配( Dynamic Allocation ):在堆中动态分配内存空间以存储数据的方式。堆中的内存块好像我们日常使用的餐巾纸,用过了就得扔到垃圾箱里,否则屋内就会满地狼藉。像我这样的懒人做梦都想有一台家用机器人跟在身边打扫卫生。在软件开发中,如果你懒得释放内存,那么你也需要一台类似的机器人——这其实就是一个由特定算法实现的垃圾收集器。 也就是说,下面提到的所有垃圾收集算法都是在程序运行过程中收集并清理废旧“餐巾纸”的算法,它们的操作对象既不是静态变量,也不是局部变量,而是堆中所有已分配内存块。 引用计数( Reference Counting )算法 1960 年以前,人们为胚胎中的 Lisp 语言设计垃圾收集机制时,第一个想到的算法是引用计数算法。拿餐巾纸的例子来说,这种算法的原理大致可以描述为: 午餐时,为了把脑子里突然跳出来的设计灵感记下来,我从餐巾纸袋中抽出一张餐巾纸,打算在上面画出系统架构的蓝图。按照“餐巾纸使用规约之引用计数版”的要求,画图之前,我必须先在餐巾纸的一角写上计数值 1 ,以表示我在使用这张餐巾纸。这时,如果你也想看看我画的蓝图,那你就要把餐巾纸上的计数值加 1 ,将它改为 2 ,这表明目前有 2 个人在同时使用这张餐巾纸(当然,我是不会允许你用这张餐巾纸来擦鼻涕的)。你看完后,必须把计数值减 1 ,表明你对该餐巾纸的使用已经结束。同样,当我将餐巾纸上的内容全部誊写到 笔记本 上之后,我也会自觉地把餐巾纸上的计数值减 1 。此时,不出意外的话,这张餐巾纸上的计数值应当是 0 ,它会被垃圾收集器——假设那是一个专门负责打扫卫生的机器人——捡起来扔到垃圾箱里,因为垃圾收集器的惟一使命就是找到所有计数值为 0 的餐巾纸并清理它们。 引用计数算法的优点和缺陷同样明显。这一算法在执行垃圾收集任务时速度较快,但算法对程序中每一次内存分配和指针操作提出了额外的要求(增加或减少内存块的引用计数)。更重要的是,引用计数算法无法正确释放循环引用的内存块,对此, D. Hillis 有一段风趣而精辟的论述: 一天,一个学生走到 Moon 面前说:“我知道如何设计一个更好的垃圾收集器了。我们必须记录指向每个结点的指针数目。” Moon 耐心地给这位学生讲了下面这个 故事 :“一天,一个学生走到 Moon 面前说:u2018我知道如何设计一个更好的垃圾收集器了u2026u2026u2019” D. Hillis 的故事和我们小时候常说的“从前有座山,山上有个庙,庙里有个老和尚”的故事有异曲同工之妙。这说明,单是使用引用计数算法还不足以解决垃圾收集中的所有问题。正因为如此,引用计数算法也常常被研究者们排除在狭义的垃圾收集算法之外。当然,作为一种最简单、最直观的解决方案,引用计数算法本身具有其不可替代的优越性。 1980 年代前后, D. P. Friedman , D. S. Wise , H. G. Baker 等人对引用计数算法进行了数次改进,这些改进使得引用计数算法及其变种(如延迟计数算法等)在简单的环境下,或是在一些综合了多种算法的现代垃圾收集系统中仍然可以一展身手。 标记-清除( Mark-Sweep )算法 第一种实用和完善的垃圾收集算法是 J. McCarthy 等人在 1960 年提出并成功地应用于 Lisp 语言的标记-清除算法。仍以餐巾纸为例,标记-清除算法的执行过程是这样的: 午餐过程中,餐厅里的所有人都根据自己的需要取用餐巾纸。当垃圾收集机器人想收集废旧餐巾纸的时候,它会让所有用餐的人先停下来,然后,依次询问餐厅里的每一个人:“你正在用餐巾纸吗?你用的是哪一张餐巾纸?”机器人根据每个人的回答将人们正在使用的餐巾纸画上记号。询问过程结束后,机器人在餐厅里寻找所有散落在餐桌上且没有记号的餐巾纸(这些显然都是用过的废旧餐巾纸),把它们统统扔到垃圾箱里。 正如其名称所暗示的那样,标记-清除算法的执行过程分为“标记”和“清除”两大阶段。这种分步执行的思路奠定了现代垃圾收集算法的思想基础。与引用计数算法不同的是,标记-清除算法不需要运行环境监测每一次内存分配和指针操作,而只要在“标记”阶段中跟踪每一个指针变量的指向——用类似思路实现的垃圾收集器也常被后人统称为跟踪收集器( Tracing Collector ) 伴随着 Lisp 语言的成功,标记-清除算法也在大多数早期的 Lisp 运行环境中大放异彩。尽管最初版本的标记-清除算法在今天看来还存在效率不高(标记和清除是两个相当耗时的过程)等诸多缺陷,但在后面的讨论中,我们可以看到,几乎所有现代垃圾收集算法都是标记-清除思想的延续,仅此一点, J. McCarthy 等人在垃圾收集技术方面的贡献就丝毫不亚于他们在 Lisp 语言上的成就了。 复制( Copying )算法 为了解决标记-清除算法在垃圾收集效率方面的缺陷, M. L. Minsky 于 1963 年发表了著名的论文“一种使用双存储区的 Lisp 语言垃圾收集器( A LISP Garbage Collector Algorithm Using Serial Secondary Storage )”。 M. L. Minsky 在该论文中描述的算法被人们称为复制算法,它也被 M. L. Minsky 本人成功地引入到了 Lisp 语言的一个实现版本中。 复制算法别出心裁地将堆空间一分为二,并使用简单的复制操作来完成垃圾收集工作,这个思路相当有趣。借用餐巾纸的比喻,我们可以这样理解 M. L. Minsky 的复制算法: 餐厅被垃圾收集机器人分成南区和北区两个大小完全相同的部分。午餐时,所有人都先在南区用餐(因为空间有限,用餐人数自然也将减少一半),用餐时可以随意使用餐巾纸。当垃圾收集机器人认为有必要回收废旧餐巾纸时,它会要求所有用餐者以最快的速度从南区转移到北区,同时随身携带自己正在使用的餐巾纸。等所有人都转移到北区之后,垃圾收集机器人只要简单地把南区中所有散落的餐巾纸扔进垃圾箱就算完成任务了。下一次垃圾收集的工作过程也大致类似,惟一的不同只是人们的转移方向变成了从北区到南区。如此循环往复,每次垃圾收集都只需简单地转移(也就是复制)一次,垃圾收集速度无与伦比——当然,对于用餐者往返奔波于南北两区之间的辛劳,垃圾收集机器人是决不会流露出丝毫怜悯的。 M. L. Minsky 的发明绝对算得上一种奇思妙想。分区、复制的思路不仅大幅提高了垃圾收集的效率,而且也将原本繁纷复杂的内存分配算法变得前所未有地简明和扼要(既然每次内存回收都是对整个半区的回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存就可以了),这简直是个奇迹!不过,任何奇迹的出现都有一定的代价,在垃圾收集技术中,复制算法提高效率的代价是人为地将可用内存缩小了一半。实话实说,这个代价未免也太高了一些。 无论优缺点如何,复制算法在实践中都获得了可以与标记-清除算法相比拟的成功。除了 M. L. Minsky 本人在 Lisp 语言中的工作以外,从 1960 年代末到 1970 年代初, R. R. Fenichel 和 J. C. Yochelson 等人也相继在 Lisp 语言的不同实现中对复制算法进行了改进, S. Arnborg 更是成功地将复制算法应用到了 Simula 语言中。 至此,垃圾收集技术的三大传统算法——引用计数算法、标记-清除算法和复制算法——都已在 1960 年前后相继问世,三种算法各有所长,也都存在致命的缺陷。从 1960 年代后期开始,研究者的主要精力逐渐转向对这三种传统算法进行改进或整合,以扬长避短,适应程序设计语言和运行环境对垃圾收集的效率和实时性所提出的更高要求。 走向成熟 从 1970 年代开始,随着科学研究和应用实践的不断深入,人们逐渐意识到,一个理想的垃圾收集器不应在运行时导致应用程序的暂停,不应额外占用大量的内存空间和 CPU 资源,而三种传统的垃圾收集算法都无法满足这些要求。人们必须提出更新的算法或思路,以解决实践中碰到的诸多难题。当时,研究者的努力目标包括: 第一,提高垃圾收集的效率。使用标记-清除算法的垃圾收集器在工作时要消耗相当多的 CPU 资源。早期的 Lisp 运行环境收集内存垃圾的时间竟占到了系统总运行时间的 40% !——垃圾收集效率的低下直接造就了 Lisp 语言在执行速度方面的坏名声;直到今天,许多人还条件反射似地误以为所有 Lisp 程序都奇慢无比。 第二,减少垃圾收集时的内存占用。这一问题主要出现在复制算法中。尽管复制算法在效率上获得了质的突破,但牺牲一半内存空间的代价仍然是巨大的。在计算机发展的早期,在内存价格以 KB 计算的日子里,浪费客户的一半内存空间简直就是在变相敲诈或拦路打劫。 第三,寻找实时的垃圾收集算法。无论执行效率如何,三种传统的垃圾收集算法在执行垃圾收集任务时都必须打断程序的当前工作。这种因垃圾收集而造成的延时是许多程序,特别是执行关键任务的程序没有办法容忍的。如何对传统算法进行改进,以便实现一种在后台悄悄执行,不影响——或至少看上去不影响——当前进程的实时垃圾收集器,这显然是一件更具挑战性的工作。 研究者们探寻未知领域的决心和研究工作的进展速度同样令人惊奇:在 1970 年代到 1980 年代的短短十几年中,一大批在实用系统中表现优异的新算法和新思路脱颖而出。正是因为有了这些日趋成熟的垃圾收集算法,今天的我们才能在 Java 或 .NET 提供的运行环境中随心所欲地分配内存块,而不必担心空间释放时的风险。 标记-整理( Mark-Compact )算法 标记-整理算法是标记-清除算法和复制算法的有机结合。把标记-清除算法在内存占用上的优点和复制算法在执行效率上的特长综合起来,这是所有人都希望看到的结果。不过,两种垃圾收集算法的整合并不像 1 加 1 等于 2 那样简单,我们必须引入一些全新的思路。 1970 年前后, G. L. Steele , C. J. Cheney 和 D. S. Wise 等研究者陆续找到了正确的方向,标记-整理算法的轮廓也逐渐清晰了起来: 在我们熟悉的餐厅里,这一次,垃圾收集机器人不再把餐厅分成两个南北区域了。需要执行垃圾收集任务时,机器人先执行标记-清除算法的第一个步骤,为所有使用中的餐巾纸画好标记,然后,机器人命令所有就餐者带上有标记的餐巾纸向餐厅的南面集中,同时把没有标记的废旧餐巾纸扔向餐厅北面。这样一来,机器人只消站在餐厅北面,怀抱垃圾箱,迎接扑面而来的废旧餐巾纸就行了。 实验表明,标记-整理算法的总体执行效率高于标记-清除算法,又不像复制算法那样需要牺牲一半的存储空间,这显然是一种非常理想的结果。在许多现代的垃圾收集器中,人们都使用了标记-整理算法或其改进版本。 增量收集( Incremental Collecting )算法 对实时垃圾收集算法的研究直接导致了增量收集算法的诞生。 最初,人们关于实时垃圾收集的想法是这样的:为了进行实时的垃圾收集,可以设计一个多进程的运行环境,比如用一个进程执行垃圾收集工作,另一个进程执行程序代码。这样一来,垃圾收集工作看上去就仿佛是在后台悄悄完成的,不会打断程序代码的运行。 在收集餐巾纸的例子中,这一思路可以被理解为:垃圾收集机器人在人们用餐的同时寻找废弃的餐巾纸并将它们扔到垃圾箱里。这个看似简单的思路会在设计和实现时碰上进程间冲突的难题。比如说,如果垃圾收集进程包括标记和清除两个工作阶段,那么,垃圾收集器在第一阶段中辛辛苦苦标记出的结果很可能被另一个进程中的内存操作代码修改得面目全非,以至于第二阶段的工作没有办法开展。 M. L. Minsky 和 D. E. Knuth 对实时垃圾收集过程中的技术难点进行了早期的研究, G. L. Steele 于 1975 年发表了题为“多进程整理的垃圾收集( Multiprocessing compactifying garbage collection )”的论文,描述了一种被后人称为“ Minsky-Knuth-Steele 算法”的实时垃圾收集算法。 E. W. Dijkstra , L. Lamport , R. R. Fenichel 和 J. C. Yochelson 等人也相继在此领域做出了各自的贡献。 1978 年, H. G. Baker 发表了“串行计算机上的实时表处理技术( List Processing in Real Time on a Serial Computer )”一文,系统阐述了多进程环境下用于垃圾收集的增量收集算法。 增量收集算法的基础仍是传统的标记-清除和复制算法。增量收集算法通过对进程间冲突的妥善处理,允许垃圾收集进程以分阶段的方式完成标记、清理或复制工作。详细分析各种增量收集算法的内部机理是一件相当繁琐的事情,在这里,读者们需要了解的仅仅是: H. G. Baker 等人的努力已经将实时垃圾收集的梦想变成了现实,我们再也不用为垃圾收集打断程序的运行而烦恼了。 分代收集( Generational Collecting )算法 和大多数软件开发技术一样,统计学原理总能在技术发展的过程中起到强力催化剂的作用。 1980 年前后,善于在研究中使用统计分析知识的技术人员发现,大多数内存块的生存周期都比较短,垃圾收集器应当把更多的精力放在检查和清理新分配的内存块上。这个发现对于垃圾收集技术的价值可以用餐巾纸的例子概括如下: 如果垃圾收集机器人足够聪明,事先摸清了餐厅里每个人在用餐时使用餐巾纸的习惯——比如有些人喜欢在用餐前后各用掉一张餐巾纸,有的人喜欢自始至终攥着一张餐巾纸不放,有的人则每打一个喷嚏就用去一张餐巾纸——机器人就可以制定出更完善的餐巾纸回收计划,并总是在人们刚扔掉餐巾纸没多久就把垃圾捡走。这种基于统计学原理的做法当然可以让餐厅的整洁度成倍提高。 D. E. Knuth , T. Knight , G. Sussman 和 R. Stallman 等人对内存垃圾的分类处理做了最早的研究。 1983 年, H. Lieberman 和 C. Hewitt 发表了题为“基于对象寿命的一种实时垃圾收集器( A real-time garbage collector based on the lifetimes of objects )”的论文。这篇著名的论文标志着分代收集算法的正式诞生。此后,在 H. G. Baker , R. L. Hudson , J. E. B. Moss 等人的共同努力下,分代收集算法逐渐成为了垃圾收集领域里的主流技术。 分代收集算法通常将堆中的内存块按寿命分为两类,年老的和年轻的。垃圾收集器使用不同的收集算法或收集策略,分别处理这两类内存块,并特别地把主要工作时间花在处理年轻的内存块上。分代收集算法使垃圾收集器在有限的资源条件下,可以更为有效地工作——这种效率上的提高在今天的 Java 虚拟机中得到了最好的证明。 应用浪潮 Lisp 是垃圾收集技术的第一个受益者,但显然不是最后一个。在 Lisp 语言之后,许许多多传统的、现代的、后现代的语言已经把垃圾收集技术拉入了自己的怀抱。随便举几个例子吧:诞生于 1964 年的 Simula 语言, 1969 年的 Smalltalk 语言, 1970 年的 Prolog 语言, 1973 年的 ML 语言, 1975 年的 Scheme 语言, 1983 年的 Modula-3 语言, 1986 年的 Eiffel 语言, 1987 年的 Haskell 语言u2026u2026它们都先后使用了自动垃圾收集技术。当然,每一种语言使用的垃圾收集算法可能不尽相同,大多数语言和运行环境甚至同时使用了多种垃圾收集算法。但无论怎样,这些实例都说明,垃圾收集技术从诞生的那一天起就不是一种曲高和寡的“学院派”技术。 对于我们熟悉的 C 和 C++ 语言,垃圾收集技术一样可以发挥巨大的功效。正如我们在学校中就已经知道的那样, C 和 C++ 语言本身并没有提供垃圾收集机制,但这并不妨碍我们在程序中使用具有垃圾收集功能的函数库或类库。例如,早在 1988 年, H. J. Boehm 和 A. J. Demers 就成功地实现了一种使用保守垃圾收集算法( Conservative GC Algorithmic )的函数库。我们可以在 C 语言或 C++ 语言中使用该函数库完成自动垃圾收集功能,必要时,甚至还可以让传统的 C/C++ 代码与使用自动垃圾收集功能的 C/C++ 代码在一个程序里协同工作。 1995 年诞生的 Java 语言在一夜之间将垃圾收集技术变成了软件开发领域里最为流行的技术之一。从某种角度说,我们很难分清究竟是 Java 从垃圾收集中受益,还是垃圾收集技术本身借 Java 的普及而扬名。值得注意的是,不同版本的 Java 虚拟机使用的垃圾收集机制并不完全相同, Java 虚拟机其实也经过了一个从简单到复杂的发展过程。在 Java 虚拟机的 1.4.1 版中,人们可以体验到的垃圾收集算法就包括分代收集、复制收集、增量收集、标记-整理、并行复制( Parallel Copying )、并行清除( Parallel Scavenging )、并发( Concurrent )收集等许多种, Java 程序运行速度的不断提升在很大程度上应该归功于垃圾收集技术的发展与完善。 尽管历史上已经有许多包含垃圾收集技术的应用平台和 操作系统 出现,但 Microsoft .NET 却是第一种真正实用化的、包含了垃圾收集机制的通用语言运行环境。事实上, .NET 平台上的所有语言,包括 C# 、 Visual Basic .NET 、 Visual C++ .NET 、 J# 等等,都可以通过几乎完全相同的方式使用 .NET 平台提供的垃圾收集机制。我们似乎可以断言, .NET 是垃圾收集技术在应用领域里的一次重大变革,它使垃圾收集技术从一种单纯的技术变成了应用环境乃至操作系统中的一种内在 文化 。这种变革对未来软件开发技术的影响力也许要远远超过 .NET 平台本身的商业价值。 大势所趋 今天,致力于垃圾收集技术研究的人们仍在不懈努力,他们的研究方向包括分布式系统的垃圾收集、复杂事务环境下的垃圾收集、数据库等特定系统的垃圾收集等等。 但在程序员中间,仍有不少人对垃圾收集技术不屑一顾,他们宁愿相信自己逐行编写的 free 或 delete 命令,也不愿把垃圾收集的重任交给那些在他们看来既蠢又笨的垃圾收集器。 我个人认为,垃圾收集技术的普及是大势所趋,这就像生活会越来越好一样毋庸置疑。今天的程序员也许会因为垃圾收集器要占用一定的 CPU 资源而对其望而却步,但二十多年前的程序员还曾因为高级语言速度太慢而坚持用机器语言写程序呢!在硬件速度日新月异的今天,我们是要吝惜那一点儿时间损耗而踟躇不前,还是该坚定不移地站在代码和运行环境的净化剂——垃圾收集的一边呢?2023-08-30 08:29:081
DOS是怎样进行内存管理的
DOS是怎样进行内存管理的?内存是计算机中存储程序代码以及数据的地方,是程序赖以运行的舞台。内存在计算机中编址,形成了内存地址空间,既包括了RAM内存,也包括了ROM内存。通常的内存编址方法是按字节(8bit进行的,1M内存便是指大小为1兆字节的内存空间。以PC机为例,早期的8086/8088系统共有20根地址线,则可寻址2^20=1M字节;80286系统则有24根地址线,相应可寻址2^24=16M字节,到了386、486,地址总线宽度扩大到了32根,可寻址的内存空间也扩大为4G字节。内存地址空间又称为物理地址空间,它是实际主存储器的大小;相对有虚拟地址空间的概念,也称逻辑地址空间,它指的是应用程序的编级地址空间。二者有时等同,有时相互区别,这取决于系统的内存管理策略。无论是早期的DOS版本,还是最近的6.22;DOS下直接使用的都是物理地址空间。如果要使用逻辑地址空间,你必须自己编程。这一点,我们后面还要讲到。DOS是单用户单作业操作系统,因此采用的是固定分区内存管理技术,把内存低端部分(1M以下)固定地分成系统区和用户区(TPA),见图4-3。当前版本的MS—DOS可以管理1MB的物理地址空间。在IBMPC及其兼容机上,由MS-DOS和其他程序所占的内存在地址0000H处开始,并可达地址09FFFFH,此640KB的RAM区域有时称为“常规内存区”。此地址以上的内存区是为ROM硬件驱动程序、视频刷新缓冲区等所保留的。非IBM兼容机有可能使用其他内存区段。在MS—DOS控制下的RAM区可分成两个主要部分:操作系统区域临时程序区域(TPA)操作系统区域在地址0000H处开始,即它占用RAM的最低部分。该处有中断向量表、操作系统模块及其所拥有的表(table)和缓冲区,以及 config.sys)文件中指定的附加可安装设备驱动程序及command.com命令解释程序的驻留部分。操作系统区所占的内存量随MS-DOS版本、磁盘缓冲区数、可安装设备驱动程序个数与大小而改变。临时程序区为RAM中所存操作系统区上面的剩余部分,是动态可分配的内存。DOS将在应用程序运行时总是试图把这部分内存分配给它,必要时系统区1(参见图4—3)将腾出以扩大TPA区。如果此区过小,则会出现。out of memory内存不够的错误,你的应用程序将无法运行。 当出现此错误时,在低版本DOS中将是一筹莫展,在8086/8088中亦是如此,最多能做到的是不装载任何TSR程序。这意味着你甚至需要牺牲鼠标器支持;而高版本DOS则可以利用将要讲到的两点功能(1)把DOS自身一部分装载到HMA中,(2)把TSR程序和驱动程序装载到UMB,从而达到扩大 TPA,供应用程序运行的目的。对于1M以上的内存,DOS将无能为力,除了下面将要讲到HMA以外。================================================================343.为什么在386、486的计算机上虽然有4M或更多的内存配置,却总是会出现“内存不够”的错误?这正是DOS的局限性所带来的。从前面的问题中我们可以看出,在DOS中,真正供应用程序运行区域是TPA。DOS为了保持与8086/8088系统兼容性,把TPA限制在1M以下.所以有时计算机虽有4M或更多内存,你也无法直接使用。当然,1M以上的内存也还是可以利用的。(1)在保护模式下,你可以直接寻址1M以上空问。DOS是无法做到这一点,而Windows或OS/2等其他操作系统可以做到。(2)利用DOS提供的工具,间接访问1M以上空间,如EMS或XMS技术。关于EMS和XMS请参见《如何使用扩充内存(Expanded)》和《如何使用扩展内存Extended)》。===============================346.什么是常规内存、扩充内存、扩展内存?常规内存(Conventional Memory)是指从00000H到9FFFPH这640k的内存空间,它是DOS的传统势力范围.DOS对这一段的划分和管理请参阅《DOS是怎样进行内存管理的》。扩充内存(Expanded Memory)是一种不参与存储器统一统址的内存。其使用规范称作EMS(Expanded Memory Sepecfication),因为是由Lotus,Intel和Microsoft三家公司联合开发的,故也称作LIM EMS。早期XT机型上扩充内存以内存卡的物理形式出现,后来的高档微机上则可以由扩展内存(Extended Memory)来仿真扩充内存,这是CPU开始支持内存映射的结果。扩展内存是原1MB内存空间的纵向延伸.这种内存只存在于80286以上的机型之中。这种内存,只是在“保护(protected)”方式时是可寻址的; DOS运行于real方式(实模式),仿真8086寻址空间,因此标准的DOS应用程序是不能直接访问它的。对286来说,CPU共有24根地址线,其扩展内存可达15MB,而在386,486或更高档机器上。扩展内存可拥有4GB-1MB的大小,这是因为它们的地址总线宽度为32位。===============================347 如何使用扩充内存(Expanded Memory)?因为扩充内存没有统一编址,所以CPU不能象访问普通的主存那样通过地址线来直接访问它。这中间就需要扩充内存管理程序EMM,也既是软件技术的支持。对扩充内存的访问有些像日常去图书馆借书。你是没有权力进入书库象查检自己的书柜那样进行“访问”的,只有去到柜台那儿,交给管理员小姐您的索书单,她便进库去找寻您要的书,找到之后回来再为您办理手续——如果把书库看作您自家书柜这一主存的扩充内存的话,管理员小姐便是EMM,您便是CPU。柜台呢,则称作页框.页框的大小是64K,为什么是64K呢?您一定记得8086的段式访问机制,一个段的大小便是64k。这样,只要知道了页框起始处的段地址,就可以通过一个偏移量指针遍历整个页框,如果超过64K,那就需要调整段地址了.或许EMS的设计者考虑到内存的使用效率而把扩充内存以16k为单位进行组织划分,而不是一个页框的大小。现在EMS内中的每16k就称作一页,那么 CPU同时也就只能“看见”扩充内存其中四页,虽然程序可以申请到不止四页的扩充内存。这自然类似于图书馆的制度,您可以“借”图书馆的许多书,甚至全部的书,但一次您只能“惜到”十本书,看完归还之后再来借.编程中对扩充内存进行访问的步骤大致如下:(1)EMM安装了没有?无论是EMM386.EXE还是QEMM386.SYS等EMM程序,具有统一的设备名“EMMxxxx”,我们可以通过判断此设备是否安装来判断EMM存在与否?(2)页框起始地址在何处?这是判断EMM已安装后的第二个步骤。页框是我们“看到”EMS内存的窗口,当然首先要找到它。(3)申请EMS内存如果您估计您的程序数据量不会超过1MB,那就申请64页的扩充内存好了(当然要实际存在如此多的扩充内存才可以,EMM不可能无中生有),申请到的EMS内存由一个称作句柄的整数来标志管理.当然您可以随时根据需要多次申请EMS内存,只不过处理多个句柄总是要多些麻烦。(4)映射EMS内存申请到了一些EMS内存页面,意味着你可以“看”它们,但迄今为止它们并不“可见”,还需要进行映射。映射的意思,也就告诉EMM,让它把哪一个句柄的哪四页(少一些页自然可以),放到页框这个窗口中来。做完映射工作之后,您就可以往页框中存放,读取数据了.当这几页用完之后.再映射其它几页到页框中,而原来的四页则不再‘可见"。如此这般,您就可以把您大量的数据存放到EMS内存中。(5)释放EMS内存当工作完成之后,还需要把申请到的EMS内存加以释放,因为EMM无法判断程序的结束而主动地来完成这项工作。这一系列步骤使得EMS内存的使用看起来有些麻烦。的确,EMS内存的使用在一定程度上降低了系统性能.但这是值得的,要知道世界上没有免费的午餐.。。。。。。================================== 348.如何使用扩展内存(Extended Memory)?早期在DOS下访问扩展内存,必须通过BIOS中断INT l5H,但是因为该接口功能不够严谨,各软件之间容易因为使用扩展内存而发生冲突.有鉴于此,1988年底Microsoft,Intel,Lotus和AST四家公司共同开发出了关于存取扩展内存的标准,这就是扩展内存规范XMS(Extended Memory Specification).为了兼容性,大多数XMS驱动程序都可以为INT l5H保留一席之地.DOS及DOS应用程序无法直接访问扩展内存,必须通过XMS功能接口达到目的.XMS编程大致可分以下几个步骤:(1)判断XMS是否已安装这一点可以通过调用INT 2FH的4300H 号子功能来实现,通常INT 2FH以其“假脱机打印”功能而闻名。功能调用之后,若寄存器AL=80H 表示XMS驱动程序已安装,反之则否.(2)申请XMS内存块 "XMS编程接口有一点很特殊,不同于一般的中断调用,就是各子功能的执行是要对XMS驱动程序入口点进行远调用,而不是中断调用.XMS驱动程序的入口地址可以通过INT 2FH的子功能4310H号来得到.调用完毕后,ES:BX即为入口点.。。。。。。(3)数据的存取申请到了扩展内存,但我们并不能直接使用它,仍需要先把数据存放在一个常规内存缓冲区内,待恰当时机再把数据从缓冲区移到扩展内存之中.这一点对应XMS的0BH 号子功能:移动扩展内存块。(4)释放扩展内存该子功能号为0AH,入口参数为要释放的扩展内存块的句柄.对于上面的讨论,请进一步阅读有关资料,以得到更详尽的信息.下面给出一个完整的例子,供你参考。。。。。。。==================================349.什么是UMB? 如何使用UMB?640K~1MB这一段地址空间是微机的设计者保留下来给系统以及外部扩展设备来使用的,因此在这一段之中没有系统板上的RAM.如果您的机器配置了 1MB的内存,并且机器没有打开明SHADOW功能的话,将会有384k的扩展内存,此时RAM最高地址为1408K。这一段地址空间某些部分的分配是比较固定的:。。。。。。其他部分的地址空间则没有固定地被占用,由其他硬件扩展设备,如汉卡、网卡等等来选择.一般情况下,这些空闲地址空间可用来再生成上位内存块UMB,供DOS利用.让我们来看一个VGA配置的PC兼容机有多大的空闲空间。首先B000—B7FF这一段32k的空闲,再就是从C800开始到EFFF结束的这一段,大小为160k——所以我们总共可以有192KB的空间提供给DOS。如果再算上HMA 64K的话,就意味着DOS拥有了896k=(640+192+64)K 的空间!事情总要打点折扣,首先如果你安装了网卡,便只有牺牲16K的大小(通常情况);如果您的应用程序需要扩充内存,或者通过扩充内存卡获得,或者通过 EMM386.exe等类似的EMM程序利用扩展内存来仿真得到,但都必须在640k--1MB这一段的空闲区内生成一个EMS页框,又会占去64K的大小.另外一个问题是保留内存中的空闲区并不连续,在插入其他插卡后有可能被再次分割.如果一个网卡占用了E000~E3FF这16K,原选160k的连续空闲区将被分割为两块,一块96K,一块48K。这就使得DOS在把驱动程序、内存驻留程序装载到UMB运行时,不可避免地造成空间浪费,不能充分利用.这儿是用MSD察看保留内存区的一个例子。。。。。。。保留内存区又称上位内存区UMA,所以利用其间的空闲地址再生成的RAM块被称作UMB,也就是上位内存块的意思。为了使DOS能够利用UMB,仅仅在CONFIG.SYS中加载EMM386.exe之类的UMB Provider程序还是不够的,必须再通过命令DOS=UMB在二者之间建立起联系,这样DOS的DEVICEHIGH、LH命令才起作用,DOS的中断功能调用也才能够访问UMB。如果没有在CONFIG中运行DOS=UMB,则利用MSD、MEM等实用程序将无法看到UMB的影子,但此时应用程序可以直接向UMB Provider程序申请使用UMB。==================================350,什么是HMA?如何使用HMA?高位内存区HMA可能是最近人摸不着头脑的东西,它是1MB以上的第一个64K,其实要少16个字节,也就是65520字节的大小.这一段可以为DOS直接访问。不是说DOS只能直接访问1MB以下的内存区域吗? 我们已知道,DOS的寻址方式是8086/8088的段式机制,16位段地址左移四位再加上16位的偏移量形成20位的地址。这样问题便来了,1MB的绝对地址可以写成段:偏移量的形成为FFFF:000FH,也就是该段起于1MB空间的最后一小节FFFF0H 处;如图4-4所示,很明显,该段还有一部分的空间在1MB以上,也就是扩展内存之内.为FFFF:000FH只是该段的第一个小节结束的地方;偏移量还有FFF0的“余量”, 这“余量”确定的空间显然可以由DOS直接访问,只得把编移量累加上去就行了.该段的1MB以上区域便是HMA,很显然其大小为64K-16B.从绝对地址的角度看,HMA的第一个字节地址FFFF:0010H 已是21位地址宽度:1000000H.这在8086/8088中将产生地址绕回错误,因为8086/8088只有20根地址线,第21根子虚乌有,所以1000000H 处即为0000OH 处.这样,“HMA”便成了0000:0000H至0OOO:FFEFH这一段!早期的一些应用程序利用这一点来作为特殊技巧,达到所需的编程效果,也就是说,它们依赖于地址回绕.所以,到了后来的286、386等机器,虽然CPU拥有了24根、32根的地址总线,解决了8086/8088中16位地址进位超出总线宽度的问题,却为了保持兼容性,并没有把HMA区直接向DOS开放,而是通过—个“开关”进行控制.这个“开关”便是我们常常见到的A20 line。A20便是第21根地址线,众所周知,计算机中的总线都是从0开始编号的.DOS下HMA区的管理由HIMEM.SYS来提供。程序可以控制A20 line的开、关,可以申请使用HMA,但有一点,HMA不能分割使用,也就是说一次只能有一个程序在其间运行.如果在CONFIG.SYS文件中加载了 HIMEM.SYS驱动程序并且同时有DOS=high命令时,MS-DOS将使A20线有效,并为HMA直新定位系统代码.。。。。。。笔者建议在编程中不要试图去使用HMA,免得遇到很多不必要的麻烦,利用HMA的最理想方法便是通过在CONFIG.SYS中加载HIMEM.SYS并运行DOS=high命令,把MS-DOS系统代码加载至其中,从而腾出更多的常规内存来.在DOS 6.2版本中,DOS=high命令可腾出约49K的空间出来.关于HMA的使用和编程,请进一步阅读有关的详细资料.=============================351.如何使用HIMEM.SYS?HIMEM.SYS是一扩展(Extended)内存管理程序,也就是常说的XMM,它为扩展内存的使用提供了统一接口标准XMS,避免了早期扩展内存使用当中存在的冲突问题;同时HIMEM.SYS还提供对HMA的管理.HIMEM.SYS必须在CONFIG.SYS中首先加载,这一点很容易理解,在EMM386.EXE加载之后,保留内存区持有UMB出现, HIMEM.SYS也提供对UMB进行管理的接口.如果在CONFIG.SYS没有运行DOS=UMB命令,也即没有建立起DOS和UMB之间的联系时,应用程序可以直接向HIMEM.SYS申请使用UMB.============================= 352.如何使用EMM386.EXE?EMM386.EXE利用扩展(Extended)内存来仿真扩充(Expanded)内存,以提供对需要扩充内存的应用程序的支持,同时它还提供UMB功能,使得一些设备驱动程序和内存驻留程序能够加载至UMB中,从而腾出更多的常规内存。EMM386.EXE在CONFIG.SYS中必须位于HIMEM.SYS之后来加载,因为它依赖于HIMEM.SYS的扩展内存支持。这二者也都必须使用DEVICE来加载,而不是DEVICEHIGH,这是因为DEVICEHIGH依赖于EMM386.EXE提供的UMB功能。同理,要在AUTOEXEC.BAT中使用LOADHIGH(LH)命令也必须在CONFIG.SYS中已加载EMM386.EXE前提之下,并使用DOS=UMB命令在DOS和UMB之间建立起联系。2023-08-30 08:29:301
内存管理有哪些主要功能?其主要任务是什么?
内存管理主要是存储视频或者文件,而主要功能主要是缓解储存空间的不足,或者让运行更快。2023-08-30 08:29:371
内存分区管理的方法有哪些
一、固定分区存储管理其基本思想是将内存划分成若干固定大小的分区,每个分区中最多只能装入一个作业。当作业申请内存时,系统按一定的算法为其选择一个适当的分区,并装入内存运行。由于分区大小是事先固定的,因而可容纳作业的大小受到限制,而且当用户作业的地址空间小于分区的存储空间时,造成存储空间浪费。1、空间的分配与回收系统设置一张“分区分配表”来描述各分区的使用情况,登记的内容应包括:分区号、起始地址、长度和占用标志。其中占用标志为“0”时,表示目前该分区空闲;否则登记占用作业名(或作业号)。有了“分区分配表”,空间分配与回收工作是比较简单的。2、地址转换和存储保护固定分区管理可以采用静态重定位方式进行地址映射。为了实现存储保护,处理器设置了一对“下限寄存器”和“上限寄存器”。当一个已经被装入主存储器的作业能够得到处理器运行时,进程调度应记录当前运行作业所在的分区号,且把该分区的下限地址和上限地址分别送入下限寄存器和上限寄存器中。处理器执行该作业的指令时必须核对其要访问的绝对地址是否越界。3、多作业队列的固定分区管理为避免小作业被分配到大的分区中造成空间的浪费,可采用多作业队列的方法。即系统按分区数设置多个作业队列,将作业按其大小排到不同的队列中,一个队列对应某一个分区,以提高内存利用率。二、可变分区存储管理可变分区存储管理不是预先将内存划分分区,而是在作业装入内存时建立分区,使分区的大小正好与作业要求的存储空间相等。这种处理方式使内存分配有较大的灵活性,也提高了内存利用率。但是随着对内存不断地分配、释放操作会引起存储碎片的产生。1、空间的分配与回收采用可变分区存储管理,系统中的分区个数与分区的大小都在不断地变化,系统利用“空闲区表”来管理内存中的空闲分区,其中登记空闲区的起始地址、长度和状态。当有作业要进入内存时,在“空闲区表”中查找状态为“未分配”且长度大于或等于作业的空闲分区分配给作业,并做适当调整;当一个作业运行完成时,应将该作业占用的空间作为空闲区归还给系统。可以采用首先适应算法、最佳(优)适应算法和最坏适应算法三种分配策略之一进行内存分配。2、地址转换和存储保护可变分区存储管理一般采用动态重定位的方式,为实现地址重定位和存储保护,系统设置相应的硬件:基址/限长寄存器(或上界/下界寄存器)、加法器、比较线路等。基址寄存器用来存放程序在内存的起始地址,限长寄存器用来存放程序的长度。处理机在执行时,用程序中的相对地址加上基址寄存器中的基地址,形成一个绝对地址,并将相对地址与限长寄存器进行计算比较,检查是否发生地址越界。3、存储碎片与程序的移动所谓碎片是指内存中出现的一些零散的小空闲区域。由于碎片都很小,无法再利用。如果内存中碎片很多,将会造成严重的存储资源浪费。解决碎片的方法是移动所有的占用区域,使所有的空闲区合并成一片连续区域,这一技术称为移动技术(紧凑技术)。移动技术除了可解决碎片问题还使内存中的作业进行扩充。显然,移动带来系统开销加大,并且当一个作业如果正与外设进行I/O时,该作业是无法移动的。2023-08-30 08:29:441
计算机管理内存的方法有哪些?优缺点是什么?
你这个问题太………………2023-08-30 08:29:553
常用的内存管理方法有哪些?
下一个 z武器 或者优化大师就非常清楚了2023-08-30 08:30:102
操作系统具有五大功能,分别都是什么?
处理机管理、存储器管理、设备管理、文件管理、用户接口2023-08-30 08:30:193
打开电视就显示内存空间不足,建议清理。如何清理海信电视?
如果你的内存不足的话,建议你清理一下内存就可以了。2023-08-30 08:30:288
内存管理的内存对象
Windows应用程序可以申请分配属于自己的内存块,内存块是应用程序操作内存的单位,它也称作内存对象,在Windows中通过内存句柄来操作内存对象。内存对象根据分配的范围可分为全局内存对象和局部内存对象;根据性质可分为固定内存对象,可移动内存对象和可删除内存对象。固定内存对象,特别是局部固定内存对象和DOS的内存块很类似,它一旦分配,就不会被移动或删除,除非应用程序主动释放它。并且对于局部固定内存对象来说,它的内存句柄本身就是内存对象的16位近地址,可供应用程序直接存取,而不必象其它类型的内存对象那样要通过锁定在内存某固定地址后才能使用。可移动内存对象没有固定的地址,Windows系统可以随时把它们移到一个新地址。内存对象的可移动使得Windows能有效地利用自由内存。例如,如果一个可移动的内存对象分开了两个自由内存对象,Windows可以把可移动内存对象移走,将两个自由内存对象合并为一个大的自由内存对象,实现内存的合并与碎片回收。可删除内存对象与可移动内存对象很相似,它可以被Windows移动,并且当Windows需要大的内存空间满足新的任务时,它可以将可删除内存对象的长度置为0,丢弃内存对象中的数据。可移动内存对象和可删除内存对象在存取前必须使用内存加锁函数将其锁定,锁定了的内存对象不能被移动和删除。因此,应用程序在使用完内存对象后要尽可能快地为内存对象解锁。内存需要加锁和解锁增加了程序员的负担,但是它却极大地改善了Windows内存利用的效率,因此Windows鼓励使用可移动和可删除的内存对象,并且要求应用程序在非必要时不要使用固定内存对象。不同类型的对象在它所处的内存堆中的位置是不一样的,图6.2说明内存对象在堆中的位置:固定对象位于堆的底部;可移动对象位于固定对象之上;可删除对象从堆的顶部开始分配。 局部内存对象在局部堆中分配,局部堆是应用程序独享的自由内存,它只能由应用程序的特定实例访问。局部堆建立在应用程序的数据段中,因此,用户可分配的局部内存对象的最大内存空间不能超过64K。局部堆由Windows应用程序在模块定义文件中用HEAPSIZE语句申请,HEAPSIZE指定以字节为单位的局部堆初始空间尺寸。Windows提供了一系列函数来操作局部内存对象。分配局部内存对象LocalAlloc函数用来分配局部内存,它在应用程序局部堆中分配一个内存块,并返回内存块的句柄。LocalAlloc函数可以指定内存对象的大小和特性,其中主要特性有固定的(LMEM_FIXED),可移动的(LMEM_MOVEABLE)和可删除的(LMEM_DISCARDABLE)。如果局部堆中无法分配申请的内存,则LocalAlloc函数返回NULL。下面的代码用来分配一个固定内存对象,因为局部固定内存对象的对象句柄其本身就是16位内存近地址,因此它可以被应用程序直接存取。加锁与解锁上面程序段分配的固定局部内存对象可以由应用程序直接存取,但是,Windows并不鼓励使用固定内存对象。因此,在使用可移动和可删除内存对象时,就要经常用到对内存对象的加锁与解锁。不管是可移动对象还是可删除对象,在它分配后其内存句柄是不变的,它是内存对象的恒定引用。但是,应用程序无法通过内存句柄直接存取内存对象,应用程序要存取内存对象还必须获得它的近地址,这通过调用LocalLock函数实现。LocalLock函数将局部内存对象暂时固定在局部堆的某一位置,并返回该地址的近地址值,此地址可供应用程序存取内存对象使用,它在应用程序调用 LocalUnlock函数解锁此内存对象之前有效。应用程序在使用完内存对象后,要尽可能早地为它解锁,这是因为Windows无法移动被锁住了的内存对象。当应用程序要分配其它内存时,Windows不能利用被锁住对象的区域,只能在它周围寻找,这会降低Windows内存管理的效率。改变局部内存对象局部内存对象分配之后,还可以调用LocalReAlloc函数进行修改。LocalReAlloc函数可以改变局部内存对象的大小而不破坏其内容:如果比原来的空间小,则Windows将对象截断;如果比原来大,则Windows将增加区域填0(使用LMEM_ZEROINIT选项),或者不定义该区域内容。另外,LocalReAlloc函数还可以改变对象的属性,如将属性从LMEM_MOVEABLE改为LMEM_DISCARDABLE,或反过来,此时必须同时指定LMEM_MODIFY选项。但是,LocalReAlloc函数不能同时改变内存对象的大小和属性,也不能改变具有LMEM_FIXED属性的内存对象和把其它属性的内存对象改为LMEM_FIXED属性。释放与删除分配了的局部内存对象可以使用LocalDiscard和LocalFree函数来删除和释放,删除和释放只有在内存对象未锁住时才有效。LocalFree函数用来释放局部内存对象,当一个局部内存对象被释放时,其内容从局部堆移走,并且其句柄也从有效的局部内存表中移走,原来的内存句柄变为不可用。LocalDiscard 函数用来删除局部内存对象,它只移走对象的内容,而保持其句柄有效,用户在需要时,还可以使用此内存句柄用LocalReAlloc函数重新分配一块内存。另外,Windows还提供了函数LocalSize用于检测对象所占空间;函数LocalFlags用于检测内存对象是否可删除,是否已删除,及其锁计数值;函数LocalCompact用于确定局部堆的可用内存。 全局内存对象在全局堆中分配,全局堆包括所有的系统内存。一般来说,应用程序在全局堆中进行大型内存分配(约大于1KB),在全局堆还可以分配大于64K的巨型内存,这将在后面介绍。分配全局内存对象全局内存对象使用GlobalAlloc函数分配,它和使用LocalAlloc分配局部内存对象很相似。使用GlobalAlloc的例子我们将和GlobalLock一起给出。加锁与解锁全局内存对象使用GlobalLock函数加锁,所有全局内存对象在存取前都必须加锁。GlobalLock将对象锁定在内存固定位置,并返回一个远指针,此指针在调用GlobalUnlock之前保持有效。GlobalLock和LocalLock稍有不同,因为全局内存对象可能被多个任务使用,因此在使用GlobalLock加锁某全局内存对象时,对象可能已被锁住,为了处理这种情况,Windows增加了一个锁计数器。当使用GlobalLock加锁全局内存对象时,锁计数器加1;使用GlobalUnlock解锁对象时,锁计数器减1,只有当锁计数器为0时,Windows才真正解锁此对象。修改全局内存对象修改全局内存对象使用GlobalReAlloc函数,它和LocalReAlloc函数很类似,这里不再赘述。修改全局内存对象的特殊之处在于巨型对象的修改上,这一点我们将在后面讲述。内存释放及其它操作全局内存对象使用GlobalFree函数和GlobalDiscard来释放与删除,其作用与LocalFree和LocalDiscard类似。GlobalSize函数可以检测内存对象大小;GlobalFlags函数用来检索对象是否可删除,是否已删除等信息;GlobalCompact函数可以检测全局堆可用内存大小。巨型内存对象如果全局内存对象的大小为64KB或更大,那它就是一个巨型内存对象,使用GlobalLock函数加锁巨型内存对象将返回一个巨型指针。巨型内存对象的修改有一点特殊性,当对象大小增加并超过64K的倍数时,Windows可能要为重新分配的内存对象返回一个新的全局句柄, Windows采用段的概念来管理应用程序的内存,段有代码段和数据段两种,一个应用程序可有多个代码段和数据段。代码段和数据段的数量决定了应用程序的内存模式,图6.2说明了内存模式与应用程序代码段和数据段的关系。段的管理和全局内存对象的管理很类似,段可以是固定的,可移动的和可删除的,其属性在应用程序的模块定义文件中指定。段在全局内存中分配空间,Windows鼓励使用可移动的代码段和数据段,这样可以提高其内存利用效率。使用可删除的代码段可以进一步减小应用程序对内存的影响,如果代码段是可删除的,在必要时Windows将其删除以满足对全局内存的请求。被删除的段由Windows监控,当应用程序利用该代码段时,Windows自动地将它们重新装入。代码段代码段是不超过64K字节的机器指令,它代表全部或部分应用程序指令。代码段中的数据是只读的,对代码段执行写操作将引起通用保护(GP)错误。每个应用程序都至少有一个代码段,例如我们前面几章的例子都只有一个代码段。用户也可以生成有多个代码段的应用。实际上,多数Windows应用程序都有多个代码段。通过使用多代码段,用户可以把任何给定代码段的大小减少到完成某些任务所必须的几条指令。这样,可通过使某些段可删除,来优化应用程序对内存的使用。中模式和大模式的应用程序都使用多代码段,这些应用程序的每一个段都有一个或几个源文件。对于多个源文件,将它们分开各自编译,为编译过的代码所属的每个段命名,然后连接。段的属性在模块定义文件中定义,Windows使用SEGMENTS语句来完成此任务,如下面的代码定义了四个段的属性:用户也可以在模块定义文件中用CODE语句为所有未显式定义过的代码段定义缺省属性。例如,要将未列在SEGMENTS语句中的所有段定义为可删除的,可用下面的语句:CODE MOVEABLE DISCARDABLE。数据段每个应用程序都有一个数据段,数据段包含应用程序的堆栈、局部堆、静态数据和全局数据。一个数据段的长度也不能超过64K。数据段可以是固定的或可移动的,但不能是可删除的。如果数据段是可移动的,Windows在将控制转向应用程序前自动为其加锁,当应用程序分配全局内存,或试图在局部堆中分配超过当前可分的内存时,可移动数据段可能被移动,因此在数据段中不要保留指向变量的长指针,当数据段移动时,此长指针将失效。在模块定义文件中用DATA语句定义数据段的属性,属性的缺省值为MOVEABLE和MULTIPLE。MULTIPLE属性使Windows为应用程序的每一个实例拷贝一个应用程序数据段,这就是说每个应用程序实例中数据段的内容都是不同的。内存管理程序示例Memory应用程序Memory示例了部分内存管理,它是一个使用了可删除代码段的中模式Windows应用程序。Memory程序有四个C语言源程序,在模块定义文件中显示定义了四个代码段,相应地模块定义文件和makefile文件有地些修改,读者可通过比较Memory程序和5.1.2节的例子来体会它们之间的不同。另外,读者在编译和连接应用程序Memory后,可用Visual C++提供的Windows Heap Walker (HEAPWALK.EXE)来观察Memory运行时的各个段。 使用动态连接库是Windows的一个很重要的特点,它使得多个Windows应用程序可以共享函数代码、数据和硬件,这可以大大提高Windows内存的利用率。动态连接库是一个可执行模块,它包含的函数可以由Windows应用程序调用执行,为应用程序提供服务。它和我们以前用的C函数库相比,在功能上是很类似的,其主要区别是动态连接库在运行是连接,C函数库(静态连接库)是在生成可执行文件时由连接器(LINK)连接。静态连接库中的代码在应用程序生成以后已经连接到应用程序模块之中,但动态连接库中的代码只有在应用程序要用到该代码段时才动态调入DLL中的相应代码。为了让应用程序在执行时能够调入DLL中正确的代码,Windows提供了动态连接库的引入库。Windows在连接生成应用程序时,如果使用动态连接库函数,连接器并不拷贝DLL中的任何代码,它只是将引入库中指定所需函数在DLL中位置的信息拷贝在应用程序模块中,当应用程序运行时,这些定位信息在可执行应用程序和动态连接库之间建立动态连接。静态库、引入库和动态库之间的区别如表6.1所示。DLL不能独立执行,也不能使用消息循环。每个DLL都有一个入口点和一个出口点,具有自己的实例句柄、数据段和局部堆,但DLL没有堆栈,它使用调用程序的堆栈。DLL也包括有.C文件,.H文件,.RC文件和.DEF文件,另外,在连接时一般要加入SDK库中的LIBENTRY.OBJ文件。创建动态连接库要创建动态连接库,至少有三个文件:C语言源文件;一个模块定义文件(.DEF);makefile文件。有了这些文件后,就可以运行Microsoft的程序维护机制(NMAKE),编译并连接源代码文件,生成DLL文件。创建C语言源文件和其它C应用程序一样,动态连接库可包含多个函数,每个函数要在被其它应用程序或库使用之前用FAR声明,并且在库的模块定义文件中用EXPORTS语句引出。在上面的源代码中,有两个函数是DLL源代码所必需的,这就是DLL入口函数LibMain和出口函数WEP。LibMain函数是DLL的入口点,它由DLL 自动初始化函数LibEntry调用,主要用来完成一些初始化任务。LibMain有四个参数:hint, wDataSeg, cbHeapSize和lpszCmdLine。其中hInst是动态连接库的实例句柄;wDataSeg是数据段(DS)寄存器的值;cbHeapSize是模块定义文件定义的堆的尺寸,LibEntry函数用该值来初始化局部堆;lpszCmdLine包含命令行的信息。WEP函数是DLL的标准出口函数,它在DLL被卸出之前由Windows调用执行,以完成一些必要的清除工作。WEP函数只使用一个参数nParameter,它用来指示终止状态。源文件中的其它函数则是DLL为应用程序提供的库函数,DLL设计者可以给它加入自己所需要的功能,如DrawBox,DrawPie和DrawCircle。建立DLL模块定义文件每个DLL必须有一个模块定义文件,该文件在使用LINK连接时用于提供定义库属性的引入信息。关键字LIBRARY用来标识这个模块是一个动态连接库,其后是库名DRAWDLL,它必须和动态连接库文件名相同。DATA语句中关键字SINGLE是必须的,它表明无论应用程序访问DLL多少次,DLL均只有单个数据段。其它关键字的用法同Windows应用程序的模块定义文件一样,这在前面已有叙述,请参见5.1.2.3。编制Makefile文件NMAKE是Microsoft的程序维护机制,它控制执行文件的创建工作,以保证只有必要的操作被执行。有五种工具用来创建动态连接库:CLMicrosoft C优化编译器,它将C语言源文件编译成目标文件.OBJ。LINKMicrosoft 分段可执行连接器,它将目标文件和静态库连接生成动态连接库。LINK命令行有五个参数,用逗号分开:第一个参数列出所有动态连接库用到的目标文件(.OBJ),如果使用了标准动态连接初始化函数,则必须包括LIBENTRY.OBJ文件;第二个参数指示最终可执行文件名,一般用.DLL作为扩展名;第三个参数列出创建动态连接库所需要的引入库和静态库;第五个参数是模块定义文件。IMPLIBMicrosoft引入库管理器,它根据动态连接库的模块定义文件创建一个扩展名为.LIB的引入库。RCMicrosoft Windows资源编译器。所有动态连接库都必须用RC编译,以使它们与Windows 3.1版兼容。MAPSYMMicrosoft符号文件生成器,它是可选工具,只用于调试版本。 应用程序要访问动态连接库函数,它应该做下面三件事:建立库函数原型,调用库函数,引入库函数。建立库函数原型一般通过在C语言源文件中包含动态连接库的头文件解决,头文件中包含了每个库函数的原型语句,原型语句的目的是为编译器定义函数的参数和返回值,以使编译器能正确创建调用库函数的代码。原型语句定义好之后,应用程序就可以象调用静态连接库函数一样调用动态连接库的函数了。应用程序调用DLL中的引出函数还要在应用程序中对其进行引入,一般有三种方法:连接时隐式引入最常用也最简单的方法是连接时隐式引入,这种方法是在应用程序的连接命令行中列出为动态连接库创建的引入库,这样应用程序在使用DLL的引出函数时,就如同使用静态库中的函数一样了。连接时显式引入和隐式引入一样,显式引入也是在连接时进行的,它通过把所需函数列在应用程序的模块定义文件的IMPORTS语句中完成。对于在模块定义文件中定义了入口序号的DLL函数,采用引入函数名、动态连接库名和入口序号的形式,如:IMPORTSDrawBox=DllDraw.2如果DLL的模块定义文件没有定义引出函数的入口序号,则使用如下引入语句:IMPORTSDllDraw.DrawBox运行时动态引入 应用程序可以在运行时动态连接DLL函数,当需要调用DLL的引出函数时,应用程序首先装入库,并直接检索所需函数地址,然后才调用该函数。2023-08-30 08:30:441
谁能概括一下windows是如何管理内存的?
1.磁盘写缓存2.程序要他就给2023-08-30 08:30:572
Python如何管理内存
内存管理机制:引用计数、垃圾回收、内存池引用计数: 引用计数是一种非常高效的内存管理手段,当一个Python对象引用时其引用计数加一,当其不再被一个变量引用时则减一。当引用计数等于0时对象被删除。1.引用计数: 引用计数也是一种垃圾收集机制,而且也是一种最直观,最简单的垃圾收集技术。当 Python 的某个对象的引用计数降为 0 时,说明没有任何引用指向该对象,该对象就成为要被回收的垃圾了。比如某个新建对象,它被分配给某个引用,对象的引用计数变为 1。如果引用被删除,对象的引用计数为 0,那么该对象就可以被垃圾回收。不过如果出现循环引用的话,引用计数机制就不再起有效的作用了。2.标记清除: 如果两个对象的引用计数都为1,但是仅仅存在他们之间的循环引用,那么这两个对象都是需要被回收的。也就是说,他们的引用计数虽然表现为非0,但是实际上有效的引用计数为0.所以现将循环引用摘掉,就会得出这两个对象的有效计数。3、分代收集经过上面的【标记-清理】方法,已经可以保证对垃圾的回收了,但还有一个问题,【标记-清理】什么时候执行比较好呢,是对所有对象都同时执行吗?同时执行很显然不合理,我们知道,存活越久的对象,说明他的引用更持久(好像是个屁话,引用不持久就被删除了),为了更合理的进行【标记-删除】,就需要对对象进行分代处理,思路很简单:1、新创建的对象做为0代2、每执行一个【标记-删除】,存活的对象代数就+13、代数越高的对象(存活越持久的对象),进行【标记-删除】的时间间隔就越长。这个间隔,江湖人称阀值4.调优手段(了解)1.手动垃圾回收2.调高垃圾回收阈值3.避免循环引用(手动解循环引用和使用弱引用)2023-08-30 08:31:072
吉利缤瑞内存怎么清理
就打开你的车载中控屏幕,然后找到内存管理,然后把一切不要的缓存数据进行删除,就可以清理了。如果可以拆卸内存卡,就把内存卡拔下来插到电脑上,用文件管理删除,如果不能拆卸内存卡,在机器的功能列表里找到文件管理或者录像管理,删除或者清空即可。内存不足清理方法将记录仪里的内存卡插到手机上,用手机直接删除文件。车记录仪即记录车辆行驶途中的影像及声音等相关资讯的仪器,安装行车记录仪后,能够记录汽车行驶全过程的视频图像和声音,可为交通事故提供证据。一般只有老式的车机才会遇到内存不足的问题。一般老式的车机会将地图下载到存储卡中,然后将存储卡插入车机。车内其他功能也需要占用一定的存储卡空空间,时间长了内存会不足。如果内存不足,可以换一个大一点的存储卡,也可以拔下存储卡连接电脑清理无用的数据。这种老式的车机几乎不再被司机使用,很多人要么选择更换智能大屏幕车机,要么直接使用移动导航。更换智能大屏幕汽车的价格在700元到1000元左右。这款智能汽车和智能手机一样,搭载安卓系统,自带内存,无需外接存储卡。它可以在线下载音乐,并使用一些导航应用程序进行导航。智能汽车的导航精度和移动导航app差不多。2023-08-30 08:31:291
简述内存管理中buddy算法和slab机制的区别
1、Buddy算法linux对空闲内存空间管理采取buddy算法,Buddy算法:把内存中所有页面按照2^n划分,其中n=0~5,每个内存空间按1个页面、2个页面、4个页面、8个页面、16个页面、32个页面进行六次划分。划分后形成了大小不等的存储块,称为页面块,简称页块,包含一个页面的页块称为1页块,包含2个页面的称为2页块,依次类推。每种页块按前后顺序两两结合成一对Buddy“伙伴”。系统按照Buddy关系把具有相同大小的空闲页面块组成页块组,即1页块组、2页块组……32页块组。 每个页块组用一个双向循环链表进行管理,共有6个链表,分别为1、2、4、8、16、32页块链表。分别挂到free_area[] 数组上。位图数组用于标记内存页面使用情况,第0组每一位表示单个页面使用情况,1表示使用,0表示空闲,第二组每一位表示比邻的两个页面使用情况,一次类推。默认为10个数组,当一对Buddy的两个页面中有一个事空闲的,而另一个全部或部分被占用时,该位置1.两个页面块都是空闲,对应位置0.内存分配和释放过程内存分配时,系统按照Buddy算法,根据请求的页面数在free_area[]对应的空闲页块组中搜索。 若请求页面数不是2的整数次幂,则按照稍大于请求数的2的整数次幂的值搜索相应的页面块组。当相应页块组中没有可使用的空闲页面块时就查询更大一些的页块组,在找到可用的页块后分配所需要的页面。当某一空闲页面被分配后,若仍有剩余的空闲页面,则根据剩余页面的大小把他们加入到相应页面组中。内存页面释放时,系统将其作为空闲页面看待,检查是否存在与这些页面相邻的其他空闲页块,若存在,则合为一个连续的空闲区按Buddy算法重新分组。2、Slab算法采用buddy算法,解决了外碎片问题,这种方法适合大块内存请求,不适合小内存区请求。如:几十个或者几百个字节。Linux2.0采用传统内存分区算法,按几何分布提供内存区大小,内存区以2的幂次方为单位。虽然减少了内碎片,但没有显著提高系统效率。Linux2.4采用了slab分配器算法,该算法比传统的分配器算法有更好性能和内存利用率,最早在solaris2.4上使用。Slab分配器思想1)小对象的申请和释放通过slab分配器来管理。2)slab分配器有一组高速缓存,每个高速缓存保存同一种对象类型,如i节点缓存、PCB缓存等。3)内核从它们各自的缓存种分配和释放对象。4)每种对象的缓存区由一连串slab构成,每个slab由一个或者多个连续的物理页面组成。这些页面种包含了已分配的缓存对象,也包含了空闲对象。2023-08-30 08:31:441
我是win10的系统,在安装计算机二级的时候,显示系统资源不足,应该怎么处理?
软件问题2023-08-30 08:31:552
关于Linux-0.11内核_段页内存管理的问题
目前还没有想法!2023-08-30 08:32:033
内存管理问题~为满足64位地址空间的作业运行,采用多级分页存储管理方式
三级2023-08-30 08:32:122
objective-c 使用什么机制管理对象内存
Objective-C内存管理机制1.Objective-C中所有对象都在堆区建立,由程序员负责释放对象所占用的内存。内存管理机制由3种:垃圾回收、引用计数、C语言方式。2.垃圾回收是Mac OS10.5提供的新方案,在系统存在一个垃圾收集器。如果发现某个对象没有被任何对象使用,该对象被自动释放。3.C语言方式,原始内存管理方式。用户手动调用malloc、calloc函数分配内存,free回收内存。4.引用计数机制:对象创建后,运行时系统通过对象维护的一个计数器来描述有多少个其他对象在使用自己,当计数器为0时,释放该对象占用的内存空间(该对象调用dealloc方法)。5,内存管理规则:当使用alloc,new或copy创建一个对象时,对象的引用计数被设置为1.;向对象发送retain消息,对象引用计数加1;向对象发送release消息时,对象引用计数减1;当对象引用计数为0时,运行时系统向对象发送dealloc消息并回收对象所占用的内存。6.注意:如果类的实例变量时对象指针,则必须重载dealloc方法(例如圆circle类:有一个变量point是Point*类型);dealloc方法不能直接调用,只有对象的引用计数为0的时候,系统会自动向对象发送dealloc消息。关于属性的assign、retain、copy关键字生成set方法assign:简单赋值 浅拷贝 常用于内置类型-(void)setX(int):aX{ x = aX;}retain: 常用于指针类型,节省内存例如:圆Circle类中有一个圆心center是Point(用户自定义点类型)和int型半径r-(void)setPoint(Point*):aPoint{ if(center != aPoint){ [centerrelease]; //原圆心对象引用计数-1 [aPoint retain]; //参数对象引用计数+1 center = aPoint; //这里是指针赋值}} 或者-(void)setPoint(Point*):aPoint{[aPoint retain]; //参数对象引用计数+1[center release]; //原圆心对象引用计数-1 center = aPoint; //这里是指针赋值}对应init方法中-(id)init{ Point* aPoint = [[Point alloc]init]; self.center = aPoint; [self.center release]; return self;}或者-(id)initWithPoint:(Point*)aPoint{ self.point = aPoint;}copy: 好处就是重新给center分配内存,避免了retain中center与参数aPoint两个指针同时指向同一个内存对象,但浪费内存。例如还是上面例子-(void)setPoint(Point*):aPoint{ if(center != aPoint){ [center release]; center = [[Pointalloc]initWithX:aPoint.x andY:aPoint.y]; }}2023-08-30 08:32:191
存储管理:如何维护手机内存
手机需要优化内存,建议您操作:1.通过智能管理器/内存管理器删除缓存、残留和广告文件等不必要的数据;结束后台应用程序;关闭不需要自启动的程序。(若机器中没有内存管理器,建议将机器更新至最新版本后查看尝试)2.若手机支持存储卡,将多媒体文件移动到扩展卡或将拍摄存储路径设置为扩展卡。3.卸载不经常使用的软件或文件。2023-08-30 08:32:261
怎么卸载内存管理器
软件拒绝卸载一般是有“设备管理器”权限或者是病毒程序,请按照以下步骤进行解决:备份重要的资料和信息(例如:通讯录,短信,照片等)以防在杀毒过程中丢失或损坏。安装杀毒软件(例如:手机管家)进行一键查杀,以手机管家为例,打开手机管家,点击“安全防护”,点击“立即扫描”即可一键杀毒。对于绝大多数病毒,请获取ROOT权限后可以彻底清除,防止死灰复燃,若依然无法处理,请到手机官方售后进行系统修复。到系统设置,安全,设备管理中关闭相关权限即可正常卸载。2023-08-30 08:32:342
system是什么意思,system是什么进程可以关闭吗?
一、System进程是Windows页面内存管理进bai程,拥有du0级优先权,没有它系统无法启动。注意:system.exe是netcontroller木马zhi病毒dao生成的文件,出现在c:windows目录下,建议将其删除。但要与系统的system进程区分开来。system进程是没有。exe的。二、不能关闭这个进程在“任务管理器”中就结束不掉,结束掉的进程说明这个进程不能对系统造成直接危害,不过,用其它软件可能能强制结束,但这样会造成蓝屏等现象。扩展资料如果关掉会有可能出现两种情况!1、蓝屏。2、出现那个说你是非法程序的对话框。总的来说就是系统有可能崩溃!system是一个系统正常进程,通常无毒,属于system权限2023-08-30 08:33:268
什么是内存管理
管理手机里储存空间,,2023-08-30 08:36:132
手机内存突然用掉这么多,也查不出那些内存都哪去了,没有内存卡,是手机储存的空间
比较麻烦2023-08-30 08:36:212
吉利缤瑞内存怎么清理
就打开你的车载中控屏幕,然后找到内存管理,然后把一切不要的缓存数据进行删除,就可以清理了。如果可以拆卸内存卡,就把内存卡拔下来插到电脑上,用文件管理删除,如果不能拆卸内存卡,在机器的功能列表里找到文件管理或者录像管理,删除或者清空即可。内存不足清理方法将记录仪里的内存卡插到手机上,用手机直接删除文件。车记录仪即记录车辆行驶途中的影像及声音等相关资讯的仪器,安装行车记录仪后,能够记录汽车行驶全过程的视频图像和声音,可为交通事故提供证据。一般只有老式的车机才会遇到内存不足的问题。一般老式的车机会将地图下载到存储卡中,然后将存储卡插入车机。车内其他功能也需要占用一定的存储卡空空间,时间长了内存会不足。如果内存不足,可以换一个大一点的存储卡,也可以拔下存储卡连接电脑清理无用的数据。这种老式的车机几乎不再被司机使用,很多人要么选择更换智能大屏幕车机,要么直接使用移动导航。更换智能大屏幕汽车的价格在700元到1000元左右。这款智能汽车和智能手机一样,搭载安卓系统,自带内存,无需外接存储卡。它可以在线下载音乐,并使用一些导航应用程序进行导航。智能汽车的导航精度和移动导航app差不多。2023-08-30 08:36:481
java 的JVM虚拟内存是如何管理的啊。
JVM内存管理:深入垃圾收集器与内存分配策略Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来。概述:说起垃圾收集(Garbage Collection,下文简称GC),大部分人都把这项技术当做Java语言的伴生产物。事实上GC的历史远远比Java来得久远,在1960年诞生于MIT的Lisp是第一门真正使用内存动态分配和垃圾收集技术的语言。当Lisp还在胚胎时期,人们就在思考GC需要完成的3件事情:哪些内存需要回收?什么时候回收?怎么样回收?把时间从1960年拨回现在,回到我们熟悉的Java语言。本文第一章中介绍了Java内存运行时区域的各个部分,其中程序计数器、VM栈、本地方法栈三个区域随线程而生,随线程而灭;栈中的帧随着方法进入、退出而有条不紊的进行着出栈入栈操作;每一个帧中分配多少内存基本上是在Class文件生成时就已知的(可能会由JIT动态晚期编译进行一些优化,但大体上可以认为是编译期可知的),因此这几个区域的内存分配和回收具备很高的确定性,因此在这几个区域不需要过多考虑回收的问题。而Java堆和方法区(包括运行时常量池)则不一样,我们必须等到程序实际运行期间才能知道会创建哪些对象,这部分内存的分配和回收都是动态的,我们本文后续讨论中的“内存”分配与回收仅仅指这一部分内存。引用计数算法(Reference Counting)最初的想法,也是很多教科书判断对象是否存活的算法是这样的:给对象中添加一个引用计数器,当有一个地方引用它,计数器加1,当引用失效,计数器减1,任何时刻计数器为0的对象就是不可能再被使用的。客观的说,引用计数算法实现简单,判定效率很高,在大部分情况下它都是一个不错的算法,但引用计数算法无法解决对象循环引用的问题。举个简单的例子:对象A和B分别有字段b、a,令A.b=B和B.a=A,除此之外这2个对象再无任何引用,那实际上这2个对象已经不可能再被访问,但是引用计数算法却无法回收他们。根搜索算法(GC Roots Tracing)在实际生产的语言中(Java、C#、甚至包括前面提到的Lisp),都是使用根搜索算法判定对象是否存活。算法基本思路就是通过一系列的称为“GC Roots”的点作为起始进行向下搜索,当一个对象到GC Roots没有任何引用链(Reference Chain)相连,则证明此对象是不可用的。在Java语言中,GC Roots包括:1.在VM栈(帧中的本地变量)中的引用2.方法区中的静态引用3.JNI(即一般说的Native方法)中的引用生存还是死亡?2023-08-30 08:37:471
linux内核由哪些部分组成?
这个问题不难的,Linux内核由进程管理、内存管理、文件系统、网络协议、进程间通信、设备驱动等模块组成,如下图所示。你可以关注致远电子微|信的,都开始连载linux指导书籍了,我也是从中一点点学习!2023-08-30 08:37:582
程序员如何识别系统采用的是分页式存储管理还是段式存储管理
好高深的问题啊,我也没有弄明白过。只在大学的时候学习操作系统的时候,学习过,什么段式,页式,段页式。2023-08-30 08:38:132
电视没有储存空间,该怎么办?
清理储存空间 把不用的软件视频删掉 如果不会的话可以拿到专门的地方让他们帮忙解决2023-08-30 08:38:244
三星手机怎么看后台运行的软件?
双击中间那个按键2023-08-30 08:38:5311
“memory_management” 蓝屏问题怎么解决?
当开机蓝屏出现如下蓝屏代码:0x0000001A:MEMORY_MANAGEMENT 电脑蓝屏原因: ◆错误分析:这个内存管理错误往往是由硬件引起的, 比如: 新安装的硬件、内存本身有问题等. 电脑蓝屏解决方法: ◇解决方案:如果是在安装Windows时出现, 有可能是由于你的电脑达不到安装Windows的最小内存和磁盘要求2023-08-30 08:39:563
计算机操作系统通常具有的5大功能是
q2023-08-30 08:40:467
电脑任务管理器的内存指的是什么内存?还有磁盘
内存指的是运行时占用的内存空间,现在的电脑一般都是4G以上的内存,旧的电脑可能有1G,2G的。这里的磁盘指的是把数据保存到硬盘,或者从硬盘读取数据。2023-08-30 08:41:473
操作系统五大 采用那些技术来实现?
1、微处理器管理功能 在大型操作系统中.可存在多个微处理器,并同时可管理多个作业。怎样选出其中一个作业进入主存储器难备运行,怎样为这个作业分配微处理器等等,都由微处理器管理模块负责。微处理器管理模块,要对系统中各个微处理器的状态进行登记,还要登记各个作业对微处理器的要求。管理模块还要用一个优化算法实现最佳调度规则。把所有的微处理器分配给各个用户作业使用。最终日的是提高微处理器的利用率。这就是操作系统的微处理器管理功能。2、内存管理功能 内存储器的管理,主要由内存管理模块来完成。内存管理模块对内存的管理分三步。首先为各个用户作业分配内存空间;其次是保护已占内存空间的作业不被破坏;最后,是结合硬件实现信息的物理地址至逻辑地址的变换。使用户在操作中不必担心信息究竟在四个具体空间――即实际物理地址,就可以操作,这样就方便了用户对计算机的使用和操作。内存管理模块对内存的管理是使用一种优化算法对内存管理进行优化处理,以提高内存的利用率。这就是操作系统的内存管理功能。3、外部设备管理功能 由于计算机的不断发展,其应用领域越来越广泛,应用技术越来越提高,应用方法越来越简便,与用户的界面越来越友好,随之外部设备的种类也日益增多,功能不断提高,档次日渐升级,因此,操作系统的设备管理模块的功能也必须跟上外部设备的发展而不断发展、不断升级以适应外部设备的日益发展的需要。设备管理模块的任务是当用户要求某种设备时,应马亡分配给用户所要求的设备,并技用户要求驱动外部设备以供用户应用。并且对外部设备的中断请求,设备管理模块要给以响应并处理。这就是操作系统的外部设备管理功能。4、文件管理功能 操作系统对文件的管理主要是通过文件管理模块来实现的。文件管理模块管理的范围包括文件目录、文件组织、文件操作和文件保护。5、进程管理功能 进程管理也称作业管理,用户交给计算机处理的工作称为作业。作业管理是由进程管理模块来控制的,进程管理模块对作业执行的全过程进行管理和控制。2023-08-30 08:43:521
安卓内存问题
估计 软件直接会有冲突的2023-08-30 08:44:003
手机内存卡空间不足怎么清理
手机内存卡不足可以下载360清理,还可以手机管家也可以,又卸载一些不需要的软件。2023-08-30 08:44:203