免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: augustusqing
打印 上一主题 下一主题

linux虚拟地址空间疑惑 [复制链接]

论坛徽章:
4
戌狗
日期:2013-08-15 18:22:43技术图书徽章
日期:2013-08-21 13:48:45巨蟹座
日期:2013-09-26 17:06:39处女座
日期:2013-12-25 11:26:10
11 [报告]
发表于 2007-09-15 22:36 |只看该作者
另外,/lib/ld-2.5.1.so是interpreter,/lib/libc-2.5.1.so才是共享库

论坛徽章:
4
戌狗
日期:2013-08-15 18:22:43技术图书徽章
日期:2013-08-21 13:48:45巨蟹座
日期:2013-09-26 17:06:39处女座
日期:2013-12-25 11:26:10
12 [报告]
发表于 2007-09-15 22:51 |只看该作者
原帖由 flw2 于 2007-9-15 19:44 发表
sys_mmap2时,如果指定MAP_FIXED,可以覆盖掉brk段
不是失败吗?

2.它从进程的地址空间数据结构里找,发现如果这么做有覆盖了就失败了,一直以为mmap也是这么做的



不知道POSIX怎么规定的,但是看kernel里,sys_mmap2在指定MAP_FIXED时,覆盖掉一切.

论坛徽章:
0
13 [报告]
发表于 2007-09-16 01:20 |只看该作者
原帖由 zx_wing 于 2007-9-15 21:29 发表
我在多台机器上做了实验,无论一次分配多大的内存,堆都是向上增长的,重现不了lz的结果。
其次,共享库确实是放在栈的下面,堆的上面,CSAPP也是这样讲的,不知lz的疑惑在哪儿。
最后,对于malloc的机制,CSAPP的动态储存器分配一节有讲,lz把第10章读完就可以看到,另外,一本经典的C语言教程《C program language》的附录中给出了malloc一种实现的例子,lz也可以看看。

另外,lz应该把虚拟地址空间和虚拟内存两个概念区分开,它们完全不相同。虚拟地址空间是描述进程资源的一个集合,例如你cat map文件看到的就是对进程虚拟地址空间map关系的描述。虚拟内存如楼上几位所讲,就是个swap机制。你可以在安装系统的时候不指定swap分区来关掉虚拟内存,但你不能使你的进程没有虚拟地址空间,除非你的程序始终运行在实模式下。


多谢回复!
我的疑惑是CSAPP书上说共享库会放在0x40000000处,但我平台上不是,请问一下你实验过的机器是什么平台,我怀疑就跟gcc,Binutils,glibc版本有关吧,我的是glibc2.5.1,binutils2.17,gcc4.1.2
另一个疑惑是在我的平台上一次分配16M的时候,malloc返回的值是在共享库下,但是是上面挨着共享库,而不是下面挨着bss段,并且是往下长,而当是一次malloc分配4K时,分配返回的值却确实如书上说下面挨着bss段,往上长,共享库还仍然不是放在0x40000000

动态存储机器分配这一节,我看了(可能看了,思考的时间还不够,主要是前面的疑惑没解开),好像我平台的C库中的实现感觉很大的不同了,是感觉,说不出来,多谢你推荐的另一本经典

我从没意识到我没把虚拟地址空间和虚拟内存明确的分开,多谢提醒,但我现在仍然没分清楚,我现在的理解是,虚拟地址空间在内核里就是一个一个的vm_area组成的区域空间,而虚拟内存就是mm_struct 中的pgd所指向的页表所指向的内存,页表里的表目可以指向物理页,也可以指向交换文件,但我认为这个vm_struct区域链表跟这个页表是一一对应的,vm_struct中的start,end成员指向的这段区域就是pgd页表中的相应地址范围的页面,给进程分配一个区域,先分配一个vm_struct,确定vm_struct区域大小,再相应的修改pgd页表,使指向某个交换文件,当CPU真正引用某个vm_struct中的数据或代码时,在pgd中就会缺页异常,从而真正从磁盘载入,再修改页表指向真正物理页面,这样理解,可以认为虚拟地址空间和虚拟内存差不多表示的是同一个空间,我的理解对吗?

还有,关于关掉swap分区,应该不代表关掉了虚拟内存吧,在我的嵌入式环境里,根本没有启动交换分区,但同样是启动了MMU,有pgd,有虚拟内存的,虚拟内存只是CPU发出的地址要先经过一个MMU功能设备的转换,转换成物理地址才能发到总线上,没有交换分区,只是pgd页表中的页表项要么指向某个物理页,要么为空的,无效,i386的实模式是指CPU发出的地址不经过MMU类设备的转换,直接传到总线上,此时进程的运行空间就是物理地址空间,只有关掉MMU类设备才叫关掉了虚拟内存,我的理解对吗?

论坛徽章:
0
14 [报告]
发表于 2007-09-16 02:13 |只看该作者
原帖由 塑料袋 于 2007-9-15 22:34 发表 [00000000
00000000
b5dd8000
00000000
00125000
00127000
................

这列表示的是什么?文件偏移么?

这列表示的就是相应的vm_area_struct中的offset成员,你最懂offset的含义了,^_^
下面各列在vm_area_struct中对应的成员
start-end perm offset major:minor inode image
而且:
ptr: 0x804a000
ptr: 0xb6dd9008
ptr: 0xb5dd8008
ptr: 0x804a000
这里边第一行和第四行一样,根本没有从堆里分配过空间.

是啊,这是我平台的malloc一次分配16M时的现象,迷惑啊

也许是/lib/ld-2.5.1.so在加载/lib/libc-2.5.1.so时, /lib/libc-2.5.1.so初始化的时候匿名影射了[b5dd8000, b7ddb000 ].不清楚.但反正是没有用过堆.

这里的[b5dd8000, b7ddb000 ]是我这个进程malloc分配的堆的区域,并且这个堆是从上往下长的,并且跟brk没关系,迷惑啊

为什么你最后一个区间是[bfc03000, bfc19000] ? 这个好象也不是栈,而是interpreter的bss段.

b7f2c000-b7f2d000 rw-p 0001a000 fe:00 81960      /lib/ld-2.5.1.so
这个才是interpreter的bss段吧,我的这个区间应该是栈,但确实有疑问,栈不是可执行的吗,却没带可执行位,难不成也是新版C库解决了栈溢出执行的问题,不知道其他平台是什么情况,哪个版本开始的,还是迷惑啊

论坛徽章:
0
15 [报告]
发表于 2007-09-16 15:14 |只看该作者
原帖由 augustusqing 于 2007-9-16 01:20 发表


多谢回复!
我的疑惑是CSAPP书上说共享库会放在0x40000000处,但我平台上不是,请问一下你实验过的机器是什么平台,我怀疑就跟gcc,Binutils,glibc版本有关吧,我的是glibc2.5.1,binutils2.17,gcc4.1.2
...

虚拟地址空间和虚拟内存有一定联系,但它们确实是两个不同的东西。先不说vm_area、vm_struct这些数据结构,它们只是linux管理虚拟地址空间的手段。
虚拟地址空间是描述进程资源的一个集合,它的大小取决于CPU实现的虚拟地址的位数,通常32bit的x86平台虚拟地址位数就是32,但有些64bit的平台,虚拟地址可能不是64位(如早期的安腾平台就是51位)。虚拟地址空间的大小就是虚拟地址位数的2幂次方。如32bit的x86就是4G。
虚拟地址空间通常是和保护模式联系在一起的,在保护模式下,进程通过虚拟地址访问内存,这些虚拟地址的总和就是虚拟地址空间。虚拟地址被MMU翻译成物理地址后,就可以访问到真正的物理内存(这些lz肯定都是知道的啦)。在没有虚拟内存的情况下,虚拟地址对应的物理页,全部在机器的RAM中,不会被交换到硬盘上,进程的页表的最后一级pte会有一个位来标识当前页是在RAM中还是在硬盘上(如果我没记错的的话这位是p)。所以即使没有虚拟内存,虚拟地址空间同样存在,只要你的内存足够大,它一样工作的很好。
虚拟内存当然就是swap机制啦。它就是扩展机器内存的一种方法,通过把RAM中一些暂时不使用的页交换到硬盘上,给人一种RAM扩大了的感觉。
所以说,虚拟地址空间是对进程资源的描述,表示进程能访问多少虚拟地址,而这些虚拟地址对应的物理页则可能在真实的RAM中,也可能在虚拟内存中。

至于关掉了swap,确实是关掉了虚拟内存。前面已经说了它们的不同。虚拟地址通过MMU翻译成物理地址,应该称为保护模式,而不是虚拟内存。所以你说在你的嵌入式上,启用的MMU,只是使用了保护模式,而不是使用了虚拟内存。

总结一下:
虚拟地址空间 ——— 描述进程可访问的资源总和(虚拟地址总和)
虚拟内存 ——— 一种通过把物理页交换到硬盘上从而扩大可用RAM量的机制
保护模式(限与内存部分) ———— 通过MMU把虚拟地址翻译成物理地址,从而使进程都以为自己独占机器资源。

论坛徽章:
0
16 [报告]
发表于 2007-09-16 15:24 |只看该作者
原帖由 augustusqing 于 2007-9-16 01:20 发表


多谢回复!
我的疑惑是CSAPP书上说共享库会放在0x40000000处,但我平台上不是,请问一下你实验过的机器是什么平台,我怀疑就跟gcc,Binutils,glibc版本有关吧,我的是glibc2.5.1,binutils2.17,gcc4.1.2
...

不好意思,昨天用错机器了,今天找了个纯32bit的x86机器,确实遇到了你说的问题。
我用google找了半天,也没找到答案( 可能是英语太菜,关键字输的不好)。看了看glibc的代码,得知当分配大于128K的内存时,依赖于操作系统的内存映射机制。我又找了找linux下heap mapping的文章,可惜也没找到答案,希望知道了朋友讲解一下。
此外,对于共享库的起始地址,这也是取决于os的mapping机制,不同的平台肯定是不一样的。例如64bit的平台和32bit平台肯定不一样,x86和非x86平台也不一样。这些和平台相关的部分不影响你对程序的理解。我认为知道理解了一个进程的虚拟地址空间要被分成几个不同的部分,每个部分map不同的内容即可。具体是什么内容,起始地址在哪儿,需要的时候查资料总能查到的。

PS:我在x86_64上分配大内存、小内存,堆都是向上增长的,我估计这和x86虚拟地址空间太小,只有4G有关。

论坛徽章:
0
17 [报告]
发表于 2007-09-16 21:13 |只看该作者
至于关掉了swap,确实是关掉了虚拟内存。前面已经说了它们的不同。虚拟地址通过MMU翻译成物理地址,应该称为保护模式,而不是虚拟内存。所以你说在你的嵌入式上,启用的MMU,只是使用了保护模式,而不是使用了虚拟内存。


这次感觉我可以扭转对虚拟内存和虚拟地址空间的长期误解了,多谢zx_wing兄的指正。

现在我这样理解:

在保护模式下,进程虚拟空间的对象,通过虚拟地址访问,启用了swap机制时,就启动了虚拟内存,虚拟地址指向的是虚拟内存页,这个虚拟内存页可能指向物理内存页,也可能指向交换文件,而没有启用swap机制,就没有启用虚拟内存,此时的虚拟地址就转换成物理地址,指向物理页,或者不存在于RAM,而指向的是硬盘上的某个文件。

它们的关系就象物理地址空间,物理地址,物理内存的关系类似,物理地址空间由物理地址位数决定,物理地址指向的物理内存页可能是RAM内存,也可能是某个设备上的设备内存

我这回的理解对了吗?多谢多谢!

不好意思,昨天用错机器了,今天找了个纯32bit的x86机器,确实遇到了你说的问题。
我用google找了半天,也没找到答案( 可能是英语太菜,关键字输的不好)。看了看glibc的代码,得知当分配大于128K的内存时,依赖于操作系统的内存映射机制。我又找了找linux下heap mapping的文章,可惜也没找到答案,希望知道了朋友讲解一下。
此外,对于共享库的起始地址,这也是取决于os的mapping机制,不同的平台肯定是不一样的。例如64bit的平台和32bit平台肯定不一样,x86和非x86平台也不一样。这些和平台相关的部分不影响你对程序的理解。我认为知道理解了一个进程的虚拟地址空间要被分成几个不同的部分,每个部分map不同的内容即可。具体是什么内容,起始地址在哪儿,需要的时候查资料总能查到的。

PS:我在x86_64上分配大内存、小内存,堆都是向上增长的,我估计这和x86虚拟地址空间太小,只有4G有关。


就是,我疑惑的应该是跟C库中堆的管理策略有关,对于x86的4G虚拟地址空间,分配不同大小虚拟内存时采取不同的策略,我也没查到系统介绍这些知识的好的资料文章
多谢你的跟踪!

论坛徽章:
0
18 [报告]
发表于 2007-09-17 09:35 |只看该作者
原帖由 augustusqing 于 2007-9-16 21:13 发表


这次感觉我可以扭转对虚拟内存和虚拟地址空间的长期误解了,多谢zx_wing兄的指正。

现在我这样理解:

在保护模式下,进程虚拟空间的对象,通过虚拟地址访问,启用了swap机制时,就启动了虚拟内存,虚 ...

>>在保护模式下,进程虚拟空间的对象,通过虚拟地址访问,启用了swap机制时,就启动了虚拟内存,虚拟地址指向的是虚拟内存页,这个虚拟内存页可能指向物理内存页,也可能指向交换文件,而没有启用swap机制,就没有启用虚拟内存,此时的虚拟地址就转换成物理地址,指向物理页,或者不存在于RAM,而指向的是硬盘上的某个文件。

无论是否启动swap机制,虚拟地址最终对应的都是物理页。只是在启动swap机制后,这个物理页可能在硬盘上(交换文件),也可能在RAM里。

简单理一下地址转换的流程:

虚拟地址 ---(通过MMU)--> 物理地址  ----> 访问到RAM里实际的物理页
                                      |
                                        -----> 物理页不存在,分配一个
                                      |
                                        ------> 物理页存在,但被交换到硬盘上,交换进来(swap机制启动的时候)。

其实后面的步骤是在产生page falut查页表的时做的,但为了方便理解,这样画了。

所以无论有没有swap机制,虚拟地址都对应物理地址,不存在虚拟地址指向交换文件的说法,只能说虚拟地址对应的物理地址所指向的物理页,可能在交换文件中。

[ 本帖最后由 zx_wing 于 2007-9-17 09:36 编辑 ]

论坛徽章:
4
戌狗
日期:2013-08-15 18:22:43技术图书徽章
日期:2013-08-21 13:48:45巨蟹座
日期:2013-09-26 17:06:39处女座
日期:2013-12-25 11:26:10
19 [报告]
发表于 2007-09-17 10:24 |只看该作者
原帖由 augustusqing 于 2007-9-16 02:13 发表

b7f2c000-b7f2d000 rw-p 0001a000 fe:00 81960      /lib/ld-2.5.1.so

这个才是interpreter的bss段吧,我的这个区间应该是栈,但确实有疑问,栈不是可执行的吗,却没带可执行位,难不成也是新版C库解决了栈溢出执行的问题,不知道其他平台是什么情况,哪个版本开始的,



这个应该不是bss。
bss应该是匿名影射,无论是可执行文件,interpreter还是lib的bss段,全部都是匿名影射,不应该有"0001a000 fe:00 81960"这些描述。




到是更高地址的那段匿名影射看起来象是bss,不过我不明白为什么      
b7f2c000-b7f2d000 rw-p 0001a000 fe:00  81960      /lib/ld-2.5.1.so
bfc03000-bfc19000 rw-p bfc03000   00:00 0         
两段中间留有一个空洞,按道理说bss段在地址上应该紧跟最后一个PT_LOAD的段,不会留有空洞。

论坛徽章:
0
20 [报告]
发表于 2007-09-17 11:43 |只看该作者
To zx_wing,

交换出去了,虚地址还能通过MMU得到物理地址?得不到了。因为pgd-pmd-pte都断链了。
还有交换在磁盘上的不是物理地址对应的物理页。如果是,物理页已经被别人使用着,怎么交换进来?先把使用的交换出去吗

虚拟地址 ---(通过MMU)--> 物理地址  ----> 访问到RAM里实际的物理页
                                      |
                                        -----> 物理页不存在,分配一个
                                      |
                                        ------> 物理页存在,但被交换到硬盘上,交换进来(swap机制启动的时候)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP