标签: virtual-memory

fork 和内核中映射的用户空间内存的交互

考虑使用get_user_pages(或get_page)映射来自调用进程的页面的 Linux 驱动程序。然后将页面的物理地址传递给硬件设备。进程和设备都可以读取和写入页面,直到双方决定结束通信。特别地,在调用get_user_pages返回的系统调用之后,通信可以继续使用页面。系统调用实际上是在进程和硬件设备之间建立一个共享内存区域

我担心如果进程调用会发生什么fork(它可能来自另一个线程,并且可能在调用的系统调用get_user_pages正在进行中或稍后发生)。特别是,如果父级在fork后写入共享内存区域,我对底层物理地址了解多少(可能是因为copy-on-write而改变)?我想明白:

  1. 内核需要做什么来防御潜在的行为不端的进程(我不想创建安全漏洞!);
  2. 进程需要遵守哪些限制,以便我们的驱动程序的功能正常工作(即物理内存保持映射到父进程中的相同地址)。

    • 理想情况下,我希望子进程根本不使用我们的驱动程序(它可能exec几乎立即调用)来工作的常见情况。
    • 理想情况下,父进程在分配内存时不应采取任何特殊步骤,因为我们已有将堆栈分配的缓冲区传递给驱动程序的现有代码。
    • 我知道madvisewith MADV_DONTFORK,并且可以让内存从子进程的空间中消失,但它不适用于堆栈分配的缓冲区。
    • “当您与我们的驱动程序有活动连接时不要使用叉”会很烦人,但如果满足第 1 点,则可以作为最后的手段。

我愿意被指出文档或源代码。我特别查看了Linux Device Drivers,但没有发现这个问题得到解决。即使只是应用于内核源代码的相关部分的 RTFS 也有点让人不知所措。

内核版本不是完全固定的,而是最近的版本(比如 ??2.6.26)。如果重要的话,我们只针对 Arm 平台(目前是单处理器,但多核即将到来)。

fork shared-memory virtual-memory linux-kernel

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

在大型阵列上使用 VirtualAlloc 保留与提交 + 保留内存的优势

我正在编写一个 C++ 程序,它基本上适用于非常大的数组。在 Windows 上,我使用 VirtualAlloc 为我的数组分配内存。现在我完全理解了使用 VirutalAlloc 保留和提交内存的区别;但是,我想知道将内存逐页提交到保留区域是否有任何好处。特别是,MSDN ( http://msdn.microsoft.com/en-us/library/windows/desktop/aa366887(v=vs.85).aspx ) 包含对 MEM_COMMIT 选项的以下解释:

除非/直到实际访问虚拟地址,否则不会分配实际的物理页面。

我的实验证实了这一点:我可以保留和提交几 GB 的内存,而不会增加进程的内存使用量(如任务管理器中所示);只有当我实际访问内存时才会分配实际内存。

现在我看到很多例子认为应该保留大部分地址空间,然后逐页提交内存(或在一些更大的块中,取决于应用程序的逻辑)。然而,正如上面所解释的,在访问内存之前似乎并没有提交内存。因此,我想知道逐页提交内存是否有任何真正的好处。事实上,由于许多实际提交内存的系统调用,逐页提交内存实际上可能会减慢我的程序速度。如果我一次提交整个区域,我只需为一次系统调用付费,但内核似乎足够聪明,实际上只分配了我实际使用的内存。

如果有人能向我解释哪种策略更好,我将不胜感激。

winapi memory-management virtualalloc virtual-memory

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

了解 mac os 中的 vm_stat,如何将这些数字转换为类似于活动监视器的内容?

我正在尝试编写一个 mac os 程序来监视系统(类似于活动监视器)。我查看了 vm_stat 函数,当我运行它时,我得到了这个:

Mach Virtual Memory Statistics: (page size of 4096 bytes)
Pages free:                         438386.
Pages active:                       236438.
Pages inactive:                     113750.
Pages speculative:                   34293.
Pages wired down:                   225027.
"Translation faults":             11132566.
Pages copy-on-write:                319385.
Pages zero filled:                 6618647.
Pages reactivated:                   23071.
Pageins:                            421804.
Pageouts:                           153240.
Object cache: 14 hits of 24183 lookups (0% hit rate)
Run Code Online (Sandbox Code Playgroud)

但是,当我运行活动监视器时,我得到了类似的信息:

Page Ins: 1.61gb (8.00kb/sec)
Page outs: 598.6 MB
Run Code Online (Sandbox Code Playgroud)

我有一个关于此的问题:为什么 vmstat 中的空闲页面如此之小(与活动监视器相比)

memory cocoa virtual-memory activity-monitor

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

运行 java -version 时“无法为对象堆保留足够的空间”

我知道这是一个常见的问题。我想知道从哪里开始。

在 windows server 2008 上运行 java,我们有 65GB 内存,它显示 25GB 空闲。(目前有几个人正在运行进程)。

systeminfo | grep -i memory

显示:

总物理内存:65, 536 MB
可用物理内存:26,512MB
虚拟内存:最大大小 69,630 MB
虚拟内存:可用 299 MB
虚拟内存:使用中:69、331 MB。 

真的只是想知道我如何解决这个问题。

  • 我从哪里开始?
  • 使用的虚拟内存多于物理内存是什么意思,这就是 java 无法启动的原因吗?
  • java 是否要使用虚拟内存而不是物理内存?

java -version

给我:

Error occured during initialization of VM could not reserve enough space for object heap

更具体的问题:

  • 为什么JVM不想使用空闲的物理内存?
  • java -version如果不指定 Xms 参数,java 命令(如)要使用多少内存?
  • 简单地分配更多的虚拟内存是解决问题的好方法吗?

java memory virtual-memory windows-server-2008

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

多级分页中的页表索引位数

处理器使用 36 位物理地址和 32 位虚拟地址,页框大小为 4 KB。每个页表条目大小为 4 个字节。一个三级页表用于虚拟到物理地址的转换,其中虚拟地址的使用如下:

位 30 - 31 用于索引到第一级页表
位 21 - 29 用于索引到第二级页表
位 12 - 20 用于索引到第三级页表
位 0 - 11 用作偏移量页面内

寻址一级、二级和三级页表的页表项中的下一级页表(或页框)所需的位数分别为?

这是 GATE 2008 中提出的一个问题。
我的分析: 最大页框数 =(物理地址大小)/(页面大小)= 2^36 / 2^12 = 2^24。因此,24 位就足以索引第 3 级页表中的页码。现在我们必须找出第 3 级将有多少页表。它给出了 9 位用于索引到第 3 级页表的情况。所以第 3 级有 2^9 个页表。这意味着 2^32 个虚拟空间包含在 2^9 个页表中,因此每个页表的条目 = 2^32/2^9 = 2^23。因此,l2 页表条目中需要 23 位来索引第三级页表中特定页表的条目。从 L1 页表到 L2 中有 2^9 个页表,我们需要到达这些 2^9 个页表中的任何一个。所以在 L1 中需要 9 位。

这种分析不知何故似乎不正确。我很困惑。有人可以解释这些概念吗?

paging operating-system virtual-memory

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

对于程序的不同运行,全局变量的地址是否相同?

考虑以下代码片段

int i=10;
int main()
{
    cout<<&i;
}
Run Code Online (Sandbox Code Playgroud)

一旦为程序生成了 exe,程序不同运行的输出是否相同?假设操作系统支持虚拟内存

编辑:问题特定于存储在数据段中的全局变量。由于这是第一个全局变量,地址应该相同还是不同?

c++ virtual-memory

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

当条目被从 TLB 驱逐时更新页表

当条目从 TLB 中驱逐时,页表是否更新?如果是这样,为什么?页表中更新了哪些信息?我认为当被驱逐的页面干净时不需要更新页表。

类似地,在 TLB 中缓存(引入)页面时是否更新了页表?

operating-system cpu-architecture virtual-memory tlb page-tables

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

PAGE_EXECUTE 和 PAGE_EXECUTE_READ 有什么区别?

Windows 提供了 2 个不同的内存保护常量(例如VirtualProtect的第三个参数),它们的行为似乎相似:PAGE_EXECUTEPAGE_EXECUTE_READ

它似乎PAGE_EXECUTE应该是仅执行权限(没有读取)。但是,没有读取的执行权限没有多大意义,因为 CPU 需要先从内存中读取指令,然后才能解码和执行它们。此外,我在这里读到确实PAGE_EXECUTE内存也允许从中读取。

那么.. 为什么有两个不同的常量,它们之间有什么区别?为什么我应该更喜欢一个?

windows winapi virtual-memory

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

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

假设一个简单的 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
查看次数