Linux物理地址空间入门:从硬件到内核内存的基石

目录

一、物理地址空间是什么?

二、物理地址空间的构成:不仅仅是内存

三、Linux内核如何管理物理地址空间

(1)物理内存的碎片化问题

(2)物理地址的分区管理

(3)物理地址与内核的直接映射

四、物理地址和虚拟地址的关系   


一、物理地址空间是什么?

        对于刚刚接触Linux的新手而言,物理地址空间是理解内存的第一道门槛。他是硬件与内核交互的核心纽带,也是程序最终运行时候的真实地点。

        简单来说,物理地址空间是硬件层面的“内存地图”,他主要是由cpu和内存控制器定义的,可以直接访问的地址范围。就好比有许多个格子,每一个编号对应一个格子,这个编号就是物理地址。

        物理地址空间有两个关键特性:

(1)硬件决定性:地址范围由CPU位数和内存控制器决定。比如32位CPU理论上最大支持4GB的物理地址空间,因为他有32根地址线,2^32次方刚好对应4GB的编号。而64位CPU目前理论值远超实际硬件的地址范围,主流硬件支持48位物理地址,即256TB。

(2)直接关联性:物理地址直接对应硬件存储单元,CPU可以通过物理地址直接访问这些硬件资源,而不需要额外的地址转换或映射。(因为许多硬件厂家就预定了物理地址范围,即CPU只能去这些地址访问,否则硬件识别不了)

二、物理地址空间的构成:不仅仅是内存

        很多人在学习的时候,会误认为物理地址空间仅仅对应我们插在主板上的内存条,但实际上他包含了计算机中所有需要通过硬件访问的硬件资源,主要分为以下几类:

(1)DRAM动态随机存取存储器:就是我们平常说的内存,是物理地址空间中最为核心的部分,用于临时存放程序的数据和程序。他的特点是可读可写,速度快,掉电丢失。

(2)ROM/Flash:用于存储固件程序(如BIOS、UEFI等)在计算机启动的时候,CPU会从ROM的固定物理地址开始执行程序(在计算机启动的时候,CPU还没有加载操作系统,它不知道自己应该从哪里开始执行,所以必须预设一个固定地址,从这里开始初始化硬件,并加载操作系统)。这部分地址通常是只可读的(或者在烧录的时候可写)

(3)外设地址空间:计算机的显卡、网卡等外设。他们的控制寄存器和数据缓冲区也会被映射到物理地址空间中。例如CPU向网卡发送数据的时候,实际上是向物理地址空间的某个特定地址写入数据。

        虽然他们都是物理地址空间的构成部分,但是我们说了CPU由于地址线的限制,比如32位CPU只能寻址到4GB空间,所以他们一定是属于这4GB的一部分。

        当然我们这里说的是内存映射方式,至于IO映射方式不在物理地址空间的4GB中,我们更多使用的是内存映射,这里不再讨论IO映射。

为什么硬件必须有自己厂商固定好的地址?

        其一,在早期没有操作系统的时候,不存在虚拟地址空间、页表等说法,所以CPU在执行的时候直接操作的就是物理地址(比如单片机)。但是各个硬件设备如果没有规定好的地址范围,可能网卡、和键盘起冲突了,都规定在了同样的地址上,那么此时CPU访问该物理地址就不知道是谁了。所以形成了一种约定,什么设备应该放在什么地址,如果不遵守这个规则,CPU就无法通过BIOS程序写死的地址中找到对应的硬件设备。

        其二,CPU在上电之后会执行BIOS程序,在这个程序之中,首先要做的就是硬件检测,看看这些硬件设备能不能正常运行,有没有哪里损坏。这个过程中还没有加载操作系统,所以不可能存在虚拟地址以及页表的概念。之后才会进行硬件初始化,加载引导程序开始加载操作系统,并将控制权从BIOS交给操作系统。

        但并非所有的硬件都是CPU直接通过物理地址访问(虽然硬件只认物理地址)。一般对于需要快速响应的设别,CPU会直接通过物理地址的对应设备的寄存器其访问,减少了页表这一层转换,提高了效率。

        然而对于大块硬件资源(启动的时候仍然是通过物理地址),如显卡的显存、网卡的缓冲区,因为对于大量的数据信息,可能该设备的寄存器根本不够用,比如要渲染某个游戏画面,往往需要几个GB的数据。

        操作系统会给这些物理地址分配一个虚拟地址,然后通过页表映射到实际物理地址。这样做的好处是应用程序不需要知道物理地址,只需要操作虚拟地址,且操作系统可以通过页表权限控制防止应用程序错误修改硬件资源。

三、Linux内核如何管理物理地址空间

        物理地址是硬件资源,而操作系统的任务就是高效、安全的管理这些资源。其管理逻辑主要围绕着以下几个关键点展开:

(1)物理内存的碎片化问题

        物理内存由连续的页框(通常为4kb)组成,就好像一张张A4纸,每次使用和回收的时候,由MMU内存管理单元一页一页的分配,但是实际软件的数据可能并不存放在一张A4纸中,即两张各存一部分。如果频繁的申请内存以及释放,就会导致碎片问题,即存在大量的页都被一部分小数据占用,就好像每张A4纸写几个孤零零的字,由于他们已经被使用了,所以不能被回收成完整的大页。也就是不能申请很大的连续空间,比如1MB的连续空间。

        为了解决这个问题,Linux内核采用伙伴系统来管理空闲页。就和我们之前做过的一个项目tcmalloc类似的内存池技术类似。

(1)把空闲页按照1、2、4、8这种形式分组,每一组称为一个伙伴块

(2)当需要分配 n 页内存时,寻找最小的、大于等于 n 的伙伴块,若块过大则拆分;释放时若相邻块空闲则合并。

(2)物理地址的分区管理

        内核会将物理地址划分为不同的区域,针对不同区域采取不同的管理策略

(1)ZONE_DMA:直接内存访问(DMA)区域,地址范围较低(通常 16MB 以下),供需要 DMA 传输的外设使用(如老式硬盘控制器)。

(2)ZONE_HIGHMEM:高端内存区域(32 位系统中超过 896MB 的部分),内核不能直接映射,需要通过临时映射机制访问(64 位系统因地址空间充足,通常无需此区域)。

之所以直接的线性映射区只有896MB,是因为剩余的128MB需要留给其他用途,如映射IO设备的物理地址、内核自身的代码数据等。

(3)ZONE_NORMAL:常规可直接映射区域,内核可以直接访问的物理内存(32 位系统中通常为 1GB 左右)。常规映射区域是给内核使用的,内核范围是3GB-4GB。所以这部分的虚拟地址=物理地址0-896MB+3GB。

(3)物理地址与内核的直接映射

        Linux 内核自身需要快速访问物理内存,因此会将物理地址空间的一部分(通常是 ZONE_DMA 和 ZONE_NORMAL)直接线性映射到内核虚拟地址空间中。例如,物理地址 0x100000 会被映射到内核虚拟地址 0xC0100000(32 位系统)(物理地址增加3GB),这种映射是固定的、一对一的,内核通过简单的地址计算就能访问物理内存,无需复杂的页表查询。

四、物理地址和虚拟地址的关系   

  • 物理地址空间是 “仓库的真实货架编号”,每个编号对应唯一的货架位置,仓库管理员(内核)必须知道它才能找到货物。​
  • 虚拟地址空间是 “给客户的取货编号”,客户(用户程序)只需要记住这个编号,无需关心货物实际放在哪个货架。​
  • 即客户来取货的时候,只能通过仓库管理员。而仓库管理员掌握了一张页表,知道用户取货编号和仓库真实编号的映射关系。

两者的映射关系由内核通过页表维护:用户程序使用虚拟地址访问内存时,CPU 的内存管理单元(MMU)会根据页表将虚拟地址转换为物理地址,最终访问实际的硬件内存。这种机制的好处是:​

  • 隔离进程:每个进程都有独立的虚拟地址空间,互不干扰。​
  • 灵活利用内存:即使物理内存不足,也能通过 swap 分区(虚拟内存)暂时存储数据。​
  • 安全性:用户程序无法直接访问物理地址,防止恶意程序破坏系统。

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

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

相关文章

解决win10下Vmware虚拟机在笔记本睡眠唤醒后ssh连接不上的问题

背景 在使用Vmware虚拟机时经常会遇到这样一个问题:当笔记本电脑从睡眠状态唤醒后【关掉笔记本盖子一段时间,再打开电脑】,ssh连接不上虚拟机,需要将Vmware的网卡在控制面板中禁用再重启才可以。 解决方法 使用Win10的任务计划程序…

20250721

P5357 【模板】AC 自动机 - 洛谷 主要是构建fail树 /* 我们可以知道的是,当访问一个点x时,接下来需要跳转其fail[x],以此类推,如果在某个fail[x]上出现了一个字符串,那么相应的统计次数应该加1,然后当访…

Maven

目录 1 什么是 Maven 2 Maven 核心功能 项目构建 依赖管理 Maven Help 插件 3 Maven 仓库 本地仓库 中央仓库 私有服务器(简称私服) 4 Maven 设置国内源 配置当前项目 setting 设置新项目的 setting 1 什么是 Maven Maven 是一个项目管理工…

RabbitMQ核心组件浅析:从Producer到Consumer

作为分布式系统中异步通信的扛把子,RabbitMQ 凭借其高可靠、灵活路由的特性,几乎是每个后端开发者的"必备技能"。但很多新手刚接触时,常被各种组件名称绕晕——Broker、Exchange、Queue、vhost…这些"术语炸弹"到底啥关系…

c#转python第四天:生态系统与常用库

作为系列文章的第 4 篇,本文将聚焦 Python 生态中最具代表性的技术栈,通过与 C# 对应技术的横向对比,帮助开发者快速掌握 Python 在数据处理、Web 开发和异步编程领域的核心优势。无论是有 C# 基础想转 Python 的开发者,还是需要在两种语言间做技术选型的团队,都能从本文的…

nginx定期清理日志

原创作者:运维工程师 谢晋 nginx定期清理日志 创建脚本clean_nginx_logs.sh # vi clean_nginx_logs.sh#!/bin/bash# 定义日志文件路径 LOG_DIR"/var/log/nginx" ACCESS_LOG"access.log" ERROR_LOG"error.log"# 定义保留日志的天数…

【Go语言-Day 22】解耦与多态的基石:深入理解 Go 接口 (Interface) 的核心概念

Langchain系列文章目录 01-玩转LangChain:从模型调用到Prompt模板与输出解析的完整指南 02-玩转 LangChain Memory 模块:四种记忆类型详解及应用场景全覆盖 03-全面掌握 LangChain:从核心链条构建到动态任务分配的实战指南 04-玩转 LangChai…

YOLO多模态融合 | 从 DEA 到 DEFA:动态卷积+交叉注意力的创新融合

本教程基线代码为开源项目 YOLOFuse 请注意:并非在所有数据集上都能带来性能提升。DEFA 模块是我基于自身思路改进的——在您的数据集上是否有效,还需您自行实验验证,无法保证一定会有所增益。 一、背景与动机 在多模态目标检测场景中&#…

基于SEP3203微处理器的嵌入式最小硬件系统设计

目录 1 引言 2 嵌入式最小硬件系统 3 SEP3202简述 4 最小系统硬件的选择和单元电路的设计 4.1 电源电路 4.2 晶振电路 4.3 复位及唤醒电路 4.5 存储器 4.5.1 FLASH存储 4.5.2 SDRAM 4.6 串行接口电路设计 4.7 JTAG模块 4.8 扩展功能(LED) …

PCIe RAS学习专题(3):AER内核处理流程梳理

目录 一、AER内核处理整体流程梳理 二、AER代码重要部分梳理 1、AER初始化阶段 2、中断上半部 aer_irq 3、中断下半部 aer_isr 3.1、aer_isr_one_error 3.2、find_source_device 3.3、aer_process_err_devices 3.4、handle_error_source 3.5、pcie_do_recovery 整体逻…

Window延迟更新10000天配置方案

1.点击"开始"菜单,搜索"注册表编辑器",点击"打开"。2.找到"\HKEY LOCAL MACHINE\SOFTWARE\Microsoft\WindowsUpdate\Ux\Settings"路径。3.右面空白处右键新建一个32位值,命名为FlightSettingsMaxPau…

TCP/IP 哲学:端到端的 Postel 定律

实际上这是互联网哲学,但 TCP/IP 是互联网的事实标准,也是互联网的唯一实例,因此 TCP/IP 等同于互联网。 我写过很多 TCP/IP 发展史的随笔,于宏观,我希望理解互联网何以至此,于微观,希望理解 TC…