Linux 地址空间分布

转载 2013年10月28日 10:42:41

地址空间分布

  最近看了本书,突然对于地址空间有些疑惑。在深入理解linux内核中把地址分为三类:逻辑地址(汇编语言中操作数地址或指令的地址,对于80x86的cup,逻辑地址是段+段内偏移地址)、线性地址(也叫虚拟地址)和物理地址。但在Stott Maxwell的《Linux Core Kernel Commentrary》中确是这样分的:逻辑地址(也叫虚拟地址)、线性地址和物理地址。按照386 CPU总设计师 John Crowford的解释,虚拟地址是保护模式下段和段内偏移量组成的地址,而逻辑地址就是代码段内偏移量,或称进程的逻辑地址。其实对于linux来说,这三种说法都没错,由于linux下并不主张将程序分段,而是主张分页,所以即使是在80x86的体系结构下,段的基地址也是0。因此逻辑地址、线性地址、虚拟地址在linux中其实是相同的。所以对于linux下的elf可执行文件来说,代码段的起始地址0x08048000既是逻辑地址,也是线性地址也是虚拟地址。

  1 x86的物理地址空间布局:

 

  物理地址空间的顶部以下一段空间,被PCI设备的I/O内存映射占据,它们的大小和布局由PCI规范所决定。640K~1M这段地址空间被BIOSVGA适配器所占据 

  Linux系统在初始化时,会根据实际的物理内存的大小,为每个物理页面创建一个page对象,所有的page对象构成一个mem_map数组。 

进一步,针对不同的用途,Linux内核将所有的物理页面划分到3类内存管理区中,如图,分别为ZONE_DMA,ZONE_NORMAL,ZONE_HIGHMEM。 

  ZONE_DMA的范围是0~16M,该区域的物理页面专门供I/O设备的DMA使用。之所以需要单独管理DMA的物理页面,是因为DMA使用物理地址访问内存,不经过MMU,并且需要连续的缓冲区,所以为了能够提供物理上连续的缓冲区,必须从物理地址空间专门划分一段区域用于DMA 

  ZONE_NORMAL的范围是16M~896M,该区域的物理页面是内核能够直接使用的。 

  ZONE_HIGHMEM的范围是896M~结束,该区域即为高端内存,内核不能直接使用。

linux虚拟地址内核空间分布

  在kernel image下面有16M的内核空间用于DMA操作。位于内核空间高端的128M地址主要由3部分组成,分别为vmalloc area,持久化内核映射区,临时内核映射区。

  由于ZONE_NORMAL和内核线性空间存在直接映射关系,所以内核会将频繁使用的数据如kernel代码、GDT、IDT、PGD、mem_map数组等放在ZONE_NORMAL里。而将用户数据、页表(PT)等不常用数据放在ZONE_ HIGHMEM里,只在要访问这些数据时才建立映射关系(kmap())。比如,当内核要访问I/O设备存储空间时,就使用ioremap()将位于物理地址高端的mmio区内存映射到内核空间的vmalloc area中,在使用完之后便断开映射关系。 

3 linux虚拟地址用户空间分布

  用户进程的代码区一般从虚拟地址空间的0x08048000开始,这是为了便于检查空指针。代码区之上便是数据区,未初始化数据区,堆区,栈区,以及参数、全局环境变量。

4 linux虚拟地址与物理地址映射的关系

 

  Linux4G的线性地址空间分为2部分,0~3Guser space3G~4Gkernel space

  由于开启了分页机制,内核想要访问物理地址空间的话,必须先建立映射关系,然后通过虚拟地址来访问。为了能够访问所有的物理地址空间,就要将全部物理地址空间映射到1G的内核线性空间中,这显然不可能。于是,内核将0~896M的物理地址空间一对一映射到自己的线性地址空间中,这样它便可以随时访问ZONE_DMAZONE_NORMAL里的物理页面;此时内核剩下的128M线性地址空间不足以完全映射所有的ZONE_HIGHMEMLinux采取了动态映射的方法,即按需的将ZONE_HIGHMEM里的物理页面映射到kernel space的最后128M线性地址空间里,使用完之后释放映射关系,以供其它物理页面映射。虽然这样存在效率的问题,但是内核毕竟可以正常的访问所有的物理地址空间了。

5 linux中可执行程序与虚拟地址空间的映射关系

  虚拟内存区域(VMA,Virtual Memory Area)是Linux中进程虚拟地址空间中的一个段,在Windows里面叫虚拟段。当操作系统创建线程后,会在进程相应的数据结构中设置一个.text段的VMA,它在虚拟空间中的地址为0x08048000~0x08049000,它对应ELF文件中的偏移为0.text。可以查看操作系统为运行的进程维护的信息:

 

从上面的图可以看出,虚拟空间地址为0x08048000~0x08049000VMA映射为elf文件中的一个段(segment),并且是按整页进行映射的。

  由于linux下的ELF可执行文件会有很多个段(section),所以如果把每个section都映射为一个VMA,那么没有一个页大小的段(section)也会被映射为一个页的VMA,这样就浪费了物理空间,由于不足会用0补充。故elf有一个装载的段(segment),与前面的段(section)不同,前面的段(section)主要用于链接,而段(segment)主要用于装载进内存。

 

  可以看出段(segment)02包含了很多的段(section),那链接器怎样将段(section)合并到一个段(segment)中的呢?可以通过段(section)的权限来合并,如以代码段为代表的权限为可读可执行权限;以数据段和BSS段为代表的权限为可读可写的段;以只读数据为代表的权限为只读权限。

  ELFLinux进程虚拟空间映射关系如下图所示:

 

  即使把多个段(section)合并到几个段(segment),每个段(segment)还是又很能产生较大的页内碎片,怎样解决这个问题呢?Unix巧妙的通过各个段(segment)接壤部分共享一个物理页来解决这个问题。 

参考:http://www.cnblogs.com/zszmhd/archive/2012/08/29/2661461.html、深入理解linux内核、Linux Core Kernel Commentrary、程序员的自我修养。


linux虚拟地址空间你真的理解了吗?

学了很久linux内核了,但对于linux内核对于内存管理这块始终有许多疑问,学而不思则罔!看了许多书籍和博客但还是没有搞得很明白。今天仔细思考了为什么需要虚拟内存的问题,突然觉得很有收获,所以记下来...
  • a675311
  • a675311
  • 2015年10月20日 17:19
  • 2817

Linux内核地址空间分布和进程地址空间

内核地址空间分布 直接映射区:线性空间中从3G开始最大896M的区间,为直接内存映射区,该区域的线性地址和物理地址存在线性转换关系:线性地址=3G+物理地址。 动态内存映射区:该区域由内核函数...
  • michaelcao1980
  • michaelcao1980
  • 2015年01月30日 16:56
  • 1217

进程地址空间分布

转载请注明出处:http://blog.csdn.net/wangxiaolong_china   对于一个进程,其空间分布如下图所示: C程序一般分为: 1.程序段:程序段为程序...
  • wangxiaolong_china
  • wangxiaolong_china
  • 2011年10月04日 20:24
  • 4924

Linux虚拟地址空间布局以及进程栈和线程栈总结

本文转自多个博客,以及最后有我的总结。我们有单独从头到尾写一个总结的原因是别人已经写得很好了,我不花大量时间是无法达到这水平的。 一:Linux虚拟地址空间布局 (转自:Linux虚拟地址空间布局...
  • FreeeLinux
  • FreeeLinux
  • 2016年12月21日 18:55
  • 4730

Linux虚拟地址空间分布

Linux虚拟地址空间分布
  • wendy_keeping
  • wendy_keeping
  • 2017年06月16日 23:35
  • 263

Linux进程地址空间分析

  • 2012年01月29日 19:01
  • 41KB
  • 下载

Linux虚拟地址空间布局

Linux虚拟地址空间布局        在多任务操作系统中,每个进程都运行在属于自己的内存沙盘中。这个沙盘就是虚拟地址空间(Virtual Address Space),...
  • wm_1991
  • wm_1991
  • 2016年08月09日 19:43
  • 1260

Linux 应用程序的地址空间分布

Linux 应用程序在被内核调入内存中运行后就成为一个进程,因此分析应用程序的地址空间实际上就是分析进程的地址空间分布。 应用程序的地址空间实际上由以下几个部分组成:代码段、初始化数据段、未初始化数据...
  • u013819957
  • u013819957
  • 2015年10月26日 17:25
  • 912

Linux下x86_64进程地址空间布局

关于Linux 32位内存下的内存空间布局,可以参考这篇博文Linux下C程序进程地址空间局关于源代码中各种数据类型/代码在elf格式文件以及进程空间中所处的段,在x86_64下和i386下是类似的,...
  • feilengcui008
  • feilengcui008
  • 2015年03月08日 23:33
  • 2165

Linux内核--内核地址空间分布和进程地址空间

内核地址空间分布 直接映射区:线性空间中从3G开始最大896M的区间,为直接内存映射区,该区域的线性地址和物理地址存在线性转换关系:线性地址=3G+物理地址。 动态内存映射区:该区域由内核函数...
  • u014774781
  • u014774781
  • 2015年08月16日 23:29
  • 966
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Linux 地址空间分布
举报原因:
原因补充:

(最多只允许输入30个字)