linux kernel物理内存概述(二)

目录

一、物理内存数据结构

二、设备数物理内存描述

三、物理内存映射

map_kernel

map_mem

四、zone数据结构 

zone类型


一、物理内存数据结构

0076b69f771b43959b3a05af355f3ecb.png

  • 站在处理器角度,管理物理内存的最小单位是页面。使用page数据结构描述,通常默认大小4kB,采用mem_map[]数组来存放这些page数据结构,数组与物理内存由一一对应关系。

二、设备数物理内存描述

  • 在设备树dts中,定义内存的起始地址,大小 如VExpress平台 ;qemu虚拟机内存的描述在 hw/arm/virt.c文件中
    memory@60000000{
        device_type = "memory";
        reg = <0x60000000 0x40000000>;
    }

dts文件的解析 start_kernel->setup_arch->setup_machine_fdt->early_init_dt_scan_nodes->early_init_dt_scan_memory

void __init early_init_dt_add_memory_arch(u64 base, u64 size)
{
	int in_use = 0;

	low_mem_sz = size;
	in_use = 1;
	memblock_add_node(base, size, 0, MEMBLOCK_NONE);
}

memblock_add_node添加到memblock子系统中

三、物理内存映射

在内核使用之前,需要初始化内核页表,paging_init 函数完成,主要做两次映射,map_kernel与map_mem

void __init paging_init(void)
{
	pgd_t *pgdp = pgd_set_fixmap(__pa_symbol(swapper_pg_dir));
	map_kernel(pgdp);
	map_mem(pgdp);
}

都是建立物理地址到内核虚拟地址的线性映射,但映射的地址不一样

map_kernel

  1. map_kernel映射内核镜像到内核空间的虚拟地址 该函数对内核映像的各个段分别进行映射,映射的内核空间虚拟地址为vmalloc区域; vmalloc区域的范围从0xFFFF 0000 1000 0000 到 0xFFFF 7DFF BFFF 0000
    • 代码段:从_text到_etext
    • 只读数据段:从__start_rodata到__inittext_begin;
    • 初始化代码段:
    • 初始化数据段:
    • 数据段:从_data到_end

map_mem

  1. map_mem做物理内存的线性映射。 映射三段物理内存到线性映射区。线性映射区的范围从0xFFFF 8000 0000 0000 到0xFFFF FFFF FFFF FFFF,大小为128TB 为什么把第三段物理内存单独拿出来映射? 这三段物理内存都会被映射到 不可执行 的属性,但是后续代码里把第三段映射的属性设置成 只读 ,防止后续的其他内核模块不经意地修改了代码,如CPU休眠机制。另外,第一段和第二段映射启用了连续页表属性(PTE_CONT),单独把第三段映射拎出来可以避免连续页表特性映像第三段的映射。

对页表的初始化完成后,内核可以对内存进行管理,内核采样zone管理区来管理。

0853487eb9034c139951a02afa903c15.png

四、zone数据结构 

struct zone {
	/* Read-mostly fields */

	/* zone watermarks, access with *_wmark_pages(zone) macros */
	unsigned long _watermark[NR_WMARK];//每个zone在系统启动时会计算出3个水位,最低警戒水位,低水位和高水位,在页面分配器和kswapd页面回收中用到
	unsigned long watermark_boost;

	unsigned long nr_reserved_highatomic;

	long lowmem_reserve[MAX_NR_ZONES];//防止页面分配器过度使用低端zone的内存

#ifdef CONFIG_NUMA
	int node;
#endif
	struct pglist_data	*zone_pgdat;//指向内存节点
	struct per_cpu_pages	__percpu *per_cpu_pageset;
	struct per_cpu_zonestat	__percpu *per_cpu_zonestats;

	int pageset_high_min;
	int pageset_high_max;
	int pageset_batch;

#ifndef CONFIG_SPARSEMEM
	/*
	 * Flags for a pageblock_nr_pages block. See pageblock-flags.h.
	 * In SPARSEMEM, this map is stored in struct mem_section
	 */
	unsigned long		*pageblock_flags;
#endif /* CONFIG_SPARSEMEM */

	/* zone_start_pfn == zone_start_paddr >> PAGE_SHIFT*/
       unsigned long		zone_start_pfn;//起始页帧号
        atomic_long_t		managed_pages;//被伙伴系统管理的页面数量
	unsigned long		spanned_pages;//zone包含的页面数量
	unsigned long		present_pages;//实际管理的页面数量
#if defined(CONFIG_MEMORY_HOTPLUG)
	unsigned long		present_early_pages;
#endif
#ifdef CONFIG_CMA
	unsigned long		cma_pages;
#endif

	const char		*name;
        ...
	atomic_long_t		vm_stat[NR_VM_ZONE_STAT_ITEMS];
	atomic_long_t		vm_numa_event[NR_VM_NUMA_EVENT_ITEMS];
} ____cacheline_internodealigned_in_smp;

  • zone经常被访问到,因此数据结构使用L1高速缓存对齐;CACHELINE_PADDING 为了性能,填充对齐空间

zone类型

内核的zone分为ZONEDMA、ZONEDMA32、ZONENORMAL和 ZONEHIGHMEM

  • 39
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

为了维护世界和平_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值