触摸 C 中的缓冲区

问题描述 投票:0回答:1

我需要确保一个内存缓冲区全部在物理内存中,并且在后续函数中访问它时不会发生页面错误,由于某些时序问题,该函数无法容忍页面错误。 缓冲区通常由许多保护页组成。

我想出了以下代码来解决这个问题:

#define PAGE_SIZE 4096
for (char* p = pbBuffer; (p < pbBuffer + cbBufferSize); *(volatile char*)p, p += PAGE_SIZE);
SubsequentFn(pBuffer, cbBufferSize); // Does not tolerate page faults.

这似乎有效,并且

volatile
关键字可以防止 C 编译器优化“几乎不执行任何操作”的 for 循环。 请参阅下面编译的机器代码:

    000000013F3F1AA7 c7 c1 78 56 34 12    mov         rcx, pbBuffer
    000000013F3F1AAE 48 8D 91 00 00 10 00 lea         rdx,[rcx+cbBufferSize]  
    000000013F3F1AB6 48 3B CA             cmp         rcx,rdx  
    000000013F3F1AB9 73 14                jae         Main+4Fh (013F3F1ACFh)  
    000000013F3F1ABB 0F 1F 44 00 00       nop         dword ptr [rax+rax]  
    
    000000013F3F1AC0 0F B6 01             movzx       eax,byte ptr [rcx]  
    000000013F3F1AC3 48 81 C1 00 10 00 00 add         rcx,1000h  
    000000013F3F1ACA 48 3B CA             cmp         rcx,rdx  
    000000013F3F1ACD 72 F1                jb          Main+40h (013F3F1AC0h)  
    000000013F3F1ACF ...

如您所见,指令

movzx eax,byte ptr [rcx]
触及内存,但寄存器
eax
在循环内不用于任何其他用途 - 这是预期的效果。

问:这是在缓冲区中触发

Guard Pages
的最佳方法还是有更好的方法? 该代码在某些情况下会崩溃吗?

c x86-64
1个回答
0
投票

如果没有操作系统级别的支持,您无法保证缓冲区将保留在物理内存中 - 如果操作系统遇到内存压力,它完全可以决定将缓冲区调出页面。

相反,请考虑使用特定于操作系统的 API 将缓冲区锁定到物理内存中。在 Linux 上,使用

mlock
;在 Windows 上,使用
VirtualLock
。这些函数将锁定指定的内存区域,防止其被调出。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.