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

Technorati 标签: 内存 布局

    X86体系结构

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

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

 

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

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

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

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

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

    

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

               Linux系统启动过程分析

   ARM体系结构

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

      

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

     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。其他的一些页分配接口。

    

 

   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 内存使用方法详细解析

Linux 内存布局的更多相关文章

  1. linux 内存布局以及tlb更新的一些理解

    问题: 1.内核线程是否有vma线性区? 2.单线程的一个进程,它修改了自己的页表,是否需要发送ipi来通知其他核更新tlb? 3.普通进程,在32位和64位,对应的线性区的最大地址能到多少? 在64 ...

  2. Linux内存布局

    在上一篇博文里,我们已经看到Linux如何有效地利用80x86的分段和分页硬件单元把逻辑地址转换为线性地址,在由线性地址转换到物理地址.那么我们的应用程序如何使用这些逻辑地址,整个内存的地址布局又是怎 ...

  3. linux内存布局------深入理解计算机系统

  4. linux系统进程的内存布局

    内存管理模块是操作系统的心脏:它对应用程序和系统管理非常重要.今后的几篇文章中,我将着眼于实际的内存问题,但也不避讳其中的技术内幕.由于不少概念是通用的,所以文中大部分例子取自32位x86平台的Lin ...

  5. linux内存管理解析1----linux物理,线性内存布局及页表的初始化

    主要议题: 1分页,分段模式及实模式 2Linux分页 3linux内存线性地址空间布局及物理内存空间布局 4linux页表初始化及代码解析 1.1.1内存寻址和保护模式 在X86平台上,内存控制单元 ...

  6. [内存管理]linux X86_64处理器的内存布局图

    linux X86 64位内存布局图

  7. Linux内存管理 (3)内核内存的布局图

    专题:Linux内存管理专题 关键词:内核内存布局图.lowmem线性映射区.kernel image.ZONE_NORMAL.ZONE_HIGHMEM.swapper_pg_dir.fixmap.v ...

  8. Linux内存初始化(三) 内存布局

    一.前言 同样的,本文是内存初始化文章的一份补充文档,希望能够通过这样的一份文档,细致的展示在初始化阶段,Linux 4.4.6内核如何从device tree中提取信息,完成内存布局的任务.具体的c ...

  9. Linux进程地址空间 && 进程内存布局[转]

    一 进程空间分布概述       对于一个进程,其空间分布如下图所示: 程序段(Text):程序代码在内存中的映射,存放函数体的二进制代码. 初始化过的数据(Data):在程序运行初已经对变量进行初始 ...

随机推荐

  1. Java再学习——停止一个正在运行的线程

    关于这个问题,先了解一下Thread类方法中被废弃的那些方法.suspend(), resume(),stop()/stop(Throwable obj),destroy() 首先,stop(Thro ...

  2. mysql ERROR1405 access deny 问题解决

    sudo /usr/local/mysql/bin/mysqld_safe --user=mysql --skip-grant-tables --skip-networking 使用这条命令可以跳过开 ...

  3. velocity 随笔

    资源网站: http://wiki.apache.org/velocity/ http://velocity.apache.org/engine/releases/velocity-1.7/user- ...

  4. FormsAuthenticationTicket学习笔记

    FormsAuthenticationTicket ticket = , ), true, string.Format("{0}:{1}", "username" ...

  5. OC之Copy语法

    转载请注明:http://www.cnblogs.com/letougaozao/p/3631105.html 概念 内存管理 NSString的copy实例 对象的copy实例 一.概念 目的:在改 ...

  6. JAVA备忘录

    本文主要是记录一下JAVA: 1.Arrays.的几个用法: fill:数组全部置一个数 sort:排序 binarySearch:二分查找 2.Map的用法: Map<Integer,Inte ...

  7. 实现 kindle 原生系统、多看系弹出注释的通用写法

    入手 Kindle 后开始自己做 ePub,之前一直用原生系统,使用的弹出注释代码如下: <p class="P_Footnote" id="ref_footnot ...

  8. 解决cell循环利用造成的重复勾选

    @interface ProfessionViewController (){ NSMutableArray *_professionArray;//cell模型数组 NSMutableArray * ...

  9. [CAMCOCO][C#]我的系统架构.服务器端.(四)----Model层 实体的自我验证

    这是Model的第二篇,上一篇点这里 这块完全是扒了@何镇汐大神博客里的教程实现的,在这之前完全没想到数据验证居然可以这样做!!在此表示严重感谢!!! 点击这里可以去了解这个方法的原理,老胡估计自己是 ...

  10. SignalR 简介

    SignalR 简介 由帕特里克 · 弗莱彻|2013 年 2 月 27 日 英文原文地址:http://www.asp.net/signalr/overview/getting-started/in ...