2011-10-11 23 views
5

我已經寫幾個程序,結果發現,在64位的編譯時,所述存儲器映射段(爲共享對象)的地址,存儲器映射段(其中,例如,共享對象和共享存儲器被保持)是總是位於7f9aca84a000-7fff88400000附近,但從未完全相同。ELF64/x86_64的,並開始

我想知道是否有一個固定的起始地址x86_64體系(ELF64)這個內存段或最大和最小範圍這部分是什麼?

這就是爲什麼我問這個問題。我們正在將一個系統從Tru64 UNIX遷移到Linux。該系統使用IPC Sys V共享內存的一個複雜的固定內存映射,並且在該段內使用鏈接列表從結構到另一個結構。由於這段代碼的大小和複雜性以及我們手頭上有限的時間,我們正試圖找到一種可靠的方法來修復共享內存的開始(有效地使用帶有指定地址的shmat來附加段)。 64位,虛擬地址空間非常巨大(48位有效的可能地址),選擇「安全」固定地址比32位更容易,風險更小。

回答

4

的x86-64的存儲器映射佈局在arch/x86/mm/mmap.c定義。正如你所看到的,有兩種策略:自上而下和自下而上。

自上而下分配是默認設置。它從堆棧的最大範圍(由堆棧rlimit定義)開始,低於128MB,由隨機偏移量調整,然後從那裏向後分配內存中的後續映射。

自下而上的分配是後備。它用於以下任一情況:

  • 堆棧rlimit是無限的;
  • 該過程具有ADDR_COMPAT_LAYOUT個性設置;或
  • sysctl的vm.legacy_va_layout非零。

在自底向上分配的情況下,映射區域被分配逐漸變高的地址,起​​始於TASK_SIZE/3,由隨機偏移調整。在x86-64上的TASK_SIZE0x800000000000,所以自下而上的分配將從0x2AAAAAAAAAAA開始。

我會建議一個適合您的固定映射的適當的洞,這應該是好的在任一分配策略下都是在2 * TASK_SIZE/3左右 - 我會用0x500000000000

+0

謝謝你的洞察力。我會環顧你指出的所有信息。 – Huygens

+0

所以不能給我們自己的起始地址? – sdkie

3

我沒有給你一個直接的答案(尚未!),但我可以說,我已經有成功的映射內存以及外面更高的內存範圍。例如:

#include <stdio.h> 
#include <sys/mman.h> 
#include <stdint.h> 

#define ADDRESS 0x700000000 

int main(int argc, char *argv[]) { 
    uint64_t *map = mmap((void *)ADDRESS, 4096, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); 

    map[0] = 64; 

    printf("Value: %lu\n", map[0]); 

    munmap(map, 4096); 

    return 0; 
} 

恐怕我現在沒有時間查看內核源代碼,但我一定會稍後再看看。我一直想知道這個問題的答案是什麼。 。 。

+0

感謝您提供的信息,系統V IPC的代碼中使用了類似的技術,我們在調用shmat時設置了一個特殊地址。請參閱手冊頁摘錄:如果shmaddr不是NULL,並且在shmflg中指定了SHM_RND,則附加發生在與shmaddr相等的地址處,舍入爲SHMLBA的最接近倍數。否則,shmaddr必須是發生附接的頁面對齊地址。 – Huygens

+0

難點在於確定一個正確的地址,就像你建議的地址:0x700000000。我們希望能夠清楚地證明我們的選擇。 – Huygens

4

有一個固定的起始地址mmaped段?

號Linux支持ASLR(地址空間佈局隨機化),這意味着,在節目地址具有隨機性的一些元件。這是爲了使一些利用不太可能成功。此外,可能有些內核補丁實施不同的ASLR策略(它們適用於普通的x86),想想PaX,exec-shield,...

因此,如果您想使用固定地址,則可能會使用MAP_FIXED ,就像@Ethereal推薦的那樣。