![linux內(nèi)存管理分析2_第1頁(yè)](http://file4.renrendoc.com/view/763a97c81b400c021a2d24c50d6a5105/763a97c81b400c021a2d24c50d6a51051.gif)
![linux內(nèi)存管理分析2_第2頁(yè)](http://file4.renrendoc.com/view/763a97c81b400c021a2d24c50d6a5105/763a97c81b400c021a2d24c50d6a51052.gif)
![linux內(nèi)存管理分析2_第3頁(yè)](http://file4.renrendoc.com/view/763a97c81b400c021a2d24c50d6a5105/763a97c81b400c021a2d24c50d6a51053.gif)
![linux內(nèi)存管理分析2_第4頁(yè)](http://file4.renrendoc.com/view/763a97c81b400c021a2d24c50d6a5105/763a97c81b400c021a2d24c50d6a51054.gif)
![linux內(nèi)存管理分析2_第5頁(yè)](http://file4.renrendoc.com/view/763a97c81b400c021a2d24c50d6a5105/763a97c81b400c021a2d24c50d6a51055.gif)
版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、linux 內(nèi)存管理分析【二】2012-11-19 21:09:22| 分類(lèi): 默認(rèn)分類(lèi) | 標(biāo)簽: | 字號(hào)大中小 訂閱2 內(nèi)存管理系統(tǒng)建立過(guò)程為建立內(nèi)存管理系統(tǒng),在內(nèi)核初始化過(guò)程中調(diào)用了下面幾個(gè)函數(shù):init/main.casmlinkage void _init start_kernel(void)初始化持久映射與臨時(shí)映射的一些信息,后面持久映射和臨時(shí)映射一節(jié)將詳細(xì)講解page_address_init();setup_arch 是特定于體系架構(gòu)的函數(shù),負(fù)責(zé)初始化自舉分配器和內(nèi)核頁(yè)表等。setup_arch(&command_line);初始化 per_cpu 機(jī)制的一些結(jié)構(gòu),將.dat
2、a.percpu 段中的數(shù)據(jù)拷貝到每個(gè)CPU 的數(shù)據(jù)段中setup_per_cpu_areas();建立結(jié)點(diǎn)和內(nèi)存域之間的關(guān)系build_all_zonelists(NULL);停用自舉分配器bootmem ,遷移到實(shí)際的內(nèi)存管理中,初始化 slab 分配器,初始化進(jìn)程虛擬地址空間管理結(jié)構(gòu)mm_init();為每一個(gè)內(nèi)存區(qū)域分配per_cpu_pageset 結(jié)構(gòu)并初始化其成員setup_per_cpu_pageset();【 start_kernelsetup_arch 】arch/arm/kernel/setup.cvoid _init setup_arch(char *cmdline_p
3、)struct machine_desc *mdesc;內(nèi)核參數(shù)可以通過(guò)平坦設(shè)備樹(shù)或者 tags 由 bootloader 傳遞給內(nèi)核。每一個(gè)機(jī)器平臺(tái)都由一個(gè)struct machine_desc 結(jié)構(gòu)來(lái)描述,內(nèi)核所支持的所有平臺(tái)對(duì)應(yīng)的machine_desc 結(jié)構(gòu)都包含在段. 的 _arch_info_begin 到 _tagtable_end 之間。但每一個(gè)平臺(tái)都有其唯一的機(jī)器碼machine_arch_type , 可通過(guò)機(jī)器碼在段. 中找到對(duì)應(yīng)的平臺(tái)描述結(jié)構(gòu)。 函數(shù) setup_machine_tags 就是根據(jù)機(jī)器碼找到對(duì)應(yīng)的平臺(tái)描述結(jié)構(gòu),并且分析內(nèi)核參數(shù)中內(nèi)存相關(guān)的信息,用以初始化
4、內(nèi)存塊管理結(jié)構(gòu)membank 。mdesc = setup_machine_fdt(_atags_pointer);if (!mdesc)mdesc = setup_machine_tags(machine_arch_type);machine_desc = mdesc;machine_name = mdesc-name;根據(jù) mdesc-dma_zone_size 設(shè)置 DMA 區(qū)域的大小 arm_dma_zone_size , 和 DMA 區(qū)域的結(jié)束地址 arm_dma_limitsetup_dma_zone(mdesc);結(jié)構(gòu) struct mm_struct 管理進(jìn)程的虛擬地址空間,所
5、有內(nèi)核線(xiàn)程都使用共同的地址空間,因?yàn)樗麄兌际怯孟嗤牡刂酚成?,這個(gè)地址空間由init_mm來(lái)描述。_text和_etext表示內(nèi)核鏡像代碼段的起始和結(jié)束位置,_etext和_edata之間是已初始化數(shù)據(jù)段, _edata至Lend是未初始化數(shù)據(jù)段等, _end 之后便是堆區(qū)。init_mm.start_code = (unsigned long) _text;init_mm.end_code = (unsigned long) _etext;init_mm.end_data = (unsigned long) _edata;init_mm.brk = (unsigned long) _end;
6、內(nèi)核命令行參數(shù)在函數(shù)setup_machine_tags 獲取并保存在了 boot_command_line 中strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);*cmdline_p = cmd_line;分析命令行參數(shù),主要關(guān)注一些與內(nèi)存相關(guān)的東西parse_early_param();將內(nèi)存塊按從小到大排序sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank0), meminfo_cmp, NULL);掃描各個(gè)內(nèi)存塊,檢測(cè)低端內(nèi)存的最大值arm_lowmem_limi
7、t ,設(shè)置高端內(nèi)存起始值的虛擬地址 high_memorysanity_check_meminfo();將所有內(nèi)存塊添加到結(jié)構(gòu)memblock 的 memory 區(qū)中, 將已使用的內(nèi)存添加到 reserved 區(qū)中去。arm_memblock_init(&meminfo, mdesc);創(chuàng)建內(nèi)核頁(yè)表,初始化自舉分配器paging_init(mdesc);內(nèi)核中將許多物理資源用 struct resource 結(jié)構(gòu)來(lái)管理, 下面函數(shù)就是將IO 內(nèi)存作為 resource注冊(cè)到內(nèi)核request_standard_resources(mdesc);如果內(nèi)核命令行中有預(yù)留用于內(nèi)核crash 是的轉(zhuǎn)存
8、空間,就將這些存儲(chǔ)空間標(biāo)記為已分配reserve_crashkernel();【 start_kernelsetup_archsetup_machine_tags 】arch/arm/kernel/setup.cstatic struct machine_desc * _init setup_machine_tags(unsigned int nr)struct tag *tags = (struct tag *)&init_tags;struct machine_desc *mdesc = NULL, *p;char *from = default_command_line;init_tag
9、s.mem.start = PHYS_OFFSET;下面循環(huán)根據(jù)機(jī)器號(hào)在段. 中尋找對(duì)應(yīng)的 machine_desc 結(jié)構(gòu)for_each_machine_desc(p)if (nr = p-nr) printk(Machine: %sn, p-name);mdesc = p;break; Bootloader 傳入的參數(shù)地址存放在_atags_pointer 中if (_atags_pointer)tags = phys_to_virt(_atags_pointer);else if (mdesc-atag_offset)tags = (void *)(PAGE_OFFSET + mdesc
10、-atag_offset);內(nèi)核參數(shù)是由 struct tag 來(lái)管理,其中第一個(gè)tag 類(lèi)型必然是ATAG_COREif (tags-hdr.tag != ATAG_CORE) tags = (struct tag *)&init_tags; 內(nèi)核提供的一個(gè)默認(rèn)參數(shù)列表函數(shù) mdesc-fixup 中一般會(huì)獲取內(nèi)存塊的信息if (mdesc-fixup)mdesc-fixup(tags, &from, &meminfo);if (tags-hdr.tag = ATAG_CORE) 如果內(nèi)存塊已經(jīng)初始化,就將參數(shù)列表中關(guān)于內(nèi)存的參數(shù)標(biāo)記為 ATAG_NONEif (meminfo.nr_ban
11、ks != 0)squash_mem_tags(tags);將參數(shù)列表拷貝到一個(gè)靜態(tài)數(shù)組 atags_copy 中save_atags(tags);分析內(nèi)核參數(shù),后面細(xì)講parse_tags(tags);將解析出來(lái)的內(nèi)核命令行信息拷貝到靜態(tài)數(shù)組 boot_command_line 中。 在內(nèi)核啟動(dòng)期間用了很多靜態(tài)存儲(chǔ)空間,它們前面綴有_initdata ,像這樣的空間在內(nèi)核啟動(dòng)起來(lái)后將被釋放strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);return mdesc;【 start_kernelsetup_archsetup_machine_
12、tagsparse_tags 】arch/arm/kernel/setup.cstatic void _init parse_tags(const struct tag *t)遍歷參數(shù)列表中每一個(gè)參數(shù)結(jié)構(gòu)for (; t-hdr.size; t = tag_next(t)if (!parse_tag(t) 【 start_kernelsetup_archsetup_machine_tagsparse_tagsparse_tag 】 arch/arm/kernel/setup.cstatic int _init parse_tag(const struct tag *tag)extern str
13、uct tagtable _tagtable_begin, _tagtable_end;struct tagtable *t;參數(shù)類(lèi)型多種多樣解析方式也各不相同,所有針對(duì)每一種參數(shù)類(lèi)型都有一個(gè)對(duì)應(yīng)的解析函數(shù),這些解析函數(shù)和其參數(shù)類(lèi)型由結(jié)構(gòu)struct tagtable 來(lái)管理。這些結(jié)構(gòu)都存放在段.init.tagtable 的_tagtable_begin 和_tagtable_end 之間。for (t = &_tagtable_begin; t hdr.tag = t-tag) t-parse(tag);break;return t u.mem.start, tag-u.mem.size)
14、;_tagtable(ATAG_MEM, parse_tag_mem32);【 parse_tag_mem32arm_add_memory 】從ATAG_MEM參數(shù)中獲取內(nèi)存信息,初始化內(nèi)存塊管理結(jié)構(gòu)int _init arm_add_memory(phys_addr_t start, unsigned long size)struct membank *bank = &meminfo.bankmeminfo.nr_banks;if (meminfo.nr_banks = NR_BANKS) printk(KERN_CRIT NR_BANKS too low, ignoring memory
15、at 0 x%08llxn, (long long)start);return -EINVAL;size -= start & PAGE_MASK;bank-start = PAGE_ALIGN(start);#ifndef CONFIG_LPAEif (bank-start + size start) size = ULONG_MAX - bank-start;#endifbank-size = size & PAGE_MASK;if (bank-size = 0)return -EINVAL;meminfo.nr_banks+;return 0;【 start_kernelsetup_ar
16、chsanity_check_meminfo 】arch/arm/mm/mmu.cvoid _init sanity_check_meminfo(void) int i, j, highmem = 0;遍歷每一個(gè)內(nèi)存塊for (i = 0, j = 0; i start ULONG_MAX) highmem = 1;#ifdef CONFIG_HIGHMEMvmalloc_min 在 文 件 arch/arm/mm/mmu.c 中 定 義 , 它 定 義 了 高 端 內(nèi) 存 的 起 始 位 置 。PAGE_OFFSE建物理位置的起始處。如果內(nèi)存塊起始位置大于vmalloc_min ,表示存在高
17、端內(nèi)存。如果內(nèi)存擴(kuò)展超過(guò) 32位,它就有可能小于 PAGE_OFFSETif (_va(bank-start) = vmalloc_min |_va(bank-start) highmem = highmem;如果該內(nèi)存塊部分處于高端內(nèi)存中,部分處于低端內(nèi)存中就將其分為兩個(gè)內(nèi)存塊。if (!highmem & _va(bank-start) size vmalloc_min - _va(bank-start) if (meminfo.nr_banks = NR_BANKS) else memmove(bank + 1, bank,(meminfo.nr_banks - i) * sizeof(
18、*bank);meminfo.nr_banks+;i+;bank1.size -= vmalloc_min - _va(bank-start);bank1.start = _pa(vmalloc_min - 1) + 1;bank1.highmem = highmem = 1;j+;bank-size = vmalloc_min - _va(bank-start);#else 如果不支持高端內(nèi)存做如下處理bank-highmem = highmem;if (highmem) continue;if (_va(bank-start) = vmalloc_min |va(bank-start) s
19、tart + bank-size) vmalloc_min |_va(bank-start + bank-size) start) unsigned long newsize = vmalloc_min - _va(bank-start);bank-size = newsize;#endif求出低端內(nèi)存的最大地址值if (!bank-highmem & bank-start + bank-size arm_lowmem_limit) arm_lowmem_limit = bank-start + bank-size;j+; meminfo.nr_banks = j; 記錄內(nèi)存塊數(shù)計(jì)算高端內(nèi)存起
20、始地址,該值不一定等于vmalloc_min ,因?yàn)榭赡軟](méi)有高端內(nèi)存high_memory = _va(arm_lowmem_limit - 1) + 1;memblock_set_current_limit(arm_lowmem_limit);【 start_kernelsetup_archarm_memblock_init 】arch/arm/mm/init.cvoid _init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc) int i;將所有內(nèi)存模塊添加到 memblock.memory 中。結(jié)構(gòu)體
21、memblock 在文件 mm/memblock.c 中 定義,如下:struct memblock memblock _initdata_memblock = .memory.regions = memblock_memory_init_regions, .reserved.regions = memblock_reserved_init_regions, ;for (i = 0; i nr_banks; i+)memblock_add(mi-banki.start, mi-banki.size);如果內(nèi)核在rom 中運(yùn)行就只將它的數(shù)據(jù)段開(kāi)始的空間添加到 memblock.reserved
22、中, 否則將內(nèi)核代碼段開(kāi)始的空間添加到 memblock.reserved 中。#ifdef CONFIG_XIP_KERNELmemblock_reserve(_pa(_sdata), _end - _sdata);#elsememblock_reserve(_pa(_stext), _end - _stext);#endif#ifdef CONFIG_BLK_DEV_INITRD如果支持 initrd 啟動(dòng),此時(shí)它還不在內(nèi)存中if (phys_initrd_size &!memblock_is_region_memory(phys_initrd_start, phys_initrd_siz
23、e) pr_err(INITRD: 0 x%08lx+0 x%08lx is not a memory region - disabling initrdn, phys_initrd_start, phys_initrd_size);phys_initrd_start = phys_initrd_size = 0;if (phys_initrd_size &memblock_is_region_reserved(phys_initrd_start, phys_initrd_size) pr_err(INITRD: 0 x%08lx+0 x%08lx overlaps in-use memory
24、 region - disabling initrdn, phys_initrd_start, phys_initrd_size);phys_initrd_start = phys_initrd_size = 0;為 inird 鏡像預(yù)留一塊存儲(chǔ)區(qū)if (phys_initrd_size) memblock_reserve(phys_initrd_start, phys_initrd_size);initrd_start = _phys_to_virt(phys_initrd_start);initrd_end = initrd_start + phys_initrd_size;#endif為
25、內(nèi)核頁(yè)表分配存儲(chǔ)空間arm_mm_memblock_reserve();【 start_kernelsetup_archpaging_init 】arch/arm/mm/mmu.cvoid _init paging_init(struct machine_desc *mdesc) void *zero_page;memblock_set_current_limit(arm_lowmem_limit);根據(jù)不同的 arm 版本初始化不同的 mem_types ,該結(jié)構(gòu)存放著頁(yè)表的一些屬性相關(guān)信息build_mem_type_table();將除了內(nèi)核鏡像、主內(nèi)存所在虛擬地址之外全部?jī)?nèi)存的頁(yè)表清除
26、掉prepare_page_table();為低端內(nèi)存的所有區(qū)域創(chuàng)建內(nèi)核頁(yè)表map_lowmem();對(duì) DMA 區(qū)域重新創(chuàng)建頁(yè)表dma_contiguous_remap();為設(shè)備IO空間和中斷向量表創(chuàng)建頁(yè)表,并刷新 TLB和緩存 devicemaps_init(mdesc);獲取持久映射區(qū)頁(yè)表的位置,存儲(chǔ)在pkmap_page_table 中kmap_init();高 64K 是用于存放中斷向量表的top_pmd = pmd_off_k(0 xffff0000);分配一個(gè) 0 頁(yè),該頁(yè)用于寫(xiě)時(shí)復(fù)制機(jī)制。zero_page = early_alloc(PAGE_SIZE);初始化自舉內(nèi)存分配
27、,后面有專(zhuān)門(mén)章節(jié)講解bootmem_init();empty_zero_page = virt_to_page(zero_page);刷新數(shù)據(jù)緩存_flush_dcache_page(NULL, empty_zero_page); 【 start_kernelsetup_archpaging_initprepare_page_table 】arch/arm/mm/mmu.cstatic inline void prepare_page_table(void) unsigned long addr;phys_addr_t end;模塊力口載的范圍應(yīng)該是在MODULES_VADDRgU MODUL
28、ES_EN0間,MODULES_VADDRfc文件 arch/arm/include/asm/memory.h 中定義,如下:#define MODULES_VADDR (PAGE_OFFSET - 8*1024*1024)對(duì)于arm處理器,該區(qū)域在正常內(nèi)核虛擬地址之下。清除存儲(chǔ)空間在MODULES_VADDR之下的頁(yè)表項(xiàng)。for (addr = 0; addr MODULES_VADDR; addr += PMD_SIZE) pmd_clear(pmd_off_k(addr);#ifdef CONFIG_XIP_KERNELaddr = (unsigned long)_etext + PMD
29、_SIZE - 1) & PMD_MASK;#endiffor ( ; addr = arm_lowmem_limit)end = arm_lowmem_limit;for (addr = _phys_to_virt(end);addr setup_per_cpu_areas 】每CPU變量(per- cpu-variable )是一種內(nèi)核的同步機(jī)制。每CPU變量分為靜態(tài)變量和動(dòng)態(tài)變量。靜態(tài)變量用 DEFINE_PER_CPU(type, nam既定義(CPU變量name,類(lèi)型為type)。這 些靜態(tài)變量包含在段.data.percpu中。下面函數(shù)就是為每個(gè)CPU分配一部分空間用于動(dòng)態(tài)分配pe
30、r_cpu變量。并為每個(gè) CPU拷貝一份.data.percup段中的內(nèi)容。mm/percpu.cvoid _init setup_per_cpu_areas(void) unsigned long delta;unsigned int cpu;int rc;rc = pcpu_embed_first_chunk(PERCPU_MODULE_RESERVE, PERCPU_DYNAMIC_RESERVE, PAGE_SIZE, NULL, pcpu_dfl_fc_alloc, pcpu_dfl_fc_free);if (rc build_all_zonelists 】mm/page_alloc
31、.cvoid _ref build_all_zonelists(void *data)設(shè)置 current_zonelist_order ,它決定備用內(nèi)存域在 pglist_data-node_zonelists 中的排列順序 set_zonelist_order();if (system_state = SYSTEM_BOOTING) 初始化備用結(jié)點(diǎn)內(nèi)存域列表pglist_data-node_zonelists 。_build_all_zonelists(NULL);mminit_verify_zonelist(); 打印一些調(diào)試信息當(dāng)前進(jìn)程的進(jìn)程描述結(jié)構(gòu)task_struct 中有一個(gè)成員
32、 mems_allowed ,該成員是nodemask_t類(lèi)型的結(jié)構(gòu)體,這個(gè)結(jié)構(gòu)體在文件include/linux/nodemask.h 中定義如下:typedef struct DECLARE_BITMAP(bits, MAX_NUMNODES); nodemask_t;這個(gè)結(jié)構(gòu)其實(shí)就是定義了一個(gè)位域, 每個(gè)位對(duì)應(yīng)一個(gè)內(nèi)存結(jié)點(diǎn), 如果置 1 表示該節(jié)點(diǎn)內(nèi)存可用。在下面函數(shù)中將這個(gè)位域中每個(gè)位置1 。cpuset_init_current_mems_allowed(); else #ifdef CONFIG_MEMORY_HOTPLUGif (data)setup_zone_pageset(s
33、truct zone *)data);#endif如果內(nèi)核不是出于啟動(dòng)過(guò)程中,就停止CPU的運(yùn)行來(lái)初始化備用結(jié)點(diǎn)內(nèi)存域列表stop_machine(_build_all_zonelists, NULL, NULL);計(jì)算總的空閑內(nèi)存數(shù)vm_total_pages = nr_free_pagecache_pages();內(nèi)核通過(guò)標(biāo)記頁(yè)的可移動(dòng)類(lèi)型來(lái)避免產(chǎn)生過(guò)多碎片,如果可用內(nèi)存太少就標(biāo)記 page_group_by_mobility_disabled 以禁用這種反碎片機(jī)制。if (vm_total_pages build_all_zonelists_build_all_zonelists 】 s
34、tatic _init_refok int _build_all_zonelists(void *data)int nid;int cpu;遍歷每一個(gè)內(nèi)存結(jié)點(diǎn),初始化他們的備用結(jié)點(diǎn)內(nèi)存域列表for_each_online_node(nid) pg_data_t *pgdat = NODE_DATA(nid);build_zonelists(pgdat);build_zonelist_cache(pgdat);遍歷每一個(gè)CPU,初始化他們的per_cpu緩存for_each_possible_cpu(cpu) setup_pageset(&per_cpu(boot_pageset, cpu),
35、0);return 0;【 start_kernelbuild_all_zonelists_build_all_zonelistsbuild_zonelists】struct zonelist 是備用結(jié)點(diǎn)內(nèi)存域列表管理結(jié)構(gòu),該結(jié)構(gòu)在文件include/linux/mmzone.h 中定義,如下:struct zonelist 指針 zlcache_ptr 通常指向本結(jié)構(gòu)中的 zlcache 成員struct zonelist_cache *zlcache_ptr;MAX_ZONES_PER_ZONELIST示所有節(jié)點(diǎn)內(nèi)存域總和struct zoneref _zonerefsMAX_ZONES_
36、PER_ZONELIST + 1;#ifdef CONFIG_NUMAstruct zonelist_cache zlcache;#endif;struct zoneref struct zone *zone; 指向內(nèi)存域管理結(jié)構(gòu)int zone_idx; 內(nèi)存域所在結(jié)點(diǎn) id;struct zonelist_cache 存儲(chǔ)所有內(nèi)存域?qū)?yīng)結(jié)點(diǎn)號(hào)unsigned short z_to_nMAX_ZONES_PER_ZONELIST;fullzones 是所有內(nèi)存域的一個(gè)位圖,如果內(nèi)存域?qū)?yīng)位置1 ,表示這個(gè)內(nèi)存域已沒(méi)有可用內(nèi)存DECLARE_BITMAP(fullzones, MAX_ZONE
37、S_PER_ZONELIST);unsigned long last_full_zap;備用結(jié)點(diǎn)內(nèi)存域列表中內(nèi)存域排列原則是: 按分配代價(jià)由小到大排列。 在節(jié)點(diǎn)間應(yīng)當(dāng)先排列本地結(jié)點(diǎn)的內(nèi)存域后排其他結(jié)點(diǎn)內(nèi)存域, 在節(jié)點(diǎn)內(nèi)先排列高端內(nèi)存、 然后是普通內(nèi)存、 再然后是 DMA 內(nèi)存。在結(jié)點(diǎn)描述結(jié)構(gòu)中,節(jié)點(diǎn)的備用結(jié)點(diǎn)內(nèi)存域列表定義如下:typedef struct pglist_data struct zonelist node_zonelistsMAX_ZONELISTS;在多處理器系統(tǒng)中MAX_ZONELISTS定義為 2, node_zonelists0中排列本結(jié)點(diǎn)內(nèi)存域,node_zoneli
38、sts1 中排列其他備用結(jié)點(diǎn)內(nèi)存域。如果在找node_zonelists0 中不到可用內(nèi)存就到 node_zonelists1 中去分配。mm/page_alloc.cstatic void build_zonelists(pg_data_t *pgdat)int j, node, load;enum zone_type i;nodemask_t used_mask;int local_node, prev_node;struct zonelist *zonelist;int order = current_zonelist_order;初始化備用結(jié)點(diǎn)內(nèi)存域for (i = 0; i node
39、_zonelists + i;zonelist-_zonerefs0.zone = NULL;zonelist-_zonerefs0.zone_idx = 0;local_node = pgdat-node_id;load = nr_online_nodes;prev_node = local_node;nodes_clear(used_mask);memset(node_order, 0, sizeof(node_order);j = 0;找一個(gè)與結(jié)點(diǎn) pgdat 距離最近的結(jié)點(diǎn)while (node = find_next_best_node(local_node, &used_mask)
40、 = 0) int distance = node_distance(local_node, node);if (distance RECLAIM_DISTANCE)zone_reclaim_mode = 1;if (distance != node_distance(local_node, prev_node) node_loadnode = load;prev_node = node;load-;if (order = ZONELIST_ORDER_NODE)將找到的最佳結(jié)點(diǎn)內(nèi)存域排列到 pgdat 的備用內(nèi)存域列表node_zonelists1 中build_zonelists_in_n
41、ode_order(pgdat, node);elsenode_orderj+ = node; /* remember order */if (order = ZONELIST_ORDER_ZONE) /* calculate node order - i.e., DMA last! */ build_zonelists_in_zone_order(pgdat, j); 將結(jié)點(diǎn)自己的內(nèi)存域排列到自己的備用結(jié)點(diǎn)內(nèi)存域node_zonelists0 中build_thisnode_zonelists(pgdat);【 start_kernelbuild_all_zonelists_build_al
42、l_zonelistsbuild_zonelistsbuild_zonelists_in_node_order 】mm/page_alloc.cstatic void build_zonelists_in_node_order(pg_data_t *pgdat, int node) int j;struct zonelist *zonelist;函數(shù) build_thisnode_zonelists 和本函數(shù)最大的區(qū)別就在于這里取的是node_zonelists0 ,而在函數(shù) build_thisnode_zonelists 中取的是 node_zonelists1 。zonelist = &
43、pgdat-node_zonelists0;找到第一個(gè)空的位置for (j = 0; zonelist-_zonerefsj.zone != NULL; j+) ;將結(jié)點(diǎn) node 的所有內(nèi)存區(qū)域排列在, j 開(kāi)始的備用列表中j = build_zonelists_node(NODE_DATA(node), zonelist, j,MAX_NR_ZONES - 1);zonelist-_zonerefsj.zone = NULL;zonelist-_zonerefsj.zone_idx = 0;【 start_kernelbuild_all_zonelists_build_all_zoneli
44、stsbuild_zonelistsbuild_zonelists_in_node_orderbuild_zonelists_node 】mm/page_alloc.cstatic int build_zonelists_node(pg_data_t *pgdat, struct zonelist *zonelist,int nr_zones, enum zone_type zone_type) struct zone *zone;BUG_ON(zone_type = MAX_NR_ZONES);zone_type+;do 這里的 zone_type ,上層函數(shù)傳入的是MAX_NR_ZONES
45、 ,循環(huán)中做的就是將內(nèi)存域按ZONE_HIGHMEMZONE_NORMAL-ZONE_DMA勺順序排歹 U 在備用內(nèi)存歹 U 表中 zone_type-;zone = pgdat-node_zones + zone_type;if (populated_zone(zone) 函數(shù)zoneref_set_zone要做的就是用 zone和zone所在結(jié)點(diǎn)id來(lái)初始化_zonerefs。 zoneref_set_zone(zone,&zonelist-_zonerefsnr_zones+);找出整個(gè)備用列表中內(nèi)存區(qū)域類(lèi)型值最大的的內(nèi)存區(qū)域check_highest_zone(zone_type);
46、while (zone_type);return nr_zones;【 start_kernelbuild_all_zonelists_build_all_zonelistsbuild_zonelist_cache】mm/page_alloc.cstatic void build_zonelist_cache(pg_data_t *pgdat)struct zonelist *zonelist;struct zonelist_cache *zlc;struct zoneref *z;zonelist = &pgdat-node_zonelists0;讓結(jié)構(gòu)struct zonelist的zlcache_ptr指針成員指向它自己的zlcache成員zonelist-zlcache_ptr = zlc = &zonelist-zlcache;bitmap_zero(zlc-fullzones, MAX_ZONES_PER_ZONELIST);for (z = zonelist-_zonerefs; z-zone; z+)zlc-z_t
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- DB35T 2234-2024交趾黃檀容器苗培育技術(shù)規(guī)程
- 鄉(xiāng)村民宿合作協(xié)議合同模板
- 產(chǎn)品加工的委托合同
- 二手車(chē)轉(zhuǎn)讓合同模板
- 交通設(shè)施采購(gòu)及養(yǎng)護(hù)合同范本
- 親屬間房屋無(wú)償贈(zèng)與合同
- 個(gè)人農(nóng)村小產(chǎn)權(quán)房抵押融資合同
- 個(gè)體合作經(jīng)營(yíng)收益分配合同
- 產(chǎn)業(yè)協(xié)同發(fā)展合同范本
- 個(gè)人合伙創(chuàng)業(yè)合同書(shū)范本
- 北京市豐臺(tái)區(qū)2024-2025學(xué)年九年級(jí)上學(xué)期期末語(yǔ)文試題(含答案)
- 計(jì)劃供貨時(shí)間方案
- 2024年石柱土家族自治縣中醫(yī)院高層次衛(wèi)技人才招聘筆試歷年參考題庫(kù)頻考點(diǎn)附帶答案
- 2024人教新目標(biāo)(Go for it)八年級(jí)英語(yǔ)下冊(cè)【第1-10單元】全冊(cè) 知識(shí)點(diǎn)總結(jié)
- 房屋市政工程生產(chǎn)安全重大事故隱患判定標(biāo)準(zhǔn)(2024版)宣傳畫(huà)冊(cè)
- 杭州市房地產(chǎn)經(jīng)紀(jì)服務(wù)合同
- 2024年大宗貿(mào)易合作共贏協(xié)議書(shū)模板
- 初中數(shù)學(xué)教學(xué)經(jīng)驗(yàn)分享
- 新聞?dòng)浾咦C600道考試題-附標(biāo)準(zhǔn)答案
- 2024年公開(kāi)招聘人員報(bào)名資格審查表
- TSG ZF001-2006《安全閥安全技術(shù)監(jiān)察規(guī)程》
評(píng)論
0/150
提交評(píng)論