首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

100分,内存 ,操作系统 C解决方案

2012-03-21 
100分,内存 ,操作系统C小弟有以下问题不明白,希望大哥们指教!每个20分,哈哈,哪位那点回答好我就结贴给分,

100分,内存 ,操作系统 C
小弟有以下问题不明白,希望大哥们指教!每个20分,哈哈,哪位那点回答好我就结贴给分,如果一个人全回答了,我也全给,我是渴望学习
假设我电脑的内存条大小是256M
请大家分点回答,谢谢了 

1.为什么说进程地址空间是0-4G,但是我内存只有256M啊,是不是多于256M的就不能访问了?

2.<1>假设有两个进程 A,B,有没有这种可能 ,A有一个int变量占据了我内存条第100-103 位置,B也有个变量占据了我内存条第100-103 位置,这两个变量的生命周期都是他们各自程序的周期,有没有可能我对A哪个变量赋值,B哪个int变量也就同时改变值了? <2>或者,内存条的同一个位置,同时只能被一个进程享用?<1>,<2> 求解释?



3.运行的进程A,B,C有没可能都有一个变量的地址都是0xf5673000d? 假设有这个情况,他们代表同一物理地址吗?


4。我是这样理解的,256M,空间,某个位置被进程A占了,进程B就不能占 ,进程A,进程B,进程C内存条的使用时分段的 ,比如A用 0x222-0x333,b 用0x3334-0x4444,c用0x4445-0x55555..这样理解对吗?



5。我们平时malloc,new ,分配内存都是在我的内存条上吗?还有堆栈上的变量都是用内存条的内存吗 ?
小弟有以下问题不明白,希望大哥们指教!每个25分,哈哈,哪位那点回答好我就结贴给分,如果一个人全回答了,我也全给,我是渴望学习
假设我电脑的内存条大小是256M
请大家分点回答,谢谢了 

1.为什么说进程地址空间是0-4G,但是我内存只有256M啊,是不是多于256M的就不能访问了?

2.<1>假设有两个进程 A,B,有没有这种可能 ,A有一个int变量占据了我内存条第100-103 位置,B也有个变量占据了我内存条第100-103 位置,这两个变量的生命周期都是他们各自程序的周期,有没有可能我对A哪个变量赋值,B哪个int变量也就同时改变值了? <2>或者,内存条的同一个位置,同时只能被一个进程享用?<1>,<2> 求解释?



3.运行的进程A,B,C有没可能都有一个变量的地址都是0xf5673000d? 假设有这个情况,他们代表同一物理地址吗?


4。我是这样理解的,256M,空间,某个位置被进程A占了,进程B就不能占 ,进程A,进程B,进程C内存条的使用时分段的 ,比如A用 0x222-0x333,b 用0x3334-0x4444,c用0x4445-0x55555..这样理解对吗?



5。我们平时malloc,new ,分配内存都是在我的内存条上吗?还有堆栈上的变量都是用内存条的内存吗 ?


[解决办法]
1. 进程地址空间是“虚拟”的,虚拟地址要引用物理地址才能真能读写内存。类似于你脑子能记4G个人的名字,但是你总共只认识256M个人。你可以把这256M个人分配给你脑子里4G个位置中的256M个,然后根据脑子里的记忆间接去找人。另外Winodows有虚拟内存机制,主内存不够用还能用硬盘。
2. 如果你考虑内存这种底层概念尽量不要把“变量”这种高级语言概念混进来。两个进程可以访问同一个物理内存,前提是两个进程的虚拟地址都引用了那个物理地址。因为是同一个物理地址,所以数据也只有一份,一个进程修改另一个进程也能看到变化。
3. 不是,那个是虚拟地址。但同时同一个物理地址可能在不同进程里对应不同虚拟地址。
4. 物理内存可以被多个进程共享。
5. 不是,Windows环境下只有你真正读写的时候才会给你分配物理内存。刚malloc或者new的时候只是占用虚拟空间。
[解决办法]
抛砖引玉了:
1. 在32bit的机器上,最大的寻址空间就是2^32 = 4G。如果操作系统没有虚拟内存机制(即将硬盘当内存使用), 那么超过256M就没有内存可用了。

2. 楼主假设的情况不可能存在,不同的进程之间的地址空间是独立的。

3. 这个问题和第2个问题差不多,参见上面的回答。同时,进程间通讯手段之一的共享内存,应该不属于这个问题讨论的范畴。

4. 是的。

5. 大部分情况下是这样的。但也有可能被分配到当做内存使用的硬盘上,这是操作系统的工作。
[解决办法]
首先普及下进程地址空间和虚拟内存相关知识: from http://blog.csdn.net/do2jiang/archive/2009/10/17/4690967.aspx
总谈:
32 位的CPU 的寻址空间是4G , 所以虚拟内存的最大值为4G , 而windows 操作系统把这4G 分成2 部分, 即2G 的用户空间和2G 的系统空间, 系统空间是各个进程所共享的, 他存放的是操作系统及一些内核对象等, 而用户空间是分配给各个进程使用的, 用户空间包括用: 程序代码和数据, 堆, 共享库, 栈


早期的内存分配机制
在早期的计算机中,要运行一个程序,会把这些程序全都装入内存,程序都是直接运行在内存上的,也就是说程序中访问的内存地址都是实际的物理内存地址。当计算机同时运行多个程序时,必须保证这些程序用到的内存总量要小于计算机实际物理内存的大小。那当程序同时运行多个程序时,操作系统是如何为这些程序分配内存的呢?下面通过实例来说明当时的内存分配方法:
某台计算机总的内存大小是 128M ,现在同时运行两个程序 A 和 B , A 需占用内存 10M , B 需占用内存 110 。计算机在给程序分配内存时会采取这样的方法:先将内存中的前 10M 分配给程序 A ,接着再从内存中剩余的 118M 中划分出 110M 分配给程序 B 。这种分配方法可以保证程序 A 和程序 B 都能运行,但是这种简单的内存分配策略问题很多。
问题1.进程地址空间不隔离 由于程序都是直接访问物理内存,所以恶意程序可以随意修改别的进程的内存数据,以达到破坏的目的
问题2.内存使用效率低 和 B 都运行的情况下,如果用户又运行了程序 C ,而程序 C 需要 20M 大小的内存才能运行,而此时系统只剩下 8M 的空间可供使用,所以此时系统必须在已运行的程序中选择一个将该程序的数据暂时拷贝到硬盘上,释放出部分空间来供程序 C 使用,然后再将程序 C 的数据全部装入内存中运行。可以想象得到,在这个过程中,有大量的数据在装入装出,导致效率十分低下。
问题3.程序运行的地址不确定。当内存中的剩余空间可以满足程序 C 的要求后,操作系统会在剩余空间中随机分配一段连续的 20M 大小的空间给程序 C 使用,因为是随机分配的,所以程序运行的地址是不确定的。
为了解决上述问题 后来的内存管理出现了2中方法:分段,分页
分段:为了解决上述问题,人们想到了一种变通的方法,就是增加一个中间层,利用一种间接的地址访问方法访问物理内存。按照这种方法,程序中访问的内存地址不再是实际的物理内存地址,而是一个虚拟地址,然后由操作系统将这个虚拟地址映射到适当的物理内存地址上。这样,只要操作系统处理好虚拟地址到物理内存地址的映射,就可以保证不同的程序最终访问的内存地址位于不同的区域,彼此没有重叠,就可以达到内存地址空间隔离的效果。

当创建一个进程时,操作系统会为该进程分配一个 4GB 大小的虚拟 进程地址空间。之所以是 4GB ,是因为在 32 位的操作系统中,一个指针长度是 4 字节,而 4 字节指针的寻址能力是从 0x00000000~0xFFFFFFFF ,最大值 0xFFFFFFFF 表示的即为 4GB 大小的容量。与虚拟地址空间相对的,还有一个物理地址空间,这个地址空间对应的是真实的物理内存。如果你的计算机上安装了 512M 大小的内存,那么这个物理地址空间表示的范围是 0x00000000~0x1FFFFFFF 。当操作系统做虚拟地址到物理地址映射时,只能映射到这一范围,操作系统也只会映射到这一范围。当进程创建时,每个进程都会有一个自己的 4GB 虚拟地址空间。要注意的是这个 4GB 的地址空间是“虚拟”的,并不是真实存在的,而且每个进程只能访问自己虚拟地址空间中的数据,无法访问别的进程中的数据,通过这种方法实现了进程间的地址隔离。那是不是这 4GB 的虚拟地址空间应用程序可以随意使用呢?很遗憾,在 Windows 系统下,这个虚拟地址空间被分成了 4 部分: NULL 指针区、用户区、 64KB 禁入区、内核区。应用程序能使用的只是用户区而已,大约 2GB 左右 ( 最大可以调整到 3GB) 。内核区为 2GB ,内核区保存的是系统线程调度、内存管理、设备驱动等数据,这部分数据供所有的进程共享,但应用程序是不能直接访问的。



人们之所以要创建一个虚拟地址空间,目的是为了解决进程地址空间隔离的问题。但程序要想执行,必须运行在真实的内存上,所以,必须在虚拟地址与物理地址间建立一种映射关系。这样,通过映射机制,当程序访问虚拟地址空间上的某个地址值时,就相当于访问了物理地址空间中的另一个值。人们想到了一种分段 (Sagmentation) 的方法,它的思想是在虚拟地址空间和物理地址空间之间做一一映射。比如说虚拟地址空间中某个 10M 大小的空间映射到物理地址空间中某个 10M 大小的空间。这种思想理解起来并不难,操作系统保证不同进程的地址空间被映射到物理地址空间中不同的区域上,这样每个进程最终访问到的

物理地址空间都是彼此分开的。通过这种方式,就实现了进程间的地址隔离。还是以实例说明,假设有两个进程 A 和 B ,进程 A 所需内存大小为 10M ,其虚拟地址空间分布在 0x00000000 到 0x00A00000 ,进程 B 所需内存为 100M ,其虚拟地址空间分布为 0x00000000 到 0x06400000 。那么按照分段的映射方法,进程 A 在物理内存上映射区域为 0x00100000 到 0x00B00000 ,,进程 B 在物理内存上映射区域为 0x00C00000 到 0x07000000 。于是进程 A 和进程 B 分别被映射到了不同的内存区间,彼此互不重叠,实现了地址隔离。从应用程序的角度看来,进程 A 的地址空间就是分布在 0x00000000 到 0x00A00000 ,在做开发时,开发人员只需访问这段区间上的地址即可。应用程序并不关心进程 A 究竟被映射到物理内存的那块区域上了,所以程序的运行地址也就是相当于说是确定的了。 
分页: 分页方法的核心思想就是当可执行文件执行到第 x 页时,就为第 x 页分配一个内存页 y ,然后再将这个内存页添加到进程虚拟地址空间的映射表中 , 这个映射表就相当于一个 y=f(x) 函数。应用程序通过这个映射表就可以访问到 x 页关联的 y 页了。

理解了以上 考虑lz问题
1.32 位的CPU 的寻址空间是4G , 所以虚拟内存的最大值为4G , 而windows 操作系统把这4G 分成2 部分, 即2G 的用户空间 2g虚拟地址映射实际的物理内存(256) 但是程序员感觉不到因为他们永远只与2g虚拟地址映射打交道!
2.由于每个程序都会有自己的虚拟地址映射,相互隔离!而操作系统会把他们映射到不同的地址上的!但是对于程序而言都是唯一的地址!
 3.运行的进程A,B,C当然可能有一个变量的地址都是0xf5673000d,但是操作系统会将它们映射到不同的物理地址上的。
 4.你的理解当然不对!你的理解就是上面讲的早期的内存分配机制!呵呵。。
 5.2G 的用户空间,2g虚拟存分配给各个进程使用的, 用户空间包括用: 程序代码和数据, 堆, 共享库, 栈
也就是new 等操作了。。
希望你好好看完!
加油!青年。。




热点排行