标签: virtual-memory

在没有虚拟内存支持的系统中进行链接和分页

  • 首先,虚拟内存是系统的硬件特性,还是仅由操作系统实现?

在链接时重定位期间,链接器将运行时地址分配给生成的可执行文件中的每个节和每个符号

  • 这些运行时地址是否对应于虚拟地址?

  • 如果生成可执行文件的系统不使用虚拟内存怎么办?

接下来,如果不使用虚拟内存,则应用程序的地址空间将限制为加载时重定位后操作系统为其分配的物理地址空间

  • 如果不使用虚拟内存,会出现页面错误吗?

我认为,确实如此:如果包含所请求的物理地址的物理页尚未存储在 RAM 中,则应该发生页错误,这是由操作系统页错误处理程序提供服务的

  • 最后,没有虚拟内存也可以进行分页吗?

我这样问是因为分页总是与虚拟内存一起提到,但似乎分页不需要虚拟内存的存在

谢谢

paging operating-system dynamic-linking virtual-memory static-linking

5
推荐指数
1
解决办法
1829
查看次数

内存地址什么时候分配?

考虑以下 CPU 指令,该指令获取地址 16777386(十进制)处的内存并将其存储在寄存器 1 中:

Move &0x010000AA, R1

传统上,程序在编译时被翻译为汇编(机器代码)。(让我们忽略更复杂的现代系统,例如抖动)。

但是,如果这个地址分配是在编译时静态完成的,操作系统如何确保两个进程不使用相同的内存?(例如,如果您同时运行相同的编译程序两次)。

问题:

程序如何以及何时分配其内存地址?

虚拟内存:

我了解大多数(如果不是全部)现代系统在硬件中使用内存管理单元来允许使用虚拟内存。地址空间的前几个八位字节用于引用哪个页面。如果每个进程使用不同的页面,这将允许内存保护。但是,如果这就是执行内存保护的方式,那么最初的问题仍然存在,只是这次如何分配页号?

编辑

中央处理器:

一种可能性是 CPU 可以通过强制操作系统在执行基于内存的指令之前分配进程 ID 来处理内存保护。然而,这只是猜测,需要 CPU 架构的硬件支持,我不确定 RISC ISA 的设计目的是什么。

memory operating-system memory-management virtual-memory

5
推荐指数
1
解决办法
1417
查看次数

有没有一种方法可以在 Darwin 上使用 `mmap` 和 Rust 中的超级页面?

mmapDarwin 的联机帮助页指定,为了与mmap超级页面(Darwin 相当于 Linux 的大页面)一起使用,VM_FLAGS_SUPERPAGE_SIZE_*应该使用标志。

我尝试在 Rust 中使用此功能,但在 Darwin 的 Rust libc 版本( i686x86_64 )中找不到这些常量。

mmap darwin virtual-memory rust huge-pages

5
推荐指数
0
解决办法
219
查看次数

与脚本所需的内存相比,为什么 NodeJS 在操作系统中占用如此多的虚拟内存?

我正在运行一个 5k loc Express 应用程序,其中包含许多其他依赖项,包括 Express。该应用程序称它需要大约 60 MB RAM RSS。但是,当查看我的 Linux 机器上的实际 RAM 使用情况时,top我发现它使用了约 1200 MB VIRT 内存,而仅占用了约 60 MB RES (RSS) 内存。

然后我编写了一个简单的test.js脚本来隔离案例:

setInterval(() => {
  console.log(JSON.stringify(process.memoryUsage()));
} , 1000);
Run Code Online (Sandbox Code Playgroud)

并开始使用:node test.js

它告诉我它使用了大约 30 MB RAM:

{"rss":30097408,"heapTotal":6537216,"heapUsed":3829224,"external":8272}
Run Code Online (Sandbox Code Playgroud)

再次查看top命令中的内存,它显示 RES 为 30 MB,但 VIRT 使用量约为 470 MB。

PID  USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
8498 ted       20   0  485948  29928  23540 S   0,3  0,8   0:00.44 node
Run Code Online (Sandbox Code Playgroud)

NodeJS 这样看起来并不轻量。 …

linux virtual-memory node.js

5
推荐指数
1
解决办法
1831
查看次数

链接器在链接时是否生成绝对虚拟地址

假设一个简单的 hello world in C,编译gcc -c为目标文件并反汇编为objdump如下所示:

_main:
       0:   55  pushq   %rbp
       1:   48 89 e5    movq    %rsp, %rbp
       4:   c7 45 fc 00 00 00 00    movl    $0, -4(%rbp)
       b:   c7 45 f8 05 00 00 00    movl    $5, -8(%rbp)
      12:   8b 05 00 00 00 00   movl    (%rip), %eax
Run Code Online (Sandbox Code Playgroud)

如您所见,内存地址是0, 1, 4, ..等等。它们不是实际地址。

链接目标文件并反汇编它看起来像这样:

_main:
100000f90:  55  pushq   %rbp
100000f91:  48 89 e5    movq    %rsp, %rbp
100000f94:  c7 45 fc 00 00 …
Run Code Online (Sandbox Code Playgroud)

macos assembly linker executable virtual-memory

5
推荐指数
1
解决办法
1316
查看次数

64 位 Windows 是否可以通过 7FFF'FFFF'FFFF 分配虚拟内存?

语境

我正在升级一个 .NET 库以支持 64 位。该库直接在 Windows 上的其他进程的内存中执行各种操作。我必须在两种类型IntPtr(最大正值 7FFF'FFFF'FFFF'FFFF)或UIntPtr(最大正值 FFFF'FFFF'FFFF'FFFF)之间进行选择来处理我的内存指针。网上有很多关于这两者的信息。IntPtr似乎是事实上的约定选择,因为它符合 CLS 并且大多数 .NET API 都依赖于它(参考Marshal来自InteropServices)。

问题

我决定打开一个 64 位进程并检查分配的内存区域,以及进程中加载​​的模块,以查看使用UIntPtr(addresses > 7FFF'FFFF'FFFF'FFFF)支持无符号指针是否有价值。如下面的屏幕截图所示,似乎内存地址不会加载符号,也不会分配超过 7FFF'FFFF'FFFF 的内存。这样做有什么具体原因吗?在某些情况下,Windows 可以根据该值分配内存区域吗?

作弊引擎(64 位)上的内存分配

c# windows x86-64 internals virtual-memory

5
推荐指数
1
解决办法
1167
查看次数

为什么 pmap 显示 strace 不显示的映射?

我正在调查一个进程的内存使用情况,该进程(意外地)保留了 TB 的VIRT. 如果我执行pmap该过程,我可以看到一些强大的分配,例如:

00007f39ea671000 317288696K rw---   [ anon ]
Run Code Online (Sandbox Code Playgroud)

我正在strace跟踪所有与内存相关的系统调用并记录它们的跟踪跟踪,从而运行我的进程。

strace -o ~/strace.out -f -e trace=mremap,mmap,munmap,brk -k <command>
Run Code Online (Sandbox Code Playgroud)

我希望能够在 中找到这个分配strace.out,所以我 grep 它:

cat strace.out | grep -A10 7f39ea671000
Run Code Online (Sandbox Code Playgroud)

我只看到这个调用mmap

106224 mmap(NULL, 201543680, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f39ea671000
 > /usr/lib/x86_64-linux-gnu/libc-2.29.so(mmap64+0x22) [0xf5252]
 > /usr/lib/x86_64-linux-gnu/libc-2.29.so(_IO_str_seekoff+0x2ff4) [0x84ab4]
 > /usr/lib/x86_64-linux-gnu/libc-2.29.so(_IO_str_seekoff+0x3e0b) [0x858cb]
 > /usr/lib/x86_64-linux-gnu/libc-2.29.so(__libc_malloc+0x22f) [0x869ff]
...
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?是否pmap显示了夸大的映射尺寸?或者我错过了一些系统调用?

linux mmap virtual-memory strace pmap

5
推荐指数
0
解决办法
556
查看次数

为什么 Linux 支持 0x7f 映射?

通过运行一个简单的程序,less /proc/self/maps我发现大多数映射都以55and开头7F。我还注意到每当我调试任何二进制文件时都会使用这些范围。

此外,该评论在这里表明,内核的确有些范围的偏好。

这是为什么?上述范围是否有更深层次的技术原因?如果我mmap在这些前缀之外手动翻页会有问题吗?

x86 x86-64 virtual-memory linux-kernel

5
推荐指数
1
解决办法
458
查看次数

linux 中的 force kill 命令 (kill -9) 是否会在 C++ 应用程序中使用 new 运算符清理动态分配的内存?

我有一个要在 Oracle Linux OS 上运行的 C++ 应用程序。

考虑一下,我用new运算符创建了几个对象。虽然我已经使用 delete 操作符来解除分配它,但是 force kill 命令不会到达这个实现。

但是,如果我强制终止 ( kill -9) 进程,动态分配的内存(使用new运算符)是否会被操作系统取消分配?由于我无法找到直接的答案,因此我想了解一些信息。

提前致谢。

c++ linux memory-management virtual-memory linux-kernel

5
推荐指数
1
解决办法
167
查看次数

为什么 malloc() 会导致轻微页面错误?

我正在尝试了解内存和页面错误,因此我编写了下面的代码来检查我的理解。我不明白为什么调用 malloc 会导致 MINFL 增加,因为 malloc() 不应该影响物理内存(据我所知)。

这是我的代码:

#include <stdio.h>
#include <stdlib.h>

void main() {
  printf("Before malloc\n");
  getchar();
  
  malloc(1 << 20);
  printf("After malloc\n");
  getchar();
}
Run Code Online (Sandbox Code Playgroud)

这些是 ps 命令的最终结果。

在进行 malloc 之前: 在malloc之前

malloc 之后: malloc之后

有两件事我不明白:

  1. 为什么 MINFL 会增加?
  2. 为什么VSZ增加1028而不是1024?

请帮忙并谢谢。

c malloc ps virtual-memory page-fault

5
推荐指数
1
解决办法
1467
查看次数