首页 > 系统相关 >内核态内存映射

内核态内存映射

时间:2023-11-06 23:32:21浏览次数:30  
标签:__ 映射 内存 虚拟地址 页表 内核

内核态的内存映射机制,主要包含以下几个部分:

  • 内核态内存映射函数 vmalloc、kmap_atomic 是如何工作的;
  • 内核态页表是放在哪里的,如何工作的?swapper_pg_dir 是怎么回事;
  • 出现了内核态缺页异常应该怎么办?

内核页表的顶级目录 init_top_pgt,定义在 __INITDATA 里面。它们都有代码段,还有一些初始化了的全局变量,放在.init 区域。这些说的就是这个区域。可以看到,页表的根其实是全局变量,这就使得我们初始化的时候,甚至内存管理还没有初始化的时候,很容易就可以定位到。

因为 level3_ident_pgt 是在虚拟地址的内核代码段里的,而 __START_KERNEL_map 正是虚拟地址空间的内核代码段的起始地址。这样,level3_ident_pgt 减去 __START_KERNEL_map 才是物理地址。

第一项定义完了以后,接下来跳到 PGD_PAGE_OFFSET 的位置,再定义一项。从定义可以看出,这一项就应该是 __PAGE_OFFSET_BASE 对应的。__PAGE_OFFSET_BASE 是虚拟地址空间里面内核的起始地址。第二项也指向 level3_ident_pgt,直接映射区。

第二项定义完了以后,接下来跳到 PGD_START_KERNEL 的位置,再定义一项。从定义可以看出,这一项应该是 __START_KERNEL_map 对应的项,__START_KERNEL_map 是虚拟地址空间里面内核代码段的起始地址。第三项指向 level3_kernel_pgt,内核代码区。

接下来的代码就很类似了,就是初始化个表项,然后指向下一级目录,最终形成下面这张图。

内核态内存映射_内核态

内核页表定义完了,一开始这里面的页表能够覆盖的内存范围比较小。例如,内核代码区 512M,直接映射区 1G。这个时候,其实只要能够映射基本的内核代码和数据结构就可以了。可以看出,里面还空着很多项,可以用于将来映射巨大的内核虚拟地址空间,等用到的时候再进行映射。

如果是用户态进程页表,会有 mm_struct 指向进程顶级目录 pgd,对于内核来讲,也定义了一个 mm_struct,指向 swapper_pg_dir。

在用户态可以通过 malloc 函数分配内存,当然 malloc 在分配比较大的内存的时候,底层调用的是 mmap,当然也可以直接通过 mmap 做内存映射,在内核里面也有相应的函数。

在虚拟地址空间里面,有个 vmalloc 区域,从 VMALLOC_START 开始到 VMALLOC_END,可以用于映射一段物理内存。

kmap_atomic 和 vmalloc 不同。kmap_atomic 发现,没有页表的时候,就直接创建页表进行映射了。而 vmalloc 没有,它只分配了内核的虚拟地址。所以,访问它的时候,会产生缺页异常。

内核态的缺页异常还是会调用 do_page_fault,但是会走到咱们上面用户态缺页异常中没有解析的那部分 vmalloc_fault。这个函数并不复杂,主要用于关联内核页表项。

对于用户态的内存分配,或者直接调用 mmap 系统调用分配,或者调用 malloc。调用 malloc 的时候,如果分配小的内存,就用 sys_brk 系统调用;如果分配大的内存,还是用 sys_mmap 系统调用。正常情况下,用户态的内存都是可以换出的,因而一旦发现内存中不存在,就会调用 do_page_fault。

内核态内存映射_内核态_02

内核态内存映射_内核态_03

标签:__,映射,内存,虚拟地址,页表,内核
From: https://blog.51cto.com/key3feng/8219394

相关文章

  • Flink 内存配置学习总结
    设置进程内存(ProcessMemory)ApacheFlink通过严格控制其各种组件的内存使用,在JVM之上提供高效的工作负载。配置总内存(TotalMemory)FlinkJVM进程的总进程内存(totalprocessmemory)由Flink应用程序消耗的内存(总Flink内存(totalFlinkmemory))和JVM运行进程所消耗的内存......
  • JAVA多线程并发查询百万数据的内存占用问题?
    在Java中使用多线程并发查询百万数据时,内存占用是一个需要考虑的重要问题。以下是一些解决该问题的方案:分批查询:将数据分成较小的批次进行查询,而不是一次性加载全部数据。这样可以减少每个线程需要处理的数据量,降低内存占用。可以将查询结果分组或按需加载,以保持内存占用的合理范......
  • Linux基础-查看dm的映射关系
    参考:https://www.cnblogs.com/aozhejin/p/16061309.htmlsudolvdisplay|awk'/LVName/{n=$3}/Blockdevice/{d=$3;sub(".*:","dm-",d);printd,n;}'   ......
  • 一次压力测试引起的内存溢出排查(apollo)
    项目从nacos配置中心适配apollo后,线上压测运行4个小时,内存告警,FGC达到了惊人的100+次拿到压测dump文件使用mat分析发现com.ctrip.framework.apollo.spring.property.SpringValueRegistry占比达到91.68%,很明显SpringValueRegistry导致的内存泄漏 找到了导致内存泄漏的原因,那么......
  • Linux下内存buff/cache占用过多问题解决
    在Linux下经常会遇到buff/cache内存占用过多问题,如果buff/cache占用过大的,free空闲内存就很少,影响使用;通常内存关系是:普通机器:total=used+free虚拟机器:total=used+free+buff/cache这个时候可以看到buff/cache占用的内存非常大,这个时候可以使用一下命令去清除一下cache内存echo1>......
  • 用户态内存映射
    内存映射不仅仅是物理内存和虚拟内存之间的映射,还包括将文件中的内容映射到虚拟内存空间。这个时候,访问内存空间就能够访问到文件里面的数据。而仅有物理内存和虚拟内存的映射,是一种特殊情况。对于堆的申请来讲,mmap是映射内存空间到物理内存。如果一个进程想映射一个文件到自己的......
  • JavaScript内存管理——隐藏类
    根据JavaScript所在的运行环境,有时候需要根据JavaScript引擎采取不同的性能优化策略。如果代码非常注重性能,那么隐藏类对我们是非常重要的。比如以下的代码:functionUser(){this.name="UserName";}letuser1=newUser();leruser2=newUser();在上面的代码中......
  • python的内存泄漏及垃圾回收机制
    python内存泄漏的几种场景: 一,如果打开一个文件,不关闭,是不是就是内存泄漏了? 在Python中,打开的文件对象会一直存在内存中,直到显式地关闭文件或者程序结束时才会被清理。因此,如果打开了一个文件但没有关闭它,那么这个文件对象会一直占用内存,导致内存泄漏。为了避免内存泄漏问题......
  • RHEL7系统管理之内核管理
    1Kdump工具Kdump的工作机制是在内核崩溃时,通过kexec工具由BIOS启动一个备用内核,由备用内核执行一系列任务,保存内存中崩溃内核的状态,供后续故障分析用。本文默认AMD或INTELX86_64架构,RHEL7系统环境.1.1内核管理工具Kdump安装Kdump是RHEL7中自带的内核管理工具......
  • crash —— 查看进程的内核栈的内容
    有时我们有这样的需求,想查看某个进程的内核栈里的全部内容,介绍下面的几种做法:方法1:得到进程的栈底地址以及栈大小,然后使用rd指令读取使用mach指令获取内核栈的大小crash>mach|grepSIZEMEMORYSIZE:64GBPAGESIZE:4096KERNELSTACKSI......