91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Linux內存怎么初始化

發布時間:2021-12-17 09:59:03 來源:億速云 閱讀:220 作者:iii 欄目:大數據

這篇文章主要講解了“Linux內存怎么初始化”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Linux內存怎么初始化”吧!

paging_init

void __init paging_init(void)
{
 phys_addr_t pgd_phys = early_pgtable_alloc();//分配一頁大小的物理內存放進pgd
 pgd_t *pgd = pgd_set_fixmap(pgd_phys);

 map_kernel(pgd);//將內核的各個段進行映射 .text .init .data .bss
 map_mem(pgd);//將memblock子系統添加的物理內存進行映射(將物理地址映射到線性區域)

 /*
  * We want to reuse the original swapper_pg_dir so we don't have to
  * communicate the new address to non-coherent secondaries in
  * secondary_entry, and so cpu_switch_mm can generate the address with
  * adrp+add rather than a load from some global variable.
  *
  * To do this we need to go via a temporary pgd.
  */
 cpu_replace_ttbr1(__va(pgd_phys));//切換頁表
 memcpy(swapper_pg_dir, pgd, PGD_SIZE);//將新建立的頁表內容替換swapper_pg_dir頁表內容
 cpu_replace_ttbr1(lm_alias(swapper_pg_dir));

 pgd_clear_fixmap();
 memblock_free(pgd_phys, PAGE_SIZE);

 /*
  * We only reuse the PGD from the swapper_pg_dir, not the pud + pmd
  * allocated with it.
  */
 memblock_free(__pa_symbol(swapper_pg_dir) + PAGE_SIZE,
        SWAPPER_DIR_SIZE - PAGE_SIZE);
}
 
  • early_pgtable_alloc:分配一頁大小的物理內存放進pgd
  • map_kernel(pgd):將內核的各個段進行映射(.text .init .data .bss)
Linux內存怎么初始化  
  • map_mem(pgd):將memblock子系統添加的物理內存進行映射(將物理地址映射到線性區域)

主要是完成通過memblock_add添加到系統中的物理內存映射,注意如果memblock設置了MEMBLOCK_NOMAP標志的話則不對其地址映射。

  • cpu_replace_ttbr1(__va(pgd_phys)):切換頁表
  • memcpy(swapper_pg_dir, pgd, PGD_SIZE):將新建立的頁表內容替換swapper_pg_dir頁表內容
 

bootmem_init

void __init bootmem_init(void)
{
 unsigned long min, max;

 min = PFN_UP(memblock_start_of_DRAM());
 max = PFN_DOWN(memblock_end_of_DRAM());

 early_memtest(min << PAGE_SHIFT, max << PAGE_SHIFT);

 max_pfn = max_low_pfn = max;

 arm64_numa_init();
 /*
  * Sparsemem tries to allocate bootmem in memory_present(), so must be
  * done after the fixed reservations.
  */
 arm64_memory_present();

 sparse_init();
 zone_sizes_init(min, max);

 memblock_dump_all();
}

 

這個函數基本上完成了linux對物理內存“劃分”的初始化,包括node, zone, page frame,以及對應的數據結構。在講這個函數之前,我們需要了解下物理內存組織。

「Linux是如何組織物理內存的?」

「node」

目前計算機系統有兩種體系結構:

  • 非一致性內存訪問 NUMA(Non-Uniform Memory Access)意思是內存被劃分為各個node,訪問一個node花費的時間取決于CPU離這個node的距離。每一個cpu內部有一個本地的node,訪問本地node時間比訪問其他node的速度快
  • 一致性內存訪問 UMA(Uniform Memory Access)也可以稱為SMP(Symmetric Multi-Process)對稱多處理器。意思是所有的處理器訪問內存花費的時間是一樣的。也可以理解整個內存只有一個node。

「zone」

ZONE的意思是把整個物理內存劃分為幾個區域,每個區域有特殊的含義

enum zone_type {
#ifdef CONFIG_ZONE_DMA
 /*
  * ZONE_DMA is used when there are devices that are not able
  * to do DMA to all of addressable memory (ZONE_NORMAL). Then we
  * carve out the portion of memory that is needed for these devices.
  * The range is arch specific.
  *
  * Some examples
  *
  * Architecture  Limit
  * ---------------------------
  * parisc, ia64, sparc <4G
  * s390   <2G
  * arm   Various
  * alpha  Unlimited or 0-16MB.
  *
  * i386, x86_64 and multiple other arches
  *    <16M.
  */
 ZONE_DMA,
#endif
#ifdef CONFIG_ZONE_DMA32
 /*
  * x86_64 needs two ZONE_DMAs because it supports devices that are
  * only able to do DMA to the lower 16M but also 32 bit devices that
  * can only do DMA areas below 4G.
  */
 ZONE_DMA32,
#endif
 /*
  * Normal addressable memory is in ZONE_NORMAL. DMA operations can be
  * performed on pages in ZONE_NORMAL if the DMA devices support
  * transfers to all addressable memory.
  */
 ZONE_NORMAL,
#ifdef CONFIG_HIGHMEM
 /*
  * A memory area that is only addressable by the kernel through
  * mapping portions into its own address space. This is for example
  * used by i386 to allow the kernel to address the memory beyond
  * 900MB. The kernel will set up special mappings (page
  * table entries on i386) for each page that the kernel needs to
  * access.
  */
 ZONE_HIGHMEM,
#endif
 ZONE_MOVABLE,
#ifdef CONFIG_ZONE_DEVICE
 ZONE_DEVICE,
#endif
 __MAX_NR_ZONES

};
 

「page」

代表一個物理頁,在內核中一個物理頁用一個struct page表示。

「page frame」:

為了描述一個物理page,內核使用struct page結構來表示一個物理頁。假設一個page的大小是4K的,內核會將整個物理內存分割成一個一個4K大小的物理頁,而4K大小物理頁的區域我們稱為page frame

 

「page frame num(pfn)」 :

pfn是對每個page frame的編號。故物理地址和pfn的關系是:

物理地址>>PAGE_SHIFT = pfn

「pfn和page的關系」

內核中支持了好幾個內存模型:CONFIG_FLATMEM(平坦內存模型)CONFIG_DISCONTIGMEM(不連續內存模型)CONFIG_SPARSEMEM_VMEMMAP(稀疏的內存模型)目前ARM64使用的稀疏的類型模式

/* memmap is virtually contiguous.  */
#define __pfn_to_page(pfn) (vmemmap + (pfn))
#define __page_to_pfn(page) (unsigned long)((page) - vmemmap)

系統啟動的時候,內核會將整個struct page映射到內核虛擬地址空間vmemmap的區域,所以我們可以簡單的認為struct page的基地址是vmemmap,則:

vmemmap+pfn的地址就是此struct page對應的地址。

感謝各位的閱讀,以上就是“Linux內存怎么初始化”的內容了,經過本文的學習后,相信大家對Linux內存怎么初始化這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

军事| 淮滨县| 长白| 福州市| 珠海市| 桃江县| 抚顺县| 清水河县| SHOW| 双峰县| 广丰县| 三江| 宁德市| 秀山| 泰顺县| 盐津县| 郓城县| 沙湾县| 富锦市| 天门市| 石门县| 成武县| 封丘县| 丹寨县| 南华县| 崇左市| 兴文县| 应城市| 新余市| 崇义县| 庐江县| 宝山区| 英吉沙县| 墨竹工卡县| 陆川县| 灵宝市| 鄱阳县| 莱西市| 望都县| 唐海县| 贵阳市|