簡體   English   中英

將內存映射到另一個地址

[英]Map memory to another address

X86-64,Linux,Windows。

考慮一下,我想做一些“免費啟動標簽指針”。 基本上我想要有兩個指針指向相同的實際內存塊但其位不同的指針。 (例如,我希望GC集合使用一個位或出於其他原因)。

intptr_t ptr = malloc() 
intptr_t ptr2 = map(ptr | GC_FLAG_REACHABLE) //some magic call

int* p = int*(ptr);
int* p2 = int*(ptr2);
*p = 10;
*p2 = 20;
assert(*p == 20)
assert(p != p2)

在Linux上,mmap()相同的文件兩次。 Windows上也是如此,但它有自己的一套功能。

將相同的內存(如Ignacio提到的POSIX上的mmap ,Windows上的MapViewOfFile )映射到多個虛擬地址可能會為您提供一些有趣的一致性謎題(在另一個地址讀取時,在一個地址寫入是否可見?)。 或者可能不是。 我不確定所有平台保證是什么。

更常見的是,只需在指針中保留幾個位,並根據需要移動。

如果所有對象都與8字節邊界對齊,則通常只將標記存儲在指針的3個最低有效位中,並在解除引用之前將其屏蔽掉(如thkala所述)。 如果選擇更高的對齊,例如16字節或32字節,則可以使用3或5個最低有效位進行標記。 等效地,選擇一些最重要的位用於標記,並在解除引用之前將其移除。 (有時使用非連續位,例如將指針打包到IEEE-754浮點數(2 23個值)或雙精度(2 51個值)的信令NaN時。)

繼續指針的高端,x86-64的當前實現使用64位指針(0x0000000000000000-0x00007fffffffffff + 0xffff800000000000-0xffffffffffffffff)中的最多48位,而Linux和Windows僅將第一個范圍內的地址分配給用戶空間,留下17個最重要的位,可以安全地屏蔽掉。 (但這既不便於攜帶,也不保證將來保持真實。)

另一種方法是停止考慮“指針”並簡單地將索引用於更大的內存數組,就像JVM使用-XX:+UseCompressedOops 如果您已分配512MB池並存儲8字節對齊的對象,則有2 26個可能的對象位置,因此除索引外,32值還有6位可用。 取消引用將需要將對齊的索引乘以數組的基地址,保存在其他地方(對於每個“指針”都是相同的)。 如果你仔細研究一下,這只是對前一種技術的概括(它總是以0為基礎,其中的東西與實際指針對齊)。

曾幾何時,我參與了Prolog實現,該實現使用以下技術在指針中有備用位:

  • 使用已知對齊方式分配內存區域。 malloc()通常使用4字節或8字節對齊分配內存。 如有必要,請使用posix_memalign()來獲取具有更高對齊大小的區域。

  • 由於結果指針與多個字節的間隔對齊,但它表示字節精確的地址,因此您有一些備用位,根據定義,它們在存儲區指針中為零。 例如,4字節對齊為您提供指針LSB側的兩個備用位。

  • OR( | )你的標志與這些位,現在有一個標記指針。

  • 只要你在使用它進行內存訪問之前注意正確地屏蔽指針,你應該完全沒問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM