Linux物理内存映射

news/2024/5/7 6:15:04/文章来源:https://blog.csdn.net/weixin_45030965/article/details/126995123

文章目录

  • 前言
  • 一、物理内存映射
    • 1.1 x86_64虚拟地址空间简介
    • 1.2 kernel text mapping
    • 1.3 direct mapping of all phys memory
  • 二、__pa(x)函数和__va(x)函数
    • 2.1 direct mapping
    • 2.2 kernel text mapping
  • 三、API演示
  • 参考资料

前言

实验平台:
intel x86_64
centos 7:3.10.0

一、物理内存映射

1.1 x86_64虚拟地址空间简介

// linux-3.10.1/Documentation/x86/x86_64/mm.txt<previous description obsolete, deleted>Virtual memory map with 4 level page tables:0000000000000000 - 00007fffffffffff (=47 bits) user space, different per mm
hole caused by [48:63] sign extension
ffff800000000000 - ffff80ffffffffff (=40 bits) guard hole
ffff880000000000 - ffffc7ffffffffff (=64 TB) direct mapping of all phys. memory
ffffc80000000000 - ffffc8ffffffffff (=40 bits) hole
ffffc90000000000 - ffffe8ffffffffff (=45 bits) vmalloc/ioremap space
ffffe90000000000 - ffffe9ffffffffff (=40 bits) hole
ffffea0000000000 - ffffeaffffffffff (=40 bits) virtual memory map (1TB)
... unused hole ...
ffffffff80000000 - ffffffffa0000000 (=512 MB)  kernel text mapping, from phys 0
ffffffffa0000000 - ffffffffff5fffff (=1525 MB) module mapping space
ffffffffff600000 - ffffffffffdfffff (=8 MB) vsyscalls
ffffffffffe00000 - ffffffffffffffff (=2 MB) unused holeThe direct mapping covers all memory in the system up to the highest
memory address (this means in some cases it can also include PCI memory
holes).vmalloc space is lazily synchronized into the different PML4 pages of
the processes using the page fault handler, with init_level4_pgt as
reference.Current X86-64 implementations only support 40 bits of address space,
but we support up to 46 bits. This expands into MBZ space in the page tables.

主要是分析其中的:

......
ffff880000000000 - ffffc7ffffffffff (=64 TB) direct mapping of all phys. memory
......
ffffffff80000000 - ffffffffa0000000 (=512 MB)  kernel text mapping, from phys 0
......

1.2 kernel text mapping

内核代码段_text的起始虚拟地址:0xffffffff81000000
在这里插入图片描述

// linux-3.10.1/arch/x86/include/asm/page_64_types.h#define __PHYSICAL_START	((CONFIG_PHYSICAL_START +	 	\(CONFIG_PHYSICAL_ALIGN - 1)) &	\~(CONFIG_PHYSICAL_ALIGN - 1))#define __START_KERNEL		(__START_KERNEL_map + __PHYSICAL_START)#define __START_KERNEL_map	_AC(0xffffffff80000000, UL)
// linux-3.10.1/Documentation/x86/x86_64/mm.txtffffffff80000000 - ffffffffa0000000 (=512 MB)  kernel text mapping, from phys 0

__START_KERNEL_map是内核映射的起始虚拟地址,从物理地址phys_base映射到虚拟地址__START_KERNEL_map。

物理地址phys_base:64bit下为了支持KASLR(kernel address space layout ramdomization)内核映像在物理内存中是一个随机地址phys_base,centos7.6 默认没有开启KASLR,物理地址phys_base默认是0 。
(3.10.0没有加入KASLR,请参考:https://www.phoronix.com/news/KASLR-Default-Linux-4.12)

// linux-3.10.1/arch/x86/kernel/head_64.S.text__HEAD.code64.globl startup_64
startup_64:....../** Compute the delta between the address I am compiled to run at and the* address I am actually running at.*/leaq	_text(%rip), %rbpsubq	$_text - __START_KERNEL_map, %rbp....../* Fixup phys_base */addq	%rbp, phys_base(%rip)ENTRY(phys_base)/* This must match the first entry in level2_kernel_pgt */.quad   0x0000000000000000

KASLR:将kernel随机的加载到不同的物理地址运行,内核在自引导及decompressed后,会通过判断kaslr命令行参数是否enable来确定是否对加载内核的物理地址和内核运行的虚拟地址进行随机化操作。

__PHYSICAL_START宏是内核代码段在物理内存中的起始地址,即:0x1000000。
__START_KERNEL宏是是内核代码段映射的起始虚拟地址,即:_text内核虚拟地址0xffffffff81000000。

_text 的物理地址(__PHYSICAL_START宏) = 0xffffffff81000000 - 0xffffffff80000000 = 0x1000000
内核代码段的起始物理地址_text就是 0x1000000。

也可以通过看内核的配置的文件查看内核代码段的起始物理地址_text:

vim /boot/config-3.10.0-693.el7.x86_64

在这里插入图片描述

通过 /proc/iomem 查看系统的物理地址空间,可以看到内核代码段的起始物理地址是0x1000000,与上述相等。
在这里插入图片描述

// linux-3.10.1/arch/x86/kernel/vmlinux.lds.S#define LOAD_OFFSET __START_KERNEL_mapOUTPUT_ARCH(i386:x86-64)
ENTRY(phys_startup_64)
jiffies_64 = jiffies;SECTIONS
{....... = __START_KERNEL;phys_startup_64 = startup_64 - LOAD_OFFSET;......
}

phys_startup_64 是内核代码段的物理起始地址, startup_64是内核代码段的虚拟起始地址(和_text是同一个地址,内核代码段的起始函数就是startup_64)。

// linux-3.10.1/arch/x86/kernel/head_64.S.text__HEAD.code64.globl startup_64
startup_64:/** At this point the CPU runs in 64bit mode CS.L = 1 CS.D = 0,* and someone has loaded an identity mapped page table* for us.  These identity mapped page tables map all of the* kernel pages and possibly all of memory.** %rsi holds a physical pointer to real_mode_data.** We come here either directly from a 64bit bootloader, or from* arch/x86_64/boot/compressed/head.S.** We only come here initially at boot nothing else comes here.** Since we may be loaded at an address different from what we were* compiled to run at we first fixup the physical addresses in our page* tables and then reload them.*//** Compute the delta between the address I am compiled to run at and the* address I am actually running at.*/leaq	_text(%rip), %rbpsubq	$_text - __START_KERNEL_map, %rbp......

所以对于内核代码段:内核代码段物理地址 + __START_KERNEL_map = 内核代码段虚拟地址。

1.3 direct mapping of all phys memory

这块区域把所有物理内存线性映射到PAGE_OFFSET虚拟地址。PAGE_OFFSET的值可能是固定的0xffff888000000000,或者KASLR使能后的随机地址page_offset_base。

// linux-3.10.1/arch/x86/include/asm/page_64_types.h#define __PAGE_OFFSET           _AC(0xffff880000000000, UL)

比如:
在这里插入图片描述
packet套接字的 struct sock 结构体的内核虚拟地址是 0xffff88025ff24800。

// linux-3.10.1/Documentation/x86/x86_64/mm.txtffff880000000000 - ffffc7ffffffffff (=64 TB) direct mapping of all phys. memory

packet套接字的 struct sock的物理地址 = 0xffff88025ff24800 - 0xffff880000000000 = 0x25ff24800

packet套接字的 struct sock的物理地址就在System RAM:100000000-26dffffff 范围中。
在这里插入图片描述

小结:/dev/mem是物理地址空间,而操作系统操作的任何内存都基于虚拟地址。
(1)x86_64可以直接映射64T的物理内存(direct mapping of all phys. memory),足以一一映射当前常见的任意物理内存。
(2)Linux内核对所有物理内存建立一一映射(kernel text mapping)。物理地址和虚拟地址之间固定偏移。

二、__pa(x)函数和__va(x)函数

对于上述的两块内存映射区:

......
ffff880000000000 - ffffc7ffffffffff (=64 TB) direct mapping of all phys. memory
......
ffffffff80000000 - ffffffffa0000000 (=512 MB)  kernel text mapping, from phys 0
......

这两块映射区域之间的内核虚拟地址转换为物理地址可以直接借助于__pa(x)函数,无需通过页表转换获得。

direct mapping之间的物理地址转换为内核虚拟地址可以直接借助于__va(x)函数。

// linux-3.10.1/arch/x86/include/asm/page.h
#define __pa(x)		__phys_addr((unsigned long)(x))// linux-3.10.1/arch/x86/include/asm/page_64.h
#define __phys_addr(x)		__phys_addr_nodebug(x)extern unsigned long phys_base;static inline unsigned long __phys_addr_nodebug(unsigned long x)
{unsigned long y = x - __START_KERNEL_map;/* use the carry flag to determine if x was < __START_KERNEL_map */x = y + ((x > y) ? phys_base : (__START_KERNEL_map - PAGE_OFFSET));return x;
}

2.1 direct mapping

// linux-3.10.1/arch/x86/include/asm/page_types.h
#define PAGE_OFFSET		((unsigned long)__PAGE_OFFSET)// linux-3.10.1/arch/x86/include/asm/page_64_types.h
#define __PAGE_OFFSET           _AC(0xffff880000000000, UL)__pa(x) = x -  PAGE_OFFSET

相对应有个__va(x)函数:

#define __va(x)			((void *)((unsigned long)(x)+PAGE_OFFSET))

2.2 kernel text mapping

// linux-3.10.1/arch/x86/include/asm/page_64_types.h
#define __START_KERNEL_map	_AC(0xffffffff80000000, UL)__pa(x) = x - __START_KERNEL_map + phys_base

如果没有开启KASLR

__pa(x) = x - __START_KERNEL_map

上述两个函数只适用direct mapping和kernel text mapping。其他区域的内核虚拟地址空间不能适用这两个函数进行转换。

三、API演示

#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/page.h>
#include <asm/pgtable_types.h>static int __init pa_va_init(void)
{unsigned long kernel_phys_address;unsigned long direct_phys_address;kernel_phys_address = __pa(0xffffffff81000000);printk(" kernel_text_start_phys_address = 0x%lx\n", kernel_phys_address);direct_phys_address = __pa(0xffff88006cadc000 );printk(" direct_phys_address = 0x%lx\n", direct_phys_address);return -1;
}static void __exit pa_va_exit(void)
{
}module_init(pa_va_init);
module_exit(pa_va_exit);
MODULE_LICENSE("GPL");

在这里插入图片描述
在这里插入图片描述

参考资料

Linux 3.10.1
https://blog.csdn.net/pwl999/article/details/112055498
https://zhuanlan.zhihu.com/p/99557658
https://blog.csdn.net/richardysteven/article/details/52629731
https://blog.csdn.net/dog250/article/details/102745181
https://mp.weixin.qq.com/s/TJ8ttDAZfZeUK-fSfRsJ8g

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

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

相关文章

基于订单系统的分库分表实战,让应用飞起来!

V-xin&#xff1a;ruyuanhadeng获得600页原创精品文章汇总PDF 前 言 各位读者朋友&#xff0c;大家好&#xff0c;这是分库分表实战的第一篇文章&#xff0c;首先介绍一下"基于ShardingSphere的分库分表实战"的设计思路及内容。 本实战的重点是分库分表实战&#x…

通讯录——文件读写版本

通讯录最终版本——文件读写 前面在暴躁小猿给大家分享了通讯录的静态版本和动态版本&#xff0c;但是这两个版本都不能实现文件的读写&#xff0c;每次运行程序都不能保存和读取数据&#xff0c;这样的通讯录是不完善的&#xff0c;根本没有办法去使用&#xff0c;所以为了满足…

Java毕设项目在线点餐系统计算机(附源码+系统+数据库+LW)

Java毕设项目在线点餐系统计算机&#xff08;附源码系统数据库LW&#xff09; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目…

电源芯片的选择

什么是电源芯片?它有什么作用?在选择电源芯片的时候&#xff0c;应该考虑那些地方?输入电压线性调整率、输入电压线性变化时对输出电压的相对影响&#xff1f;下面先来了解几个概念问题&#xff1a; 1、输出电压负载调整率&#xff1a;负载电流变化时输出电压相对变化情况 …

(附源码)计算机毕业设计SSM在线考试主观题评分系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

神经网络适用于什么情况,神经网络是分类算法吗

1、人工神经网络评价法 人工神经元是人工神经网络的基本处理单元&#xff0c;而人工智能的一个重要组成部分又是人工神经网络。人工神经网络是模拟生物神经元系统的数学模型&#xff0c;接受信息主要是通过神经元来进行的。首先&#xff0c;人工神经元利用连接强度将产生的信号…

web响应式布局与BootStrap框架

目录什么是响应式网页布局媒体查询什么是媒体查询&#xff1f;媒体类型&#xff08;mediatype&#xff09;关键字媒体特性&#xff08;media feature&#xff09;引入方式BootStrap简介使用步骤栅格系统组件JavaScript插件定制案例腾讯前端web首页什么是响应式网页布局 响应式…

Excel工作日日历

在项目管理中&#xff0c;通常需要制作一个工作日历&#xff0c;能标识出休假日。 难点在识别休假日&#xff0c;不能简单根据周几来判断&#xff0c;而是要根据国家法定假日和换班日进行判断。我做了一个示例&#xff0c;给感兴趣的朋友演示一下。 我会分步骤讲解一下如何制作…

APS高级排产如何帮助帮助企业制定生产计划?

对于物料及产能规划与现场详细作业排程而言&#xff0c;企业常因无法确实掌握生产制造现场实际的产能状况及物料进货时程&#xff0c;而采取有单就接的接单政策与粗估产能的生产排程方式&#xff0c;但又在提高对顾客的服务水平及允诺交期的基本前提下&#xff0c;导致生产车间…

Redis配置文件详解

容量单位不区分大小写&#xff0c;G和GB有区别 可以使用 include 组合多个配置问题 网络配置 日志输出级别 日志输出文件 持久化规则 由于Redis是基于内存的数据库&#xff0c;需要将数据由内存持久化到文件中 持久化方式&#xff1a; RDBAOF RDB文件相关 主从复制 Security模…

【建立逻辑结构】

前言 这是【Windows Server 2016 服务器配置与管理】的一些实操 下面是我自己做实验过程当中的一些简单记录&#xff0c;可能会有小错误&#xff0c;欢迎大家的指正&#xff01; Slogan&#xff1a;日拱一卒&#xff0c;功不唐捐&#xff01;&#xff01;&#xff01; 问答题 …

【重识云原生】第四章云网络6.4.5.2节——Deployment配置详细说明

1 deployment配置说明 1.1 deployment的资源清单文件 主要字段说明&#xff1a; 全量字段说明&#xff1a; apiVersion: apps/v1 #版本号 kind: Deployment #类型 metadata: #元数据 name: #rs名称 namespace: #所属命名空间 labels: #标签 controller: deploy spec: #详…

Linux自动挂载 (autofs)

个人主页&#xff1a;&#x1f497;wei_shuo的个人主页 &#x1f3c0; Hello World &#xff01;&#x1f3c0; 文章目录实现自动挂载-autofsautofs工具简单使用autofs配置详细说明自动挂载资源有两种格式&#xff1a;相对路径挂载法绝对路径挂载法优化 Linux 系统性能安装 Tun…

动态代理详解

想要更加透彻的理解动态代理&#xff0c;首先要熟悉下静态代理 一、静态代理 总结来说&#xff1a;目标类和代理类实现了相同的接口&#xff0c;在代理类中依赖了目标类&#xff0c;代理类的方法中调用了目标类的方法&#xff0c;并做了一些增强性的工作。 1、实现静态代理&…

ROS|乌龟TF变换案例分析

1. 相关源码内容 1.1 turtle_df_demo.launch <launch><!-- Turtlesim Node--><node pkg"turtlesim" type"turtlesim_node" name"sim"/><node pkg"turtlesim" type"turtle_teleop_key" name"tel…

如何快速创建 GCDW 实例

GCDW 实例需云用户注册 GCDW 租户成功后&#xff0c; GBASE 云服务系统给租户分配独 立的实例&#xff0c; 同时创建租户的数据库根用户&#xff0c; 根用户即为该实例的超户&#xff0c; 拥有该实例 的最高权限&#xff0c; 租户可以通过根用户登录自己的实例管理数据&#xf…

Centos7 单机单网卡 RDO 安装 OpenStack

文档 OpenStack 涵盖太多知识量&#xff0c;总是找不到一个称心的官方文档 OpenStack Installation Guide for Red Hat Enterprise Linux and CentOS 这个是中文版的&#xff0c;但是 UPDATED: 2017-06-12 11:14 &#xff0c;很古老了&#xff01;基本概念和思想还是一样的 h…

SiO2/罗丹明B荧光杂化纳米微球/硅钼比核壳结构二氧化硅微球钼酸钙荧光粉的性能

SiO2/罗丹明B荧光杂化纳米微球性能制备&#xff1a; 在甲苯存在下的反相微乳液体系中,将γ-缩水甘油醚氧丙基三甲氧基硅烷(KH560)与罗丹明B进行预反应&#xff1b;再与正硅酸乙酯( TEOS)经原位溶胶-凝胶反应,制备SiO2/罗丹明B荧光杂化纳米微球.通过FTIR、UV-Vis、TEM、TG和光致…

聚焦 | 电力行业国产操作系统迎来大市场,麒麟信安积极承接发展新机遇

近年来&#xff0c;针对信息安全的外部环境不确定性加剧&#xff0c;作为关系到国计民生的电力行业&#xff0c;加速了自主创新的步伐。 从2009年起&#xff0c;电力行业就开始采用拥有自主核心技术的软硬件设施&#xff0c;到如今&#xff0c;整个电力行业已普遍完成了调度自动…

4.<tag-排序和TopK问题的三种典型解法>补充: 面试题 17.14. 最小K个数 + lt.215-数组中的第K个最大元素 dbc

面试题 17.14. 最小K个数 [案例需求] TopK问题很普遍, 解题套路也很简单, 无非就是排序, 运用最基础的排序(如Array.sort(nums))复杂度为nlogn, 或者使用堆, 复杂度为nlogk, 或者在快排的基础上进行减治 详细参见此文: 点我 [思路分析一, 直接排序] 对原数组从小到大排序后取出…