物理/逻辑/虚拟内存地址之间的差异

2024-01-17

我对操作系统中的术语物理/逻辑/虚拟地址有点困惑(我使用 Linux-open SU​​SE)

这是我的理解:

  1. 物理地址-当处理器处于系统模式时,处理器使用的地址是物理地址。

  2. 逻辑地址-当处理器处于用户模式时,使用的地址是逻辑地址。无论如何,通过添加带有偏移值的基址寄存器,这些都映射到某个物理地址。它在某种程度上提供了一种内存保护。

  3. 我曾经遇到过这样的讨论:虚拟地址和逻辑地址/地址空间是相同的。这是真的吗?

非常感谢任何帮助。


我的答案对于运行在现代 Linux 系统上的 Intel CPU 来说是正确的,而且我说的是用户级进程,而不是内核代码。尽管如此,我认为它会给你一些足够的洞察力来思考其他可能性

地址类型

关于问题3:

我遇到过虚拟和逻辑的讨论 地址/地址空间是相同的。这是真的吗?

据我所知,它们是相同的,至少在英特尔处理器上运行的现代操作系统中是这样。

在解释更多内容之前,让我尝试定义两个概念:

  • 实际地址:RAM 芯片中某物物理位置的地址。
  • 逻辑/虚拟地址:您的程序用来访问其内容的地址。它通常稍后由硬件芯片转换为物理地址(大多数情况下,甚至 CPU 都没有真正意识到这种转换)。

虚拟/逻辑地址

虚拟地址是一个虚拟地址,操作系统以及称为 MMU(内存管理单元)的硬件电路欺骗您的程序,它是在系统中单独运行的,它拥有整个地址空间(拥有 32 位系统意味着您的程序会认为它有 4 GB RAM;粗略地说)。

显然,如果您同时运行多个程序(您总是这样做,GUI、Init 进程、Shell、时钟应用程序、日历等),则这将不起作用。

将会发生的情况是,操作系统会将大部分程序内存放在硬盘中,它使用最多的部分将出现在 RAM 中,但是,嘿,这并不意味着它们将拥有您和您的程序的地址知道。

Example:您的进程可能有一个名为 (counter) 的变量,该变量被赋予虚拟地址 0xff(可以想象......),另一个名为 (oftenNotUsed) 的变量被赋予虚拟地址 (0xaa)。

如果您在所有链接发生后读取编译代码的汇编,您将使用这些地址访问它们,但是(oftenNotUsed)变量不会真正存在于 RAM 中的 0xaa 处,它将位于硬盘中因为该进程没有使用它。

此外,变量(计数器)可能不会物理上位于(0xff),它将位于 RAM 中的其他位置,当您的 CPU 尝试获取 0xff 中的内容时,MMU 和操作系统的一部分将进行映射从 RAM 中真正可用的位置获取该变量,CPU 甚至不会注意到它不在 0xff 中。

现在,如果您的程序要求 (oftenNotUsed) 变量,会发生什么? MMU+OS会注意到这个“未命中”,并将其从硬盘中为CPU获取到RAM中,然后将其交给CPU,就好像它位于地址(0xaa)中一样;此获取意味着 RAM 中存在的一些数据将被发送回硬盘。

现在想象一下它为系统中的每个进程运行。每个进程都认为自己有 4GB RAM,实际上没有人拥有,但一切正常,因为每个人的程序的某些部分在 RAM 中物理可用,但大部分程序驻留在硬盘中。不要将HD中的这部分程序存储器与您可以通过文件操作访问的程序数据混淆。

Summary

虚拟地址:您在程序中使用的地址,即您的 CPU 用于获取数据的地址,不是真实的,而是通过 MMU 转换为某个物理地址;每个人都有一个,其大小取决于您的系统(运行 32 位的 Linux 有 4GB 地址空间)

实际地址:如果您在操作系统之上运行,您将永远无法到达该地址。这是您的数据(无论其虚拟地址如何)驻留在 RAM 中的位置。如果您的数据来回发送到硬盘以便为其他进程提供更多空间,这种情况将会改变。

我上面提到的所有内容,虽然是整个概念的简化版本,但都是所谓的计算机系统的内存管理部分。

该系统的后果

  • 进程无法访问彼此的内存,每个进程都有自己单独的虚拟地址,并且每个进程都会对不同区域进行不同的转换,即使有时您可能会发现两个进程尝试访问相同的虚拟地址。
  • 该系统作为缓存系统运行良好,您通常不会使用可用的整个 4GB,那么为什么要浪费它呢?让其他人分享并让他们也使用它;当您的进程需要更多数据时,操作系统将从硬盘中获取您的数据并替换其他进程的数据,当然这是有代价的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

物理/逻辑/虚拟内存地址之间的差异 的相关文章

  • 如何重新编译单个内核模块?

    通常内核源代码存储在 usr src linux 2 6 x 为了避免在修改模块的源代码时重新编译整个内核 如何重新编译该模块 切换到源代码树的根目录并运行以下命令 make modules SUBDIRS drivers the modu
  • 在 strace 中捕获 vDSO

    我想知道是否有一种方法可以捕获 换句话说观察 vDSO 调用 例如gettimeofday in strace 另外 有没有一种方法可以在不加载的情况下执行二进制文件linux vdso so 1 标志或环境变量 最后 如果我编写一个程序来
  • 如何设置 intel_idle.max_cstate=0 来禁用 c 状态?

    我想在我的计算机上禁用 c 状态 我在 BIOS 上禁用了 c state 但没有获得任何结果 不过 我找到了一个解释 大多数较新的 Linux 发行版 在配备 Intel 处理器的系统上 使用 intel idle 驱动程序 可能编译到内
  • Linux 如何在 x86-64 中支持超过 512GB 的虚拟地址范围?

    Linux 中 x86 64 的用户虚拟地址空间为 47 位长 这本质上意味着 Linux 可以映射大约 128 TB 虚拟地址范围的进程 然而 令我困惑的是 x86 64 架构支持 ISA 为每个进程定义的 4 级分层页表 排列为基数树
  • 尝试将 GCC 特定的 asm goto 移植到 Clang

    我一直在尝试将一些 GNU 扩展转换为实际的标准 C 这样它就可以在 clang 上运行 知道标准 C 而不是 GNU 扩展 我有点不知所措 asm goto 1 STATIC KEY INITIAL NOP pushsection jum
  • /dev/mem的访问权限

    我有一系列关于 dev mem 网上很多文章 好像都提到了 dev mem作为通往 Physical RAM 但如果我是对的 dev mem是通往 Physical Address Space 处理器的控制寄存器可能包括许多硬件外设的控制寄
  • 如何在 Ada 中直接访问内存地址?

    所以我是 Ada 的新手 我正在尝试在其中编写内核 但我似乎找不到任何关于如何正确执行此操作的好信息 在 C 语言中 我会这样写 unsigned char videoram char 0xB8000 videoram 0 65 直接访问视
  • 如何在Linux内核中启用CONFIG_PREEMPT选项?

    我是 Linux 内核编程的新手 尝试在 x86 64 上使用旧内核 Linux 2 6 32 我想启用其中的 CONFIG PREEMPT 选项 但找不到有关如何执行此操作的信息 我可以使用我的首选选项编译新内核 但不知道在这种情况下我需
  • 套接字对和一对无名管道有什么区别吗?

    我不仅想知道用户端的差异 还想知道 Linux 内核实现中的差异 共同部分 管道是单向的 因此需要两个管道才能进行双向通信 而套接字对是双向的 管道始终是面向流的 而套接字对可以是面向数据报的 套接字对正常AF UNIX套接字 这意味着辅助
  • 在执行期间访问.eh_frame数据

    我正在尝试访问以下内容 eh frame正在运行的程序的一部分 具体来说 该程序是 Linux 内核 2 6 34 8 这 eh frame包含用于异常处理的有用数据 我想在内核代码内部使用它 该部分已经由以下人员编写gcc readelf
  • 缓冲区溢出(与)缓冲区溢出(与)堆栈溢出[重复]

    这个问题在这里已经有答案了 可能的重复 堆栈溢出和缓冲区溢出有什么区别 https stackoverflow com questions 1120575 what is the difference between a stack ove
  • 如果物理内存的大小是2^32-1,那么虚拟内存的大小是多少?

    我知道物理地址是 32 位长 但是如何通过这些信息找出虚拟内存的大小 虚拟内存地址空间的总大小为2 32x86架构和更大 目前约为 2 48 x64建筑学 然而 操作系统通常会保留一部分空间 因此 32 位应用程序不一定能一次寻址 4GB
  • 从 Java 访问文件名中带有空格的文件

    我想从java程序访问文件名中有空格的目录中的文件 但它不访问文件 场景是我在文件中有文件名 iread 从该文件中读取文件名 但无法在 java 中打开带有空格的文件 我们使用 File exist 函数来检查文件是否存在 但它返回 fa
  • 索引数组时应该始终使用 size_t 吗?

    我需要使用吗size t总是在索引数组时即使数组没有大到超过 int 的大小 这不是我应该什么时候使用的问题size t 我只想知道 例如 一个程序是否具有 2GB 可用内存 所有这些字段都可以通过 int32 进行索引 但该内存 虚拟内存
  • 如何在 Linux 内核空间使用 ioctl()?

    可以打电话吗ioctl来自 Linux 内核模块 谁能提供一个如何使用它的例子吗 您可以尝试拨打电话sys ioctl 如果内核是用以下命令编译的 则它会被导出CONFIG COMPAT 或者 如果您有设备驱动程序struct file o
  • 用户空间栈和堆的内存布局

    最近在研究OS 网上有一张图 展示了用户空间和内核空间的内存布局 以及栈 堆等的布局 在这个图中我看到栈位于用户空间的最高内存地址 高于堆 数据段等 为了检查这一点 我在调试视图下使用了 vs2012 中的内存观察器窗口 这是我的代码 in
  • 使用Linux虚拟鼠标驱动

    我正在尝试实施一个虚拟鼠标驱动程序根据基本 Linux 设备驱动程序书 有一个用户空间应用程序 它生成坐标以及内核模块 See 虚拟鼠标驱动程序和用户空间应用程序代码 http www embeddedlinux org cn Essent
  • 是否可以将 CFLAGS 设置为 Linux 内核模块 Makefile?

    例如 常见设备模块的Makefile obj m jc o default MAKE C lib modules shell uname r build M shell pwd modules clean MAKE C lib module
  • “do { ... } while (0)”在内核代码中到底做了什么? [复制]

    这个问题在这里已经有答案了 可能的重复 当我们定义宏时 do while 0 有什么用 https stackoverflow com questions 923822 whats the use of do while0 when we
  • 操作系统崩溃的常见原因[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有兴趣了解 操作系统崩溃 不限于Windows崩溃 最常见的技术原因 从操作系统编程的角度 有哪些 我正在寻找一个不像 打开太多应用

随机推荐