首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Linux内存管理之mem_map对象.md

Linux内存管理之mem_map对象.md

作者头像
233333
发布于 2023-04-21 12:17:19
发布于 2023-04-21 12:17:19
1.5K00
代码可运行
举报
运行总次数:0
代码可运行

在linux内核中,所有的物理内存都用struct page结构来描述,这些对象以数组形式存放,而这个数组的地址就是mem_map。内核以节点node为单位,每个node下的物理内存统一管理,也就是说在表示内存node的描述类型struct pglist_data中,有node_mem_map这个成员,其针对平坦型内存进行描述(CONFIG_FLAT_NODE_MEM_MAP),与此相反的是SPARSEMEM,其稀疏性内存描述。

mem_map的作用

mem_map是一个数组,存放了所有的页描述符。一个页对应一个页描述符。

mem_map的定义

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/* \linux\mm\memory.c */

#ifndef CONFIG_NEED_MULTIPLE_NODES
/* use the per-pgdat data instead for discontigmem - mbligh */
unsigned long max_mapnr;
struct page *mem_map;

EXPORT_SYMBOL(max_mapnr);
EXPORT_SYMBOL(mem_map);
#endif

dump_stack的输出

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[    0.000000] [alloc_node_mem_map 5920] .
[    0.000000] CPU: 0 PID: 0 Comm: swapper Not tainted 4.9.51-1.2 #136
[    0.000000] Hardware name: Broadcom STB (Flattened Device Tree)
[    0.000000] [<c0210710>] (unwind_backtrace) from [<c020bb54>] (show_stack+0x10/0x14)
[    0.000000] [<c020bb54>] (show_stack) from [<c04fc93c>] (dump_stack+0x84/0x98)
[    0.000000] [<c04fc93c>] (dump_stack) from [<c09b6e4c>] (alloc_node_mem_map.constprop.8+0x28/0xd0)
[    0.000000] [<c09b6e4c>] (alloc_node_mem_map.constprop.8) from [<c0e0f10c>] (free_area_init_node+0xf0/0x38c)
[    0.000000] [<c0e0f10c>] (free_area_init_node) from [<c0e065f8>] (bootmem_init+0x16c/0x1b0)
[    0.000000] [<c0e065f8>] (bootmem_init) from [<c0e08ac0>] (paging_init+0xd28/0xd90)
[    0.000000] [<c0e08ac0>] (paging_init) from [<c0e0429c>] (setup_arch+0x61c/0xc24)
[    0.000000] [<c0e0429c>] (setup_arch) from [<c0e009d0>] (start_kernel+0xb8/0x404)
[    0.000000] [<c0e009d0>] (start_kernel) from [<00008090>] (0x8090)

/*
代码调用流程:
start_kernel --> setup_arch --> paging_init --> bootmem_init --> free_area_init_node --> alloc_node_mem_map

由代码调用流程可以看出,mem_map的初始化,是在初始化node时做的。也就是说,mem_map是node下一级的一个概念。
*/

alloc_node_mem_map源码分析

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/* \linux\mm\page_alloc.c */
static void __ref alloc_node_mem_map(struct pglist_data *pgdat)
{
	unsigned long __maybe_unused start = 0;
	unsigned long __maybe_unused offset = 0;

    /* 空节点判断 */
	/* Skip empty nodes */
	if (!pgdat->node_spanned_pages)
		return;

#ifdef CONFIG_FLAT_NODE_MEM_MAP

    /* start 是起始页帧号 */
	start = pgdat->node_start_pfn & ~(MAX_ORDER_NR_PAGES - 1);
	offset = pgdat->node_start_pfn - start;

	/* ia64 gets its own node_mem_map, before this, without bootmem */
    /* 如果当前node没有分配node_mem_map, 则分配 */
	if (!pgdat->node_mem_map) {
		unsigned long size, end;
		struct page *map;

		/*
		 * The zone's endpoints aren't required to be MAX_ORDER
		 * aligned but the node_mem_map endpoints must be in order
		 * for the buddy allocator to function correctly.
		 */
        /* end 是终点页帧号 */
		end = pgdat_end_pfn(pgdat);
		end = ALIGN(end, MAX_ORDER_NR_PAGES);

		// (end - start)计算当前节点有多少个page
		size =  (end - start) * sizeof(struct page);
		map = alloc_remap(pgdat->node_id, size);
		if (!map)
			map = memblock_virt_alloc_node_nopanic(size,
							       pgdat->node_id);
		pgdat->node_mem_map = map + offset;
	}
#ifndef CONFIG_NEED_MULTIPLE_NODES
	/*
	 * With no DISCONTIG, the global mem_map is just set as node 0's
	 */
	if (pgdat == NODE_DATA(0)) {
        /* 当前节点是0号节点, 则初始化mem_map*/
		mem_map = NODE_DATA(0)->node_mem_map;
#if defined(CONFIG_HAVE_MEMBLOCK_NODE_MAP) || defined(CONFIG_FLATMEM)
		if (page_to_pfn(mem_map) != pgdat->node_start_pfn){
			mem_map -= offset;
			}
#endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
	}
#endif
#endif /* CONFIG_FLAT_NODE_MEM_MAP */
}

/*
这个函数只是给mem_map分配了内存空间,并没有初始化里面的数据
*/
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-04-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Linux-3.14.12内存管理笔记【构建内存管理框架(3)】
此处接前文,分析free_area_init_nodes()函数最后部分,分析其末尾的循环:
233333
2019/10/08
9330
Linux-3.14.12内存管理笔记【构建内存管理框架(3)】
启动期间的内存管理之bootmem_init初始化内存管理–Linux内存管理(十二)
1. 启动过程中的内存初始化 首先我们来看看start_kernel是如何初始化系统的, start_kerne定义在init/main.c?v=4.7, line 479 其代码很复杂, 我们只截取
233333
2018/12/24
3K0
五万字 | 深入理解Linux内存管理
作者简介: 程磊,一线码农,在某手机公司担任系统开发工程师,日常喜欢研究内核基本原理。 1.1 内存管理的意义 1.2 原始内存管理 1.3 分段内存管理 1.4 分页内存管理 1.5 内存管理的目标 1.6 Linux内存管理体系 2.1 物理内存节点 2.2 物理内存区域 2.3 物理内存页面 2.4 物理内存模型 2.5 三级区划关系 3.1 Buddy System 3.1.1 伙伴系统的内存来源 3.1.2 伙伴系统的管理数据结构 3.1.3 伙伴系统的算法逻辑 3.1.4 伙伴系统的接口 3.1
刘盼
2022/08/26
4.5K0
五万字 | 深入理解Linux内存管理
启动期间的内存管理之初始化过程概述----Linux内存管理(九)
在内存管理的上下文中, 初始化(initialization)可以有多种含义. 在许多CPU上, 必须显式设置适用于Linux内核的内存模型. 例如在x86_32上需要切换到保护模式, 然后内核才能检测到可用内存和寄存器.
233333
2018/12/21
2.2K0
Linux内存描述之内存节点node--Linux内存管理(二)
这点前面是说的很明白了, NUMA结构下, 每个处理器CPU与一个本地内存直接相连, 而不同处理器之前则通过总线进行进一步的连接, 因此相对于任何一个CPU访问本地内存的速度比访问远程内存的速度要快
233333
2018/11/21
8.9K0
一文掌握 Linux 内存管理
作者:dengxuanshi,腾讯 IEG 后台开发工程师 以下源代码来自 linux-5.10.3 内核代码,主要以 x86-32 为例。 Linux 内存管理是一个很复杂的“工程”,它不仅仅是对物理内存的管理,也涉及到虚拟内存管理、内存交换和内存回收等 物理内存的探测 Linux 内核通过 detect_memory()函数实现对物理内存的探测 void detect_memory(void) {  detect_memory_e820();  detect_memory_e801();  d
腾讯技术工程官方号
2021/05/13
2.4K0
启动期间的内存管理之引导分配器bootmem--Linux内存管理(十)
在内存管理的上下文中, 初始化(initialization)可以有多种含义. 在许多CPU上, 必须显式设置适用于Linux内核的内存模型. 例如在x86_32上需要切换到保护模式, 然后内核才能检测到可用内存和寄存器.
233333
2018/12/21
1.4K0
内存管理专栏 | 之内存管理架构
一、内存管理架构 二、虚拟地址空间布局架构 三、物理内存体系架构 四、内存结构 五、内存模型 六、虚拟地址和物理地址的转换 七、内存映射原理分析 一、内存管理架构 内存管理子系统架构可以分为:用户空间、内核空间及硬件部分3个层面,具体结构如下所示:1、用户空间:应用程序使用malloc()申请内存资源/free()释放内存资源。2、内核空间:内核总是驻留在内存中,是操作系统的一部分。内核空间为内核保留,不允许应用程序读写该区域的内容或直接调用内核代码定义的函数。3、硬件:处理器包含一个内存管理单元(Memo
刘盼
2022/09/02
1.7K0
内存管理专栏 | 之内存管理架构
Buddy 内存管理机制(上)
内存是计算机系统中最重要的核心资源之一,Buddy 系统是 Linux 最底层的内存管理机制,它使用 Page 粒度来管理内存。通常情况下一个 Page 的大小为 4K,在 Buddy 系统中分配、释放、回收的最小单位都是 Page。
刘盼
2023/01/05
1.9K0
Buddy 内存管理机制(上)
Linux-3.14.12内存管理笔记【构建内存管理框架(2)】
前面构建内存管理框架,已经将内存管理node节点设置完毕,接下来将是管理区和页面管理的构建。此处代码实现主要在于setup_arch()下的一处钩子:x86_init.paging.pagetable_init()。据前面分析可知x86_init结构体内该钩子实际上挂接的是native_pagetable_init()函数。
233333
2019/10/08
9780
Linux-3.14.12内存管理笔记【构建内存管理框架(2)】
一步一图带你深入理解 Linux 物理内存管理
在上篇文章 《深入理解 Linux 虚拟内存管理》 中,笔者分别从进程用户态和内核态的角度详细深入地为大家介绍了 Linux 内核如何对进程虚拟内存空间进行布局以及管理的相关实现。在我们深入理解了虚拟内存之后,那么何不顺带着也探秘一下物理内存的管理呢?
bin的技术小屋
2023/10/30
1.9K0
一步一图带你深入理解 Linux 物理内存管理
Linux内存初始化(下)
我们接着看linux初始化内存的下半部分,等内存初始化后就可以进入真正的内存管理了,初始化我总结了一下,大体分为三步:
刘盼
2020/06/29
3.4K0
内存管理相关数据结构之pg_data_t
若系统节点多余一个,则内核会维护一个位图用于提供每个节点的状态信息,状态信息为一个enum。定义如下:
233333
2020/04/13
8560
Linux-3.14.12内存管理笔记【构建内存管理框架(1)】
传统的计算机结构中,整个物理内存都是一条线上的,CPU访问整个内存空间所需要的时间都是相同的。这种内存结构被称之为UMA(Uniform Memory Architecture,一致存储结构)。但是随着计算机的发展,一些新型的服务器结构中,尤其是多CPU的情况下,物理内存空间的访问就难以控制所需的时间相同了。在多CPU的环境下,系统只有一条总线,有多个CPU都链接到上面,而且每个CPU都有自己本地的物理内存空间,但是也可以通过总线去访问别的CPU物理内存空间,同时也存在着一些多CPU都可以共同访问的公共物理内存空间。于是乎这就出现了一个新的情况,由于各种物理内存空间所处的位置不同,于是访问它们的时间长短也就各异,没法保证一致。对于这种情况的内存结构,被称之为NUMA(Non-Uniform Memory Architecture,非一致存储结构)。事实上也没有完全的UMA,比如常见的单CPU电脑,RAM、ROM等物理存储空间的访问时间并非一致的,只是纯粹对RAM而言,是UMA的。此外还有一种称之为MPP的结构(Massive Parallel Processing,大规模并行处理系统),是由多个SMP服务器通过一定的节点互联网络进行连接,协同工作,完成相同的任务。从外界使用者看来,它是一个服务器系统。
233333
2019/10/08
9220
Linux-3.14.12内存管理笔记【构建内存管理框架(1)】
【Linux 内核 内存管理】Linux 内核内存布局 ④ ( ARM64 架构体系内存分布 | 内核启动源码 start_kernel | 内存初始化 mm_init | mem_init )
① 内核空间 ( Kernel Space ) : 寻址范围 0x FFFF 0000 0000 0000 ~ 0x FFFF FFFF FFFF FFFF ;
韩曙亮
2023/03/30
7.7K0
【Linux 内核 内存管理】Linux 内核内存布局 ④ ( ARM64 架构体系内存分布 | 内核启动源码 start_kernel | 内存初始化 mm_init | mem_init )
Linux-3.14.12内存管理笔记【伙伴管理算法(2)】
具体的算法初始化则回到start_kernel()函数接着往下走,下一个函数是mm_init():
233333
2019/10/08
1K0
【Linux 内核 内存管理】物理内存组织结构 ③ ( 内存管理系统三级结构 | 内存节点描述 | 内存节点 pglist_data 结构体 | pglist_data 结构体源码 )
Linux 内核中 , 内存节点 ( Node ) 是 " 内存管理 " 的 最顶层的结构 , 下层分别是 区域 和 页 ;
韩曙亮
2023/03/30
1.9K0
【Linux 内核 内存管理】物理内存组织结构 ③ ( 内存管理系统三级结构 | 内存节点描述 | 内存节点 pglist_data 结构体 | pglist_data 结构体源码 )
【Linux 内核 内存管理】物理内存组织结构 ⑥ ( 物理页 page 简介 | 物理页 page 与 MMU 内存管理单元 | 内存节点 pglist_data 与 物理页 page 联系 )
在 Linux 内核中 , MMU 内存管理单元 , 主要作用是 将 " 虚拟地址 " 映射到 真实的 " 物理地址 " 中 ,
韩曙亮
2023/03/30
7.2K0
【Linux 内核 内存管理】物理内存组织结构 ⑥ ( 物理页 page 简介 | 物理页 page 与 MMU 内存管理单元 | 内存节点 pglist_data 与 物理页 page 联系 )
Linux内存描述之内存区域zone--Linux内存管理(三)
为了支持NUMA模型,也即CPU对不同内存单元的访问时间可能不同,此时系统的物理内存被划分为几个节点(node), 一个node对应一个内存簇bank,即每个内存簇被认为是一个节点
233333
2018/12/17
10.4K1
Linux内存描述之内存区域zone--Linux内存管理(三)
启动期间的内存管理之build_zonelists初始化备用内存域列表zonelists--Linux内存管理(十三)
我们之前讲了在memblock完成之后, 内存初始化开始进入第二阶段, 第二阶段是一个漫长的过程, 它执行了一系列复杂的操作, 从体系结构相关信息的初始化慢慢向上层展开, 其主要执行了如下操作
233333
2018/12/24
2.4K0
推荐阅读
Linux-3.14.12内存管理笔记【构建内存管理框架(3)】
9330
启动期间的内存管理之bootmem_init初始化内存管理–Linux内存管理(十二)
3K0
五万字 | 深入理解Linux内存管理
4.5K0
启动期间的内存管理之初始化过程概述----Linux内存管理(九)
2.2K0
Linux内存描述之内存节点node--Linux内存管理(二)
8.9K0
一文掌握 Linux 内存管理
2.4K0
启动期间的内存管理之引导分配器bootmem--Linux内存管理(十)
1.4K0
内存管理专栏 | 之内存管理架构
1.7K0
Buddy 内存管理机制(上)
1.9K0
Linux-3.14.12内存管理笔记【构建内存管理框架(2)】
9780
一步一图带你深入理解 Linux 物理内存管理
1.9K0
Linux内存初始化(下)
3.4K0
内存管理相关数据结构之pg_data_t
8560
Linux-3.14.12内存管理笔记【构建内存管理框架(1)】
9220
【Linux 内核 内存管理】Linux 内核内存布局 ④ ( ARM64 架构体系内存分布 | 内核启动源码 start_kernel | 内存初始化 mm_init | mem_init )
7.7K0
Linux-3.14.12内存管理笔记【伙伴管理算法(2)】
1K0
【Linux 内核 内存管理】物理内存组织结构 ③ ( 内存管理系统三级结构 | 内存节点描述 | 内存节点 pglist_data 结构体 | pglist_data 结构体源码 )
1.9K0
【Linux 内核 内存管理】物理内存组织结构 ⑥ ( 物理页 page 简介 | 物理页 page 与 MMU 内存管理单元 | 内存节点 pglist_data 与 物理页 page 联系 )
7.2K0
Linux内存描述之内存区域zone--Linux内存管理(三)
10.4K1
启动期间的内存管理之build_zonelists初始化备用内存域列表zonelists--Linux内存管理(十三)
2.4K0
相关推荐
Linux-3.14.12内存管理笔记【构建内存管理框架(3)】
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验