您好,登錄后才能下訂單哦!
這篇文章主要講解了“Linux內(nèi)存怎么初始化”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“Linux內(nèi)存怎么初始化”吧!
void __init paging_init(void)
{
phys_addr_t pgd_phys = early_pgtable_alloc();//分配一頁(yè)大小的物理內(nèi)存放進(jìn)pgd
pgd_t *pgd = pgd_set_fixmap(pgd_phys);
map_kernel(pgd);//將內(nèi)核的各個(gè)段進(jìn)行映射 .text .init .data .bss
map_mem(pgd);//將memblock子系統(tǒng)添加的物理內(nèi)存進(jìn)行映射(將物理地址映射到線性區(qū)域)
/*
* 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));//切換頁(yè)表
memcpy(swapper_pg_dir, pgd, PGD_SIZE);//將新建立的頁(yè)表內(nèi)容替換swapper_pg_dir頁(yè)表內(nèi)容
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);
}
主要是完成通過(guò)memblock_add添加到系統(tǒng)中的物理內(nèi)存映射,注意如果memblock設(shè)置了MEMBLOCK_NOMAP標(biāo)志的話則不對(duì)其地址映射。
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();
}
這個(gè)函數(shù)基本上完成了linux對(duì)物理內(nèi)存“劃分”的初始化,包括node, zone, page frame,以及對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu)。在講這個(gè)函數(shù)之前,我們需要了解下物理內(nèi)存組織。
「Linux是如何組織物理內(nèi)存的?」
「node」:
目前計(jì)算機(jī)系統(tǒng)有兩種體系結(jié)構(gòu):
「zone」:
ZONE的意思是把整個(gè)物理內(nèi)存劃分為幾個(gè)區(qū)域,每個(gè)區(qū)域有特殊的含義
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」:
代表一個(gè)物理頁(yè),在內(nèi)核中一個(gè)物理頁(yè)用一個(gè)struct page表示。
「page frame」:
為了描述一個(gè)物理page,內(nèi)核使用struct page結(jié)構(gòu)來(lái)表示一個(gè)物理頁(yè)。假設(shè)一個(gè)page的大小是4K的,內(nèi)核會(huì)將整個(gè)物理內(nèi)存分割成一個(gè)一個(gè)4K大小的物理頁(yè),而4K大小物理頁(yè)的區(qū)域我們稱為page frame
「page frame num(pfn)」 :
pfn是對(duì)每個(gè)page frame的編號(hào)。故物理地址和pfn的關(guān)系是:
物理地址>>PAGE_SHIFT = pfn
「pfn和page的關(guān)系」:
內(nèi)核中支持了好幾個(gè)內(nèi)存模型:CONFIG_FLATMEM(平坦內(nèi)存模型)CONFIG_DISCONTIGMEM(不連續(xù)內(nèi)存模型)CONFIG_SPARSEMEM_VMEMMAP(稀疏的內(nèi)存模型)目前ARM64使用的稀疏的類型模式
/* memmap is virtually contiguous. */
#define __pfn_to_page(pfn) (vmemmap + (pfn))
#define __page_to_pfn(page) (unsigned long)((page) - vmemmap)
系統(tǒng)啟動(dòng)的時(shí)候,內(nèi)核會(huì)將整個(gè)struct page映射到內(nèi)核虛擬地址空間vmemmap的區(qū)域,所以我們可以簡(jiǎn)單的認(rèn)為struct page的基地址是vmemmap,則:
vmemmap+pfn的地址就是此struct page對(duì)應(yīng)的地址。
感謝各位的閱讀,以上就是“Linux內(nèi)存怎么初始化”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)Linux內(nèi)存怎么初始化這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。