内存管理篇-03物理内存管理-32位

news2024/9/22 1:26:52

正片从现在开始了。

1.结构体关联

        当DDR初始化后,整个内存就可以访问了。但是需要合理的管理,防止内存碎片以及安全相关的问题。因此需要对物理内存进行严格的管理。

        物理内存分为:页, 分区,内存节点。DMA需要连续的内存,因此需要单独的内存。(大概16MB)。

物理页帧结构体,每个物理块都通过一个struct page描述。

  • 定义头文件:include/linux/mm_type.h 描述不同类型的页。
  • 每个物理页帧page frame 都使用结构体page表示。
  • 结构体struct page核心成员分析。
  • 思考
    • 物理页帧和struct page之间的关系:通过page结构体找到对应的页帧号。因为page结构体是线性存放。
    • 不同类型的page分别有什么作用。
    • 物理页帧号pfn 和物理地址的关系:通过页帧号找到对应的page结构体。
    • struct page存储在哪里。page本身是需要占用内存的,每个页空间,都会用page结构体描述它。比如说系统总共有1024个page,那么就需要1024个page结构体来描述整个系统内存。此时需要类似struct page mm_map[1024]的信息来保存。
    • 全局变量:mem_map。它保存了系统所有page的地址,因为系统所有的page都有对应的地址,需要这么一块内存指向它。

         假设物理页帧号是0x10240000,0x10250000,0x10260000 ... 0x20470000, 如果用arr[1024]数组保存它,arr[0] = 0x10240000,arr[1] = 0x10250000, ... arr[1023] = 0x20470000。因此物理页帧号对应存放的地址:__page_to_pfn(page) ==> (page - mem_map)

示例1:如果已知page,要去求pfn

struct page my_page=mem_map[22]
my_page_pfn = (my_page - mem_map) + ARCH_PFN_OFFSET

示例2:如果已知某个pfn,去求page

my_pfn = 0x10250000
struct page my_page = mem_map + (pfn - ARCH_FPN_OFFSET)

2.内存页:page结构体

struct page 是 Linux 内核中的一个重要数据结构,用于表示和管理物理内存页。struct page 结构体的设计非常复杂,因为它必须能够适应多种不同的用途,包括但不限于页缓存、匿名页面、页表管理、内存池管理、内存控制组等。为了支持这些多样的用途,struct page 中包含了多个 union 联合体。

unsigned long flags 这个成员包含了一些标志位,用于表示页面的状态,如是否可写、是否脏、是否被锁定等。

struct page {
	unsigned long flags; /* 用于表示页面的状态,如是否可写、是否脏、是否被锁定等。
	/*
	 * Five words (20/40 bytes) are available in this union.
	 * WARNING: bit 0 of the first word is used for PageTail(). That
	 * means the other users of this union MUST NOT use the bit to
	 * avoid collision and false-positive PageTail().
	 */
	union {
		struct {	/* Page cache and anonymous pages */
			/**
			 * @lru: Pageout list, eg. active_list protected by
			 * pgdat->lru_lock.  Sometimes used as a generic list
			 * by the page owner.
			 */
			struct list_head lru;
			/* See page-flags.h for PAGE_MAPPING_FLAGS */
			struct address_space *mapping;
			pgoff_t index;		/* Our offset within mapping. */
			/**
			 * @private: Mapping-private opaque data.
			 * Usually used for buffer_heads if PagePrivate.
			 * Used for swp_entry_t if PageSwapCache.
			 * Indicates order in the buddy system if PageBuddy.
			 */
			unsigned long private;
		};
		struct {	/* page_pool used by netstack */
			/**
			 * @dma_addr: might require a 64-bit value on
			 * 32-bit architectures.
			 */
			unsigned long dma_addr[2];
		};
		struct {	/* slab, slob and slub */
			union {
				struct list_head slab_list;
				struct {	/* Partial pages */
					struct page *next;
#ifdef CONFIG_64BIT
					int pages;	/* Nr of pages left */
					int pobjects;	/* Approximate count */
#else
					short int pages;
					short int pobjects;
#endif
				};
			};
			struct kmem_cache *slab_cache; /* not slob */
			/* Double-word boundary */
			void *freelist;		/* first free object */
			union {
				void *s_mem;	/* slab: first object */
				unsigned long counters;		/* SLUB */
				struct {			/* SLUB */
					unsigned inuse:16;
					unsigned objects:15;
					unsigned frozen:1;
				};
			};
		};
		struct {	/* Tail pages of compound page */
			unsigned long compound_head;	/* Bit zero is set */

			/* First tail page only */
			unsigned char compound_dtor;
			unsigned char compound_order;
			atomic_t compound_mapcount;
			unsigned int compound_nr; /* 1 << compound_order */
		};
		struct {	/* Second tail page of compound page */
			unsigned long _compound_pad_1;	/* compound_head */
			atomic_t hpage_pinned_refcount;
			/* For both global and memcg */
			struct list_head deferred_list;
		};
		struct {	/* Page table pages */
			unsigned long _pt_pad_1;	/* compound_head */
			pgtable_t pmd_huge_pte; /* protected by page->ptl */
			unsigned long _pt_pad_2;	/* mapping */
			union {
				struct mm_struct *pt_mm; /* x86 pgds only */
				atomic_t pt_frag_refcount; /* powerpc */
			};
#if ALLOC_SPLIT_PTLOCKS
			spinlock_t *ptl;
#else
			spinlock_t ptl;
#endif
		};
		struct {	/* ZONE_DEVICE pages */
			/** @pgmap: Points to the hosting device page map. */
			struct dev_pagemap *pgmap;
			void *zone_device_data;
			/*
			 * ZONE_DEVICE private pages are counted as being
			 * mapped so the next 3 words hold the mapping, index,
			 * and private fields from the source anonymous or
			 * page cache page while the page is migrated to device
			 * private memory.
			 * ZONE_DEVICE MEMORY_DEVICE_FS_DAX pages also
			 * use the mapping, index, and private fields when
			 * pmem backed DAX files are mapped.
			 */
		};

		/** @rcu_head: You can use this to free a page by RCU. */
		struct rcu_head rcu_head;
	};

	union {		/* This union is 4 bytes in size. */
		/*
		 * If the page can be mapped to userspace, encodes the number
		 * of times this page is referenced by a page table.
		 */
		atomic_t _mapcount;

		/*
		 * If the page is neither PageSlab nor mappable to userspace,
		 * the value stored here may help determine what this page
		 * is used for.  See page-flags.h for a list of page types
		 * which are currently stored here.
		 */
		unsigned int page_type;

		unsigned int active;		/* SLAB */
		int units;			/* SLOB */
	};

	/* Usage count. *DO NOT USE DIRECTLY*. See page_ref.h */
	atomic_t _refcount;

#ifdef CONFIG_MEMCG
	union {
		struct mem_cgroup *mem_cgroup;
		struct obj_cgroup **obj_cgroups;
	};
#endif

	/*
	 * On machines where all RAM is mapped into kernel address space,
	 * we can simply calculate the virtual address. On machines with
	 * highmem some memory is mapped into kernel virtual memory
	 * dynamically, so we need a place to store that address.
	 * Note that this field could be 16 bits on x86 ... ;)
	 *
	 * Architectures with slow multiplication can define
	 * WANT_PAGE_VIRTUAL in asm/page.h
	 */
#if defined(WANT_PAGE_VIRTUAL)
	void *virtual;			/* Kernel virtual address (NULL if
					   not kmapped, ie. highmem) */
#endif /* WANT_PAGE_VIRTUAL */

#ifdef LAST_CPUPID_NOT_IN_PAGE_FLAGS
	int _last_cpupid;
#endif
} _struct_page_alignment;

3.内存区域:struct zone

  • 定义:mmzone.h
  • 重要结构体成员:_watermark watermark_boost zone_start_pfn present_pages free_area
    • zone_start_pfn 起始页帧号 present_pages 该zone当前有多少个页
    • lowmem_reseve备用内存,怎么理解??
  • 初始化:zone_sizes_init

zone_type

enum zone_type {
#ifdef CONFIG_ZONE_DMA
	ZONE_DMA,
#endif
#ifdef CONFIG_ZONE_DMA32
	ZONE_DMA32,
#endif
	ZONE_NORMAL,
#ifdef CONFIG_HIGHMEM
	ZONE_HIGHMEM,
#endif
	ZONE_MOVABLE,
#ifdef CONFIG_ZONE_DEVICE
	ZONE_DEVICE,
#endif
	__MAX_NR_ZONES
};

struct zone

struct zone {
	/* Read-mostly fields */

	/* zone watermarks, access with *_wmark_pages(zone) macros */
	unsigned long _watermark[NR_WMARK]; 表示该内存区域的水印阈值,用于内存管理策略。
	unsigned long watermark_boost; 用于提高水印阈值的临时值。
	unsigned long nr_reserved_highatomic; 表示为高原子操作预留的页面数量。
	long lowmem_reserve[MAX_NR_ZONES]; 用于保留低内存区域的页面数量,以防上层内存充足而下层内存不足的情况。
#ifdef CONFIG_NEED_MULTIPLE_NODES
	int node; 表示该内存区域所在的 NUMA 节点编号。
#endif
	struct pglist_data	*zone_pgdat; 用于描述整个内存区域的元数据。
	struct per_cpu_pageset __percpu *pageset;

#ifndef CONFIG_SPARSEMEM
	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; 表示该内存区域中由 buddy 系统管理的页面数量。
	unsigned long		spanned_pages; 表示该内存区域覆盖的总页数,包括空洞区域。
	unsigned long		present_pages; 表示该内存区域存在的物理页数,不包括空洞区域。

	const char		*name;

#ifdef CONFIG_MEMORY_ISOLATION
	unsigned long		nr_isolate_pageblock;
#endif

#ifdef CONFIG_MEMORY_HOTPLUG
	/* see spanned/present_pages for more description */
	seqlock_t		span_seqlock;
#endif

	int initialized; 表示该内存区域是否已经初始化。
	/* Write-intensive fields used from the page allocator */
	ZONE_PADDING(_pad1_)
	/* free areas of different sizes */
	struct free_area	free_area[MAX_ORDER]; 用于表示不同大小的空闲页面区域。

	/* zone flags, see below */
	unsigned long		flags; 包含该内存区域的标志位,如是否支持 NUMA 等

	/* Primarily protects free_area */
	spinlock_t		lock;

	/* Write-intensive fields used by compaction and vmstats. */
	ZONE_PADDING(_pad2_)

	/*
	 * When free pages are below this point, additional steps are taken
	 * when reading the number of free pages to avoid per-cpu counter
	 * drift allowing watermarks to be breached
	 */
	unsigned long percpu_drift_mark;

#if defined CONFIG_COMPACTION || defined CONFIG_CMA
	/* pfn where compaction free scanner should start */
	unsigned long		compact_cached_free_pfn;
	/* pfn where compaction migration scanner should start */
	unsigned long		compact_cached_migrate_pfn[ASYNC_AND_SYNC];
	unsigned long		compact_init_migrate_pfn;
	unsigned long		compact_init_free_pfn;
#endif

#ifdef CONFIG_COMPACTION
	unsigned int		compact_considered;
	unsigned int		compact_defer_shift;
	int			compact_order_failed;
#endif

#if defined CONFIG_COMPACTION || defined CONFIG_CMA
	/* Set to true when the PG_migrate_skip bits should be cleared */
	bool			compact_blockskip_flush; 表示是否应清除 PG_migrate_skip 标志。
#endif

	bool			contiguous; 表示该内存区域是否支持连续内存分配。
	ZONE_PADDING(_pad3_)
	/* Zone statistics */
	atomic_long_t		vm_stat[NR_VM_ZONE_STAT_ITEMS]; 维护关于该内存区域的各种统计信息。
	atomic_long_t		vm_numa_stat[NR_VM_NUMA_STAT_ITEMS]; 维护关于该内存区域的 NUMA 相关统计信息。
} ____cacheline_internodealigned_in_smp;

4.内存节点:node(struct pglist_data)

  • 内存模型:uma numa
  • struct pglist_data 表示node中的内存资源
  • 定义:include/linux/mmzone.h
  • 结构体:struct pglist_data
  • node_data数组:保存所有node的的pglist_data结构体

物理内存管理架构:

  • 在numa系统中,每个node节点将有一个pglist_data结构体去描述它。如果在uma上,这里将只有一个pglist_data.
  • 接下来就是zone:一般分为dma区,nomal区和highmem区,当然这里是不一定的。
  • zone区通过struct zone结构体描述,unsigned long zone_start_pfn;描述具体page页帧号。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2068987.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

配置PXE预启动执行环境:Kickstart自动化无人值守安装

文章目录 实现 Kickstart 无人值守安装1. 安装Kickstart和配置应答文件&#xff08;图形化界面&#xff09;2. 配置 PXE 菜单支持 Kickstart 无人值守安装3. 验证 Kickstart 无人值守安装4. 拓展&#xff1a;命令行配置应答文件&#xff08;命令行界面&#xff09; 实现 Kickst…

猜数3次-python

题目要求&#xff1a; 定一个数字&#xff08;1-10&#xff0c;随机产生&#xff0c;通过3次判断来猜出数字&#xff09; 数字随机产生&#xff0c;范围1-10有三次机会猜测数字&#xff0c;通过3层嵌套判断实现每次猜不中会提示大了或者小了 ps&#xff1a;补充随机函数 imp…

client网络模块的开发和client与server端的部分联动调试

客户端网络模块的开发 我们需要先了解socket通信的流程 socket通信 server端的流程 client端的流程 对于closesocket()函数来说 closesocket()是用来关闭套接字的,将套接字的描述符从内存清除,并不是删除了那个套接字,只是切断了联系,所以我们如果重复调用,不closesocket()…

合合信息文档解析Coze插件发布,PDF转Markdown功能便捷集成

近日&#xff0c;TextIn开发的PDF转Markdown插件正式上架Coze平台。 在扣子搜索“pdf转markdown”&#xff0c;或在Coze平台搜索“pdf2markdown”&#xff0c;即可找到插件&#xff0c;在你的专属智能体中便捷使用文档解析功能。 如果想测试解析插件在你需要的场景下表现如何&…

R语言VAR模型的多行业关联与溢出效应可视化分析

全文链接&#xff1a;https://tecdat.cn/?p37397 摘要&#xff1a;本文对医疗卫生、通信、金融、房地产和零售等行业的数据展开深入研究。通过读取数据、计算收益率、构建 VAR 模型并进行估计&#xff0c;帮助客户进一步分析各行业变量的影响及残差的协方差与相关矩阵&#xf…

xml打印模板解析-SAAS本地化及未来之窗行业应用跨平台架构

一、为何要自己设置打印模板系统 1.确保自由知识产权 2.支持跨平台&#xff1a;物联网&#xff0c;自助终端&#xff0c;电脑&#xff0c;web&#xff0c;C#&#xff0c;jsp,android,java,php 等多种语言 二、xml 代码解析 package CyberWinPHP.Cyber_Plus;import java.io.…

2024下半年软考有哪些科目开考?该怎么选?

近年来&#xff0c;软考&#xff08;软件水平考试&#xff09;的难度逐渐攀升&#xff0c;这并非源于题目本身的复杂化&#xff0c;而是官方对通过率的调控策略所致。整体通过率维持在13%左右&#xff0c;高级别考试更是低至10%以下&#xff0c;考生需慎重对待。以湖南2024年上…

数据仓库建模的步骤-从需求分析到模型优化的全面指南

想象一下,你正站在一座巨大的图书馆前。这座图书馆里存放着你公司所有的数据。但是,书籍杂乱无章,没有分类,没有索引。你如何才能快速找到所需的信息?这就是数据仓库建模要解决的问题。本文将带你深入了解数据仓库建模的主要步骤,让你掌握如何将杂乱的数据转化为有序、高效、易…

Java | Leetcode Java题解之第367题有效的完全平方数

题目&#xff1a; 题解&#xff1a; class Solution {public boolean isPerfectSquare(int num) {double x0 num;while (true) {double x1 (x0 num / x0) / 2;if (x0 - x1 < 1e-6) {break;}x0 x1;}int x (int) x0;return x * x num;} }

监控摄像头能看到电脑屏幕内容吗?监控摄像头VS电脑屏幕监控软件!告别盲区,让您的企业管理无死角!

在企业管理中&#xff0c;监控摄像头和电脑屏幕监控软件都是重要的工具&#xff0c;但它们在监控电脑屏幕内容方面存在显著差异。本文将深入探讨监控摄像头在捕捉电脑屏幕内容时的局限性&#xff0c;并对比介绍安企神——电脑屏幕监控软件的优势及其功能策略&#xff0c;帮助企…

在Windows下安装设置Node.js 20.16.0

文章目录 一、下载Node.js二、安装Node.js三、设置Node.js四、更换npm源 一、下载Node.js 官网地址&#xff08;中文网&#xff09; 或者使用直链下载 二、安装Node.js 打开下载好的安装包&#xff0c;点击下一步 同意用户协议后下一步 选择安装目录后下一步 可以根据自…

02 tkinter有趣项目-头像制作-界面设计

头像制界面设计 **avatar.png** **界面** 界面分析 背景图片: 顶部中央位置显示一个小孩背着书包的图片。这个图片是程序的背景&#xff0c;占据了大部分的窗口空间。 标题和按钮: 在图片上方&#xff0c;有一个标题栏&#xff0c;显示文本“在线姓氏头像制作”&#xff0c;使…

vue+fastadmin跨域请求问题

记录一个 vuefastadmin项目api 访问跨域问题 前端页面使用的是 axios 发起请求&#xff0c;api 是 fastadmin 写的&#xff0c;遇到跨域错误&#xff1a; 解决办法&#xff1a; 控制器代码中加入check_cors_request()实现跨域检测 fa 官网对跨域的说明 &#xff1a;跨域配置 -…

乐凡三防高亮屏工业平板电脑的应用场景

随着科技的发展&#xff0c;三防高亮屏工业平板电脑在越来越多的领域中得到广泛应用。下面探讨一下三防高亮屏工业平板电脑的应用场景及其在不同领域中的优势。 物流行业 在物流行业中&#xff0c;三防高亮屏工业平板电脑可以用于仓库管理、货物跟踪、运输调度等多个方面。在阳…

在Ubuntu22.04使用PySide6或PyQt5的文件选择框时,无法显示文件夹中的文件问题的解决方案

摘要&#xff1a;在使用PySide6或PyQt5开发图形用户界面&#xff08;GUI&#xff09;应用程序时&#xff0c;我们经常会使用 QFileDialog 来让用户选择文件或文件夹。然而&#xff0c;有时候会遇到一个奇怪的问题&#xff0c;即在打开文件选择对话框时&#xff0c;某些文件类型…

Vue3的三种样式控制及实现原理

你好&#xff0c;我是沐爸&#xff0c;欢迎点赞、收藏和关注。个人知乎 Vue3中一共有三种样式控制&#xff0c;分别是全局样式控制、局部作用域样式控制和深度样式控制&#xff0c;今天我们一起看下这三种样式控制的使用&#xff0c;以及实现的原理是什么。 一、全局样式控制…

数据恢复技术-手动修复MBR-/NTFS分区

前言 本文只作为本人学习笔记&#xff0c;不做他用&#xff0c;转载请注明原处谢谢&#xff01; 本文教大家如何手工修复MBR引导分区&#xff0c;找回丢失的数据&#xff0c;先附加题目镜像&#xff08;右键我的电脑或win标&#xff0c;选择管理/磁盘管理---操作---附加VHD&…

笔记整理—uboot启动过程(2)BL1低级初始化

lowlevel_init看名字就知道是关于初级方面的初始化&#xff0c;其中可用将其干的事情分为11个步骤&#xff1a; &#xff08;1&#xff09;push {lr} 也就是lr压栈。 &#xff08;2&#xff09;检测复位状态&#xff1a;如冷上电、热启动、睡眠等。冷上电要初始化DDR后才能使用…

MS2232/MS2232T——±20kV ESD 保护、3V-5.5V 供电、真 RS-232 收发器

MS2232/MS2232T 芯片是集成电荷泵、具有 20kV ESD 保护的 RS-232 收发器&#xff0c;包括两路接收器、两路发送器。芯 片满足 TIA/EIA-232 标准&#xff0c;为异步通信控制器和串口连接器 提供通信接口。 芯片采用 3V-5.5V 供电&#xff0c;电荷泵仅用 4 个 0.1-0.47μF 小…

GUI / GitOps / API: 用 Bytebase 实现 SQL 审核

修改数据库中的数据时&#xff0c;确保安全准确至关重要。Bytebase 提供 SQL 审核功能&#xff1a;将 SQL 变更应用到数据库之前&#xff0c;可对其进行评估。SQL 审核可通过 Bytebase GUI、GitOps 工作流或 API 触发。 本教程将使用 Bytebase 的 SQL 审核来改进数据库 Schema …