zoukankan      html  css  js  c++  java
  • Linux 内存布局

         本文主要简介在X86体系结构下和在ARM体系结构下,Linux内存布局的概况,力求简单明了,不过多深入概念,多以图示的方式来记忆理解,一图胜万言。

    Technorati 标签:

        X86体系结构

         在X86体系结构下,物理内存地址一般从0x0000_0000开始,而Linux内核主要按照在物理地址0x0010_0000开始的地方,即物理地址1M以上的空间。那最开始的1M空间是用来干什么的呢?

          考虑到通用的IBM-PC体系结构,最开始的1M空间由BIOS例程和映射ISA图形卡的内存,这块区域为了所有IBM兼容PC从640K到1M的物理地址,始终存在,但无法被操作系统使用。

    image 

    主要内存布局如上图所示:

         mmap映射区向下扩展,堆向上扩展,两者相对扩展,直到耗尽虚拟地址空间中的剩余区域。

         BSS段用来存放程序中未初始化的全局变量,该段内容只记录数据所需空间大小,并不分配真实空间。

         DATA段用来存放程序中已初始化的全局变量,为数据分配空间,数据具体值保持在目标文件中。

         CODE段用来存放程序中执行代码的内存区域,通常为大小确定的只读段,包括只读常量、只读代码等。

         image

      参考资料:从加载到进入kernel运行的内存布局变化

                   Linux系统启动过程分析

       ARM体系结构

         以S3C2410为例子,假设物理内存为64M,映射到ARM的起始物理地址为【0x3000_0000~0x3200_0000】,这个由硬件接线决定。我们可以通过查看内核编译输出的System.map文件来了解内核虚拟地址空间布局,结果类似如下:

         image  image

       可以看出内核镜像大小为3.7M,虚拟地址空间起始地址为0xc000_0000(这是开启MMU之后的虚拟地址空间),在内核head.S文件中,有内核线性地址和物理地址的描述,见下图:

    image

         PAGE_OFFSET为0xC000_0000,为内核虚拟地址相对偏移(相对于0地址的偏移),PHYS_OFFSET为内核载入实际物理地址相对偏移,不同的硬件板子,ARM访问的内存物理地址不一样,这里以0x3000_0000(这由硬件接线决定)为假设。TEXT_OFFSET为0x0000_8000,为编译时指定的代码段偏移,所以,uboot最后启动内核的地址为内核代码指定的KERNEL_RAM_PADDR(0x3000_8000),这样才能正常运行,而内核的入口地址和载入地址,最好设置成一样。而uboot加载kernel的实际地址设置为0x3000_7fc0,比KERNEL_RAM_PADDR少64个字节,这可以避免拷贝内核,64个字节为uImage内核镜像针对uboot添加的特定头部信息。

         从上面的检查宏可以看出,内核开始的物理地址,必须开始在0xXXXX_8000的地址空间。

          swapper_pg_dir 为内核全局页表的起始地址,stext为内核的入口虚拟地址,因此,可以看出,全局页表占据16K的空间。

         head.S文件的功能,主要获取处理器类型和机器类型信息,创建临时页表,然后开启MMU,并进入第一个C语言函数start_kernel。

         更加详细的可以参见:

        http://www.arm.linux.org.uk/developer/memory.txt
     
     

    内核提供的内存访问接口

        内核提供的所有接口都是以页为单位分配内存的,其中,最核心的函数为alloc_pages,其原型如下:

        struct page * alloc_pages(unsigned int gfp_mask,unsigned int order)

         该函数分配2^order个连续的物理页,并返回指向第一个页的指针。如果分配出错,返回NULL。其他的一些页分配接口。

         61d132cb54a04e109f063388c7260011

     

       1. kmalloc/kfree:    基于slab分配器的内存分配函数,支持分配大小32byte-128KB,分配的为物理地址连续的一段内存,使用GFP_KERNEL时,函数可能睡眠。使用GFP_ATOMIC时,函数不睡眠。

        kzalloc:基于kmallc的,分配一段内核内存并且清零。

        2.vmalloc/vfree:工作在内核虚拟空间的VMALLOC_START和VMALLOC_END所代表的vmalloc区,支持分配大内容,分配为逻辑地址连续的一段内存,速度慢,效率低,可能睡眠,映射的地址优先从ZONE_HIGHMEM分配.

        3.利用slab分配器的高速缓存,使用kmem_cache_create和keme_cache_alloc这两个函数。/proc/slabinfo查看所有的kmem_cache缓存。 keme_cache_alloc 用于需要频繁分配和释放同一类型的数据结构对象,充分利用硬件缓存,提升系统性能。

        相反的处理函数有kmem_cache_destory和kmem_cache_free

        4.用于多处理器的per-CPU变量,核心思想是,通过为系统中每个处理器都分配一个CPU特定的变量副本,减少多处理器并发访问时的锁定操作,提高系统性能。

     

    强烈推荐优秀参考链接:arm-linux启动过程

    Linux 内存使用方法详细解析

  • 相关阅读:
    Java程序:从命令行接收多个数字,求和并输出结果
    大道至简读后感
    大道至简第一章读后感Java伪代码
    Creating a SharePoint BCS .NET Connectivity Assembly to Crawl RSS Data in Visual Studio 2010
    声明式验证超时问题
    Error message when you try to modify or to delete an alternate access mapping in Windows SharePoint Services 3.0: "An update conflict has occurred, and you must re-try this action"
    Upgrading or Redeploying SharePoint 2010 Workflows
    Upgrade custom workflow in SharePoint
    SharePoint 2013中Office Web Apps的一次排错
    How to upgrade workflow assembly in MOSS 2007
  • 原文地址:https://www.cnblogs.com/cherishui/p/4235145.html
Copyright © 2011-2022 走看看