U盘PE| w764位旗舰版下载 | U盘装win7系统 | U盘启动 |win7pe | win10下载 |加入收藏土豆PE官网U盘PE,U盘装win7系统,win7pe,U盘启动,U盘装系统,w764位旗舰版下载站!
当前位置:主页 > 帮助中心 > bios设置U盘启动 >

启动伙伴系统

来源:http://www.tudoupe.com时间:2022-04-13

众所周知,伙伴系统是Linux记忆管理的核心。事实上 当Linux第一次出现时记忆管理已在进行中。事实并非如此 管理界的朋友在内核中,用于控制物理内存的分布器包括:

实时物理内存管理

不连续vmallalloc 分配器的物理内存管理

微小物理内存管理板板分配器

特殊物理内存管理kmapper

推进阶段块初始化的物理内存管理

在该系统启动阶段,将使用一个靴子经销商和一个混凝土经销商。该撒布器打算在启动阶段使用。一个靴子经销商负责节点节点节点上的所有记忆。努马建筑中的若干节点有一个以上的靴子。为了保存,它们与数据列表链表相连。合作伙伴系统的启动是 将Bootmem维护的所有物理页面框 发布到合作伙伴系统中。本章的主要重点是分析。在整个过程中 如何让靴子成为你的好友

一,从梅姆尼特开始
void __init mem_init(void)
{
#ifdef CONFIG_HAVE_TCM
/* These pointers are filled in on TCM detection */
extern u32 dtcm_end;
extern u32 itcm_end;
#endif

set_max_mapnr(pfn_to_page(max_pfn) - mem_map);                                   --------------(1)

/* this will put all unused low memory onto the freelists */
free_unused_memmap();                                                            --------------(2)
free_all_bootmem();                                                              --------------(3)

#ifdef CONFIG_SA1111
/* now that our DMA memory is actually so designated, we can free it */
free_reserved_area(__va(PHYS_OFFSET), swapper_pg_dir, -1, NULL);
#endif

free_highpages();                                                               --------------(4)

mem_init_print_info(NULL);                                                      --------------(5)

#define MLK(b, t) b, t, ((t) - (b)) >> 10
#define MLM(b, t) b, t, ((t) - (b)) >> 20
#define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), SZ_1K)

pr_notice("Virtual kernel memory layout:n"
"    vector  : 0x%08lx - 0x%08lx   (%4ld kB)n"
#ifdef CONFIG_HAVE_TCM
"    DTCM    : 0x%08lx - 0x%08lx   (%4ld kB)n"
"    ITCM    : 0x%08lx - 0x%08lx   (%4ld kB)n"
#endif
"    fixmap  : 0x%08lx - 0x%08lx   (%4ld kB)n"
"    vmalloc : 0x%08lx - 0x%08lx   (%4ld MB)n"
"    lowmem  : 0x%08lx - 0x%08lx   (%4ld MB)n"
#ifdef CONFIG_HIGHMEM
"    pkmap   : 0x%08lx - 0x%08lx   (%4ld MB)n"
#endif
#ifdef CONFIG_MODULES
"    modules : 0x%08lx - 0x%08lx   (%4ld MB)n"
#endif
"      .text : 0x%p" " - 0x%p" "   (%4td kB)n"
"      .init : 0x%p" " - 0x%p" "   (%4td kB)n"
"      .data : 0x%p" " - 0x%p" "   (%4td kB)n"
"       .bss : 0x%p" " - 0x%p" "   (%4td kB)n",

MLK(UL(CONFIG_VECTORS_BASE), UL(CONFIG_VECTORS_BASE) +
(PAGE_SIZE)),
#ifdef CONFIG_HAVE_TCM
MLK(DTCM_OFFSET, (unsigned long) dtcm_end),
MLK(ITCM_OFFSET, (unsigned long) itcm_end),
#endif
MLK(FIXADDR_START, FIXADDR_END),
MLM(VMALLOC_START, VMALLOC_END),
MLM(PAGE_OFFSET, (unsigned long)high_memory),
#ifdef CONFIG_HIGHMEM
MLM(PKMAP_BASE, (PKMAP_BASE) + (LAST_PKMAP) *
(PAGE_SIZE)),
#endif
#ifdef CONFIG_MODULES
MLM(MODULES_VADDR, MODULES_END),
#endif

MLK_ROUNDUP(_text, _etext),
MLK_ROUNDUP(__init_begin, __init_end),
MLK_ROUNDUP(_sdata, _edata),
MLK_ROUNDUP(__bss_start, __bss_stop));

#undef MLK
#undef MLM
#undef MLK_ROUNDUP

/*
* Check boundaries twice: Some fundamental inconsistencies can
* be detected at build time already.
*/
#ifdef CONFIG_MMU
BUILD_BUG_ON(TASK_SIZE                > MODULES_VADDR);
BUG_ON(TASK_SIZE                 > MODULES_VADDR);
#endif

#ifdef CONFIG_HIGHMEM
BUILD_BUG_ON(PKMAP_BASE + LAST_PKMAP * PAGE_SIZE > PAGE_OFFSET);
BUG_ON(PKMAP_BASE + LAST_PKMAP * PAGE_SIZE    > PAGE_OFFSET);
#endif

if (PAGE_SIZE >= 16384 && get_num_physpages() <= 128) {
extern int sysctl_overcommit_memory;
/*
* On a machine this small we won't get
* anywhere without overcommit, so turn
* it on by default.
*/
sysctl_overcommit_memory = OVERCOMMIT_ALWAYS;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
函数设置_max_mapnr () 用于确定最大值_mapnr, 这实际上指物理内存大小 。

在页面管理像素图中, Free_unused_memmap 登记任何物理上不存在“无关”的页面(洞) 。

Free_all_bootmem 函数释放页面管理像素图, 允许伙伴系统管理空白页面 。

Free_highpage为伙伴系统提供了高端内存位置,以便管理空白页面。

Mem_init_print_info () 输出出多个内核图像段, 主要是完整内核空间的虚拟地图, 并在我们目前使用的开发委员会上提供以下打印信息 :

在这里插入图片描述

2. 空闲内存释放
函数 Free_unused_memmap () 和 free_all_bootm () 向伙伴系统释放自由内存, 从而释放阻塞自由内存和启动内存 。

static void __init free_unused_memmap(void)
{
unsigned long start, prev_end = 0;
struct memblock_region *reg;

/*
* This relies on each bank being in address order.
* The banks are sorted previously in bootmem_init().
*/
for_each_memblock(memory, reg) {
start = memblock_region_memory_base_pfn(reg);

#ifdef CONFIG_SPARSEMEM
start = min(start,
ALIGN(prev_end, PAGES_PER_SECTION));
#else
start = round_down(start, MAX_ORDER_NR_PAGES);
#endif

if (prev_end && prev_end < start)
free_memmap(prev_end, start);

prev_end = ALIGN(memblock_region_memory_end_pfn(reg),
MAX_ORDER_NR_PAGES);
}

#ifdef CONFIG_SPARSEMEM
if (!IS_ALIGNED(prev_end, PAGES_PER_SECTION))
free_memmap(prev_end,
ALIGN(prev_end, PAGES_PER_SECTION));
#endif
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
这都是为了获得Memblock的记忆对于IMX开发板,值为 0x800 。获取合适的 0x800 启动 。因此,我不符合免费地图的要求。之后,前置V_end值为 0x100。开发委员会只有一个记忆。因此,Memblock没有相应的自由记忆释放。从记忆节点的开始到结束, 系统会指派 mem_ map 。这一解决空间可能存在差距。此空地址指已解开的页面数据结构 。如下图所示

在这里插入图片描述

让我们看看Bootm的释放情况。

typedef struct bootmem_data {
unsigned long node_min_pfn;
unsigned long node_low_pfn;
void *node_bootmem_map;
unsigned long last_end_off;
unsigned long hint_idx;
struct list_head list;
} bootmem_data_t;
1
2
3
4
5
6
7
8
结构的成员 含义
NOde_min_ pfn NOde_ min_ pfn NOde_ min_ pfn
NOde_ low_pfn
位图内存由节点_bootmem_map 引用 。Zone_HIGHMEM前所有节点中的页面在此有一个单个条目 。当您需要分配内存时,要扫描一个空页面框。空闲的内存也将占用座位。然而,空白的内存应标为指定符号。
最后_ 结束_ 结束
hint_idx
结构表 bdata_ list 的链条列表
节点- bootmem_ map的位图是导火线经销商的核心。这些节点的每一页当需要分配时,我要扫描这个位图 然后再扫描一遍在那之后,你将得到一个实际的页面框,以供分发。它通常从一开始就向后分布。合作伙伴系统的启动将基于这个位图。这是我第一次把像素图页面 归还给合作伙伴系统在启动过程中,已经分配的网页将不再放回伙伴系统。然而,在行动期间,可以释放伙伴系统。关于混凝土支持的内核,内核设置为CONFIG_NO_BOOMTMEM,在mm/nobootmem.com.c/中实施。具体实现如下:

unsigned long __init free_all_bootmem(void)
{
unsigned long pages;

reset_all_zones_managed_pages();                                               ---------------(1)

pages = free_low_memory_core_early();                                          ---------------(2)
totalram_pages += pages;

return pages;
}
1
2
3
4
5
6
7
8
9
10
11
将所有节点的管理页面属性设置为 0。在启动时,此函数只被调用一次。
将所有页面框从 bdata 启动存储区块释放到页面框经销商, 计算所有存储页数据, 存储在总计 ram_ pages 中, 并返回通过所有启动存储区块释放的需要释放的页面总数 。
继续调查免费的_low_morary_core_EARLY;主要成绩如下:

static unsigned long __init free_low_memory_core_early(void)
{
unsigned long count = 0;
phys_addr_t start, end;
u64 i;

memblock_clear_hotplug(0, -1);

for_each_reserved_mem_region(i, &start, &end)
reserve_bootmem_region(start, end);

/*
* We need to use NUMA_NO_NODE instead of NODE_DATA(0)->node_id
*  because in some case like Node0 doesn't have RAM installed
*  low ram will be on Node1
*/
for_each_free_mem_range(i, NUMA_NO_NODE, MEMBLOCK_NONE, &start, &end,
NULL)
count += __free_memory_core(start, end);

return count;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
保存类型区域,页面属性为每个区域保留,对于Imx,这个保留区域是

[root@qemu_imx6ul:~]# cat /sys/kernel/debug/memblock/reserved
0: 0x0000000080003000..0x0000000080007fff
1: 0x0000000080200000..0x00000000810e8eeb
2: 0x0000000088000000..0x0000000088014303
3: 0x000000008bad3000..0x000000008bb40fff
4: 0x000000008bb413c0..0x000000008bb433bf
5: 0x000000008bb433f4..0x000000008bffefff
6: 0x000000008bfff740..0x000000008bfff77b
7: 0x000000008bfff780..0x000000008bfff7bb
8: 0x000000008bfff7c0..0x000000008bfff837
9: 0x000000008bfff840..0x000000008bfff843
10: 0x000000008bfff880..0x000000008bfff883
11: 0x000000008bfff8c0..0x000000008bfff8c3
12: 0x000000008bfff900..0x000000008bfff903
13: 0x000000008bfff940..0x000000008bfff9a1
14: 0x000000008bfff9c0..0x000000008bfffa21
15: 0x000000008bfffa40..0x000000008bfffaa1
16: 0x000000008bfffaac..0x000000008bfffac6
17: 0x000000008bfffac8..0x000000008bfffae2
18: 0x000000008bfffae4..0x000000008bfffb5e
19: 0x000000008bfffb60..0x000000008bfffb7a
20: 0x000000008bfffb7c..0x000000008bfffb96
21: 0x000000008bfffb98..0x000000008bfffbb2
22: 0x000000008bfffbb4..0x000000008bfffbce
23: 0x000000008bfffbd0..0x000000008bfffbea
24: 0x000000008bfffbec..0x000000008bfffc06
25: 0x000000008bfffc08..0x000000008bfffc22
26: 0x000000008bfffc24..0x000000008bfffccc
27: 0x000000008bfffcd0..0x000000008bfffce8
28: 0x000000008bfffcec..0x000000008bfffd04
29: 0x000000008bfffd08..0x000000008bfffd20
30: 0x000000008bfffd24..0x000000008bfffd3c
31: 0x000000008bfffd40..0x000000008bfffd5c
32: 0x000000008bfffd60..0x000000008bfffd7c
33: 0x000000008bfffd80..0x000000008bfffdc7
34: 0x000000008bfffdd8..0x000000009fffffff
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
整个中间区 。 记忆, 但不在中间区 。 保留区 。 然后删除保留页属性 。

下面是如何缩小页面的注意力 以完成预设的设置。其代码如下,主要是清空各页的page->flags的PG_reserved位,保留部分的页面标签是 PG_reserved 。并加入到page->lru链表中。

void __meminit reserve_bootmem_region(phys_addr_t start, phys_addr_t end)
{
unsigned long start_pfn = PFN_DOWN(start);
unsigned long end_pfn = PFN_UP(end);

for (; start_pfn < end_pfn; start_pfn++) {
if (pfn_valid(start_pfn)) {
struct page *page = pfn_to_page(start_pfn);

init_reserved_page(start_pfn);

/* Avoid false-positive PageTail() */
INIT_LIST_HEAD(&page->lru);

SetPageReserved(page);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
让我们来看看- free_ memory_ core points, 大部分都是在混凝土上。 memory, 但不在混凝土上。 保留区中的区域, 对于 Ix 开发委员会, 信息如下:

0: 0x0000000080000000 .. 0x0000000080003000
1: 0x0000000080008000 .. 0x0000000080200000
2: 0x00000000810e9000 .. 0x0000000080200000
3: 0x0000000088015000 .. 0x000000008bad3000
4:0x000000008bb41000 .. 0x000000008bb41000
5: 0x000000008bfff000 .. 0x000000008bfff000
1
2
3
4
5
6
static unsigned long __init __free_memory_core(phys_addr_t start,
phys_addr_t end)
{
unsigned long start_pfn = PFN_UP(start);
unsigned long end_pfn = min_t(unsigned long,
PFN_DOWN(end), max_low_pfn);

if (start_pfn > end_pfn)
return 0;
__free_pages_memory(start_pfn, end_pfn);

return end_pfn - start_pfn;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
核心的__free_pages_memory函数,该函数以顺序为单位释放页,清空各页的PG_reserved位,设置pgae->count为0后,然后调用__free_pages,代码实现为

void __free_pages(struct page *page, unsigned int order)
{
if (put_page_testzero(page)) {
if (order == 0)
free_hot_cold_page(page, false);
else
__free_pages_ok(page, order);
}
}
1
2
3
4
5
6
7
8
9
首先检查页次数page->_refcount减1后的值是否为0

零时,请拨Free_hot_cold_page或呼_free_pages_ok以连续单元发布页面。

程序更为复杂,包括伙伴系统的若干算法,留下一个问题有待回答,然后进行深入审查。

3. 高端内存释放
static void __init free_highpages(void)
{
#ifdef CONFIG_HIGHMEM
unsigned long max_low = max_low_pfn;
struct memblock_region *mem, *res;

/* set highmem page free */
for_each_memblock(memory, mem) {
unsigned long start = memblock_region_memory_base_pfn(mem);
unsigned long end = memblock_region_memory_end_pfn(mem);
/* Ignore complete lowmem entries */
if (end <= max_low)
continue;

if (memblock_is_nomap(mem))
continue;

/* Truncate partial highmem entries */
if (start < max_low)
start = max_low;

/* Find and exclude any reserved regions */
for_each_memblock(reserved, res) {
unsigned long res_start, res_end;

res_start = memblock_region_reserved_base_pfn(res);
res_end = memblock_region_reserved_end_pfn(res);

if (res_end < start)
continue;
if (res_start < start)
res_start = start;
if (res_start > end)
res_start = end;
if (res_end > end)
res_end = end;
if (res_start != start)
free_area_high(start, res_start);
start = res_end;
if (start == end)
break;
}

/* And now free anything which remains */
if (start < end)
free_area_high(start, end);
}
#endif
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
存在高端内存时,代码寻找高端内存的开始和结束框架。下一步,为了允许伙伴系统管理空白页面,请使用自由区域高函数。内部,自由区域高函数引用自由页面函数。空白页和通用内存位置作为一组放入伙伴系统。

4. 总结
本章的 mem_ init () 函数以内存经销商mmblock 和 Bootmem 结尾 。Bootmem和Memblock的空白页按顺序排列。结构化伙伴系统将为Linux的记忆经销商提供空白页板。

Copyright © 2012-2014 Www.tudoupe.Com. 土豆启动 版权所有 意见建议:tdsky@tudoupe.com

土豆系统,土豆PE,win7系统下载,win7 64位旗舰版下载,u盘启动,u盘装系统,win10下载,win10正式版下载,win10 RTM正式版下载,win8下载,电脑蓝屏,IE11修复,网络受限,4K对齐,双系统,隐藏分区,系统安装不了,U盘装系统,笔记本装系统,台式机装系统,diskgenius运用,GHSOT装系统,U盘修复,U盘技巧,U盘速度,U盘不能格式化,U盘复制发生错误,U盘加密,U盘选购,开机黑屏,蓝屏,进不了系统,上不了网,打不开程序,点击无反应,系统设置,PE个性化,PE添加网络,PE维护系统

点击这里给我发消息