linux kernel物理内存概述(三)

目录

物理内存空间划分

物理内存初始化

查看当前页面分配状态

页块

页面如何添加到伙伴系统中?


物理内存空间划分

  • 32位系统 4GB 用户空间和内核空间划分 3:1

  • ARM64架构处理器虚拟地址空间划分方式;

  • 内核中使用PAGE_OFFSET宏计算 内核线性映射中 **虚拟地址和物理地址的转换 **

    #define VA_BITS (CONFIG_ARM64_VA_BITS)
    #define VA_START (UL(0×ffffffffffffffff) - \
    (UL(1) << VABITS)+1)
    #define VA_OFFSET (UL(0×ffffffffffffffff) -\
    (UL (1) << (VA_BITS - 1)) +1)
  • CONFIG_ARM64_VA_BITS设置48,那么PAGE_OFFSET的值为0xFFFF 8000 0000 0000

  • 内核中计算线性映射的物理地址和虚拟地址的转换关系 线性映射的物理地址 = vaddr - PAGE_OFFSET + PHYS_OFFSET

  • 内核常用的宏 __pa()和__va()

  • __phys_to_virt()用于根据计算物理地址 计算线性映射的虚拟地址

  • __virt_to_phys_nodebug()根据虚拟地址计算物理地址。在arm64内核中,内核空间虚拟地址分为1,线性映射区域;2,vmalloc区域,内核会映射到vmalloc区域

  • __is_lm_address 用于判断虚拟地址是否为线性映射的虚拟地址

物理内存初始化

在内核启动时,DDR大小,内存起始地址和内核空间内存布局,以及映射关系。物理内存要添加到 伙伴系统中 伙伴系统是内核中内存管理一种方法,在用户提出申请时,分配一个大小合适的内存块给用户。内存块的大小2的order次幂个页面;

  • order最大值是MAX_ORDER 通常是11,就是把所有空闲页面分成11个内存块链表,每个内存块链表分别有1,2,4,8, 1024个连续页面。 zone结构体中有free_area数组,大小是MAX_ORDER.free_area数据结构中包含了MIGRATE_TYPES(不可移动、可回收、可移动页面)个链表
查看当前页面分配状态
# cat /proc/pagetypeinfo 
Page block order: 9
Pages per block:  512Free pages count per migrate type at order       0      1      2      3      4      5      6      7      8      9     10 
Node    0, zone      DMA, type    Unmovable      0      0      0      0      0      0      0      1      0      0      0 
Node    0, zone      DMA, type      Movable      0      0      0      0      0      0      0      0      0      1      3 
Node    0, zone      DMA, type  Reclaimable      0      0      0      0      0      0      0      0      0      0      0 
Node    0, zone      DMA, type   HighAtomic      0      0      0      0      0      0      0      0      0      0      0 
Node    0, zone      DMA, type      Isolate      0      0      0      0      0      0      0      0      0      0      0 
Node    0, zone    DMA32, type    Unmovable    200    200    296    190    130     61     47     13      5      8      5 
Node    0, zone    DMA32, type      Movable   1990    153     26     14      0      1      1      0      0      4      4 
Node    0, zone    DMA32, type  Reclaimable   1009    246    171     12     91     28      4      0      0      0      0 
Node    0, zone    DMA32, type   HighAtomic      0      0      0      0      0      0      0      0      0      0      0 
Node    0, zone    DMA32, type      Isolate      0      0      0      0      0      0      0      0      0      0      0 
Node    0, zone   Normal, type    Unmovable    468    398    242     80     54     16      2      2      0      0      0 
Node    0, zone   Normal, type      Movable      0      0      0      0      0      0      0      0      0      0      0 
Node    0, zone   Normal, type  Reclaimable    174     55     45     12      0      0      0      0      0      0      0 
Node    0, zone   Normal, type   HighAtomic     15     10      3      0      0      0      0      0      0      0      0 
Node    0, zone   Normal, type      Isolate      0      0      0      0      0      0      0      0      0      0      0 Number of blocks type     Unmovable      Movable  Reclaimable   HighAtomic      Isolate 
Node 0, zone      DMA            1            7            0            0            0 
Node 0, zone    DMA32          434         1037           57            0            0 
Node 0, zone   Normal          149          331           31            1            0 

 从上可以看出

  • Node 节点有1个
  • Node 划分为3个zone Normal DMA32 DMA
  • 伙伴系统的类型 Isolate,Reclaimable,Movable,Unmovable,HighAtomic,
  • 伙伴系统的阶数 0~10
  • 大部分的页面是DMA32的Movable

页块

  • 内核中,一个页块大小通常是2(MAX_ORDER-1)个页面
  • 每个页块有迁移属性,zone->pageblock_flags指向其内存空间;
  • 迁移类型内存空间大小通过usemap_size函数来计算 zone初始化函数free_area_init_core会调用setup_usemap()函数计算大小,并分配内存;
static void __ref setup_usemap(struct pglist_data *pgdat,struct zone *zone,unsigned long zone_start_pfn,unsigned long zonesize)
{unsigned long usemapsize = usemap_size(zone_start_pfn, zonesize);if (usemapsize) {zone->pageblock_flags =memblock_alloc_node(usemapsize, SMP_CACHE_BYTES,pgdat->node_id);}
}
/** Calculate the size of the zone->blockflags rounded to an unsigned long*/
static unsigned long __init usemap_size(unsigned long zone_start_pfn, unsigned long zonesize)
{unsigned long usemapsize;zonesize += zone_start_pfn & (pageblock_nr_pages-1);usemapsize = roundup(zonesize, pageblock_nr_pages);usemapsize = usemapsize >> pageblock_order;usemapsize *= NR_PAGEBLOCK_BITS;usemapsize = roundup(usemapsize, 8 * sizeof(unsigned long));return usemapsize / 8;
}

  • 首先,通过四舍五入确保zonesize是pageblock_order的倍数。
  • 然后每个页面块使用1个NR_PAGEBLOCK_BITS值的比特,
  • 最后将现在的比特四舍五入到最接近的long
  • memblock_alloc_node 分配内存,设置类型,并赋值给pageblock_flags
页面如何添加到伙伴系统中?

<start_kernel->mm_init->mem_init->free_all_bootmem->free_low_memory_core_eearly> free_low_memory_core_eearly函数,通过for_each_free_mem_range遍历所有内存块,找出内存块的起始地址和结束地址。

 函数调用关系

static unsigned long __init free_low_memory_core_early(void)
{for_each_free_mem_range(i, NUMA_NO_NODE, MEMBLOCK_NONE, &start, &end,NULL)count += __free_memory_core(start, end);return count;
}
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;
}
static void __init __free_pages_memory(unsigned long start, unsigned long end)
{int order;while (start < end) {order = min(MAX_ORDER - 1UL, __ffs(start));while (start + (1UL << order) > end)order--;memblock_free_pages(pfn_to_page(start), start, order);start += (1UL << order);}
}
void __init memblock_free_pages(struct page *page, unsigned long pfn,unsigned int order)
{__free_pages_core(page, order);
}
void __free_pages_core(struct page *page, unsigned int order)
{...__free_pages_ok(page, order, FPI_TO_TAIL);
}
static void __free_pages_ok(struct page *page, unsigned int order,fpi_t fpi_flags)
{free_one_page(page_zone(page), page, pfn, order, migratetype,fpi_flags);
}
static void free_one_page(struct zone *zone,struct page *page, unsigned long pfn,unsigned int order,int migratetype, fpi_t fpi_flags)
{__free_one_page(page, pfn, zone, order, migratetype, fpi_flags);
}
  • 参数start和end时起始与终止页帧号,while循环遍历[start,end],步长取MAX_ORDER-1和__ffs(start)中较小值
  • 假设start起始地址0x35300,该地址以0x100对其,通过__ffs(start)计算出合适的order值为8,(2^8=0x100)。此起始地址适合创建一个2^8个页面,并添加到order为8的伙伴系统中;
  • 得到order 最后调用__free_pages_core 将内存添加到伙伴系统中

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

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

相关文章

llc半桥开关电源基础知识2(电路图简化)

llc半桥开关电源拓扑图如下 稳态:LLC电源已经正常工作,已经输出电压稳定稳态:LLC电源已经正常工作,已经输出电压稳定。 我们在分析拓扑结构的时候,都是基于他已经正常稳定输出的时候来分析的,毕竟LC电源只要以工作啊,绝大多数时间都是工作在稳态。 具体电路图化简分析如…

Android activity的启动模式和生命周期

一、Activity的启动模式有四种&#xff1a;standard&#xff08;默认&#xff09;、singleTop&#xff08;栈顶复用&#xff09;、singleTask&#xff08;栈内复用&#xff09;、singleInstance&#xff08;单例模式&#xff09; 使用方法&#xff1a; 在清单文件中声明 Acti…

yolov9训练

目录 说明 1、下载代码安装新的python环境 2、准备数据 3、修改代码 说明 本文参考该博主的文章&#xff0c;在已经有数据的情况&#xff0c;进行简单总结。需要详细版见原文链接如下&#xff1a;YOLOV9保姆级教程-CSDN博客 1、下载代码安装新的python环境 代码下载&…

力扣每日一道系列 --- LeetCode 160. 相交链表

&#x1f4f7; 江池俊&#xff1a; 个人主页 &#x1f525;个人专栏&#xff1a; ✅数据结构探索 ✅LeetCode每日一道 &#x1f305; 有航道的人&#xff0c;再渺小也不会迷途。 LeetCode 160. 相交链表 思路&#xff1a; 首先计算两个链表的长度&#xff0c;然后判断两个链…

如何选择程序员职业赛道

目录 前言1 个人技能分析1.1 技术栈评估1.2 经验积累1.3 数据科学能力 2 兴趣与价值观2.1 用户交互与界面设计2.2 复杂问题解决与系统优化 3 长期目标规划4 市场需求分析4.1 人工智能和云计算4.2 前沿技术趋势 5 就业前景5.1 前端在创意性公司中的应用5.2 后端在大型企业中的广…

前端爬虫+可视化Demo

爬虫简介 可以把互联网比做成一张 “大网”&#xff0c;爬虫就是在这张大网上不断爬取信息的程序。 爬虫是请求网站并提取数据的自动化程序。 省流&#xff1a;Demo实现前置知识&#xff1a; JS 基础Node 基础 &#xff08;1&#xff09;爬虫基本工作流程&#xff1a; 向…

『运维备忘录』之 RegEx 正则表达式实例汇总

运维人员不仅要熟悉操作系统、服务器、网络等知识&#xff0c;甚至对于开发相关的也要有所了解。很多运维工作者可能一时半会记不住那么多命令、代码、方法、原理或者用法等等。这里我将结合自身工作&#xff0c;持续给大家更新运维工作所需要接触到的知识点&#xff0c;希望大…

深入理解Tomcat

目录&#xff1a; TomcatTomcat简介如何下载tomcatTomcat工作原理Tomcat架构图Tomcat组件Server组件Service组件Connector组件Engine组件Host组件Context组件 配置虚拟主机(Host)配置Context Tomcat Tomcat简介 Tomcat服务器是Apache的一个开源免费的Web容器。它实现了JavaEE…

【Android】源码解析 Activity 的构成

本文是基于 Android 14 的源码解析。 当我们写 Activity 时会调用 setContentView() 方法来加载布局。现在来看看 setContentView() 方法是怎么实现的&#xff0c;源码如下所示&#xff1a; 路径&#xff1a;/frameworks/base/core/java/android/app/Activity.javapublic void…

【机器学习】包裹式特征选择之递归特征添加法

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;机器学习 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进…

Springboot解决模块化架构搭建打包错误找不到父工程

Springboot解决模块化架构搭建打包错误找不到父工程 一、情况一找不到父工程依赖1、解决办法 二、情况二子工程相互依赖提示"程序包xxx不存在" 一、情况一找不到父工程依赖 报错信息 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:…

windows安装pytorch(anaconda安装)

文章目录 前言一、安装anaconda1、进入官网下载&#xff08;1&#xff09;点击view all Installers&#xff08;2&#xff09;下载需要的版本 2、一顿默认安装就行&#xff08;到这一步这样填&#xff09;3、进入开始找到Anaconda Prompt&#xff0c;点击进入到base环境 二、新…

低代码与国产化部署:软件开发的未来趋势与应用实践

在数字化时代&#xff0c;软件开发已经成为企业创新和竞争力提升的关键。随着我国科技实力的不断提升&#xff0c;国产化部署逐渐成为软件开发领域的重要趋势。与此同时&#xff0c;低代码技术的发展也为国产化部署提供了新的机遇。本文将探讨如何在软件开发过程中充分发挥两者…

3-字典树-单词搜索 II

这是字典树的第3篇算法&#xff0c;力扣链接。 给定一个 m x n 二维字符网格 board 和一个单词&#xff08;字符串&#xff09;列表 words&#xff0c; 返回所有二维网格上的单词 。 单词必须按照字母顺序&#xff0c;通过 相邻的单元格 内的字母构成&#xff0c;其中“相邻”单…

Rust Web框架的选择

一、概述 Rust语言在系统编程领域的崛起&#xff0c;它的安全性、性能和并发特性也吸引了Web开发者的关注。本文将深入探讨当前流行的Rust Web框架&#xff0c;分析它们的特点、优势以及如何在Web开发中进行选择和使用。同时&#xff0c;我们还将提供一些实际的示例&#xff0…

docker 常用命令大全(基础、镜像、容器、数据卷)

文章目录 1.docker基础命令2.docker镜像命令2.1 镜像名称2.2 镜像命令2.3 案例1--拉取、查看镜像2.4 案例2--保存、导入镜像 3.docker容器命令3.1 容器命令3.2 案例--创建并运行一个容器3.3 案例--进入容器&#xff0c;修改文件3.4 小结 4.数据卷4.1 什么是数据卷4.2 数据卷操作…

【3GPP】【核心网】【5G】5G核心网协议解析(二)(超详细)

5G UE 附着过程 UE AMF ----------------- 注册请求(Registration Request) ----------------------> <--------------- 鉴权请求(Authentication Request) ------…

当Sora风靡,AI风潮吹醒金融科技

以下文章来源&#xff1a;凤凰网 前有OpenAI发布了Sora&#xff0c; 后有苹果放弃了秘密进行了十年的造车项目&#xff0c;转身拥抱AI&#xff0c; 再有国内市场上此起彼伏的AI呐喊声&#xff0c; 一场以AI为主导的新热浪&#xff0c;正在来袭。 当AI的风潮开始兴盛&#x…

xshell安装java/jdk

1.下载jdk wget https://download.java.net/java/GA/jdk11/13/GPL/openjdk-11.0.1_linux-x64_bin.tar.gz 2.解压jdk安装包 tar -zxvf openjdk-11.0.1_linux-x64_bin.tar.gz 其中第三步 编辑 ~/.bashrc 或 ~/.bash_profile 文件 打开vim文本编辑器 vim ~/.bash_profile export …

MoonBit 新增 += 运算符,引入 super trait 和 List 字面量机制

MoonBit更新 1. 添加了 系列语句 包括、-、*、/&#xff0c;支持运算符重载&#xff1a; fn init {let array [1,2,3,4]array[2] * 10println(array) // [1, 2, 30, 4] }fn init {let mut a 1a 20println(a) // 21 } struct Foo {data : Array[Int] } derive(Debug)fn o…