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 內存使用方法詳細解析


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM