2014-04-04 71 views
0

我很清楚Window堆分配和堆棧堆等。雖然是Linux的新手,但我沒有太多的清晰度,它是如何工作的?共享庫和可執行文件與Linux上的靜態C運行時間鏈接。他們每個人都有像Windows一樣的單獨堆嗎?

在Windows上:

  1. 在一個進程的開始,操作系統創建一個名爲進程堆一個默認堆。如果沒有使用其他堆,則使用進程堆分配塊。
  2. 語言運行時間也可以在一個過程中創建單獨的堆。 (例如,C運行時創建自己的堆)
  3. 除了這些專用堆,應用程序或許多加載的動態鏈接庫(DLL)之一可能會創建並使用單獨的堆,稱爲私有堆
  4. 這些堆位於所有虛擬內存系統中操作系統的虛擬內存管理器之上。 a)C/C++運行時(CRT)分配器:提供malloc()和free()以及新的和刪除操作符。 b)CRT作爲其初始化的一部分,爲其所有分配創建了一個額外的堆(該CRT堆的句柄在CRT庫內部存儲在名爲_crtheap的全局變量中)。 c)CRT創建自己的私有堆,它位於Windows堆的頂部。 d)Windows堆是圍繞Windows運行時分配器(NTDLL)的薄層。 e)Windows運行時分配器與虛擬內存分配器進行交互,虛擬內存分配器保留並提交操作系統使用的頁面。

我們的DLL和exe鏈接到多線程靜態CRT庫。我們創建的每個DLL和exe都有一個自己的堆,即_crtheap。分配和解除分配必須從各個堆發生。動態分配的DLL不能從可執行文件中取消分配,反之亦然。

編譯我們的代碼在DLL和EXE的使用/ MD或/ MDD使用多線程特定和DLL特定版本的運行時庫,將DLL和EXE鏈接到相同的C運行時庫,因此一個_crtheap。分配總是與單個模塊內的解除分配配對。

這與Liunx上的行爲相同嗎? 那裏有什麼堆?怎麼樣CRT堆?

回答

1

我真的不知道該如何回答這個問題,但我會盡量給出足夠的一般信息,以便我知道您需要知道的內容。

作爲一名unix人員,我從你的問題中瞭解到有關Windows內存管理的知識,你們大量使用「堆」這個詞。除了作爲「由malloc管理的內存區域」的非正式同義詞外,我們不這樣做。

有兩個主要的動態內存分配原語需要注意:brkmmap。所有其他分配功能,包括malloc都建立在這些之上。

brk是舊的。它的工作原理是在bss段結束後,將更多內存添加到進程的虛擬內存映射中。您通過brk一個值,並且成爲進程的「中斷」地址 - 分配的虛擬內存的末尾。

每次需要更多的內存時,malloc都可以構建在brk之上,每次調用時都會使用更高的值,並且維護一些內部數據結構來跟蹤已釋放和仍在使用的內容。 (在經典實現中沒有將內存回饋給系統)。一些malloc實現的內部數據結構必須是heap,它給出了brk段的綽號:「堆」。

參見:What does brk() system call do?(有照片!)

這真是不尋常的程序直接調用brk。 (甚至薄包裝sbrk)。正常程序中每次使用brk都是通過malloc。請記住,雖然您將C庫(包括malloc)視爲某種可選的額外內容,但我們有一個與C緊密耦合的操作系統,因此不會像內存管理那樣使用libc來處理低級內容的程序非常奇怪的確如此。所以大多數情況下,brk段a.k.a.「堆」中的所有內存都由malloc管理。然而,相反是不正確的,因爲...

mmap,比brk(mmap是從90年代; brk是從70年代)提供了很多選項。如果要將文件映射到內存中,或者分配多個不連續的內存塊,而不是在原始數據塊的末尾添加一些空間,則可以使用mmap。共享庫加載器使用mmap來映射每個庫的文本和數據。現代malloc實現使用mmap來處理大型請求,而使用brk來處理小型請求。我們也有mremap,它將映射重定位到一個新的虛擬地址,同時保持它在同一個物理地址,允許realloc避免昂貴的副本。

如果您在Linux上查看/proc/$PID/maps,您會看到標記爲[heap]的內存區域。這是brk分部。每個過程只有一個。 (我已經看到一些例子,其中maps文件顯示其中2個,但它們是連續的並具有相同的屬性,因此真的等同於單個區域。我不知道是什麼導致了雙重列表。)

With記住所有這些背景,分配「額外堆」是什麼意思?你可以用mmap從系統請求一些內存,給你一個獨立於malloc的區域。然後,您可以對該區域進行自己的類似malloc的管理,以各種大小的塊傳遞它,並跟蹤哪些部分未被使用。但是你的新分配器不會是「堆」。這實際上並不意味着什麼,因爲系統並不知道有關堆的任何信息。

+0

非常感謝您的洞察力。當一個靜態鏈接到libc的共享庫被一個可執行文件加載時會發生什麼,該可執行文件也與libc靜態鏈接。那麼會有兩堆嗎?如果從內存中分配內存並從其他內存中釋放內存,會是一個問題嗎? –

+0

我不知道......靜態鏈接並不總是得到很好的支持,而且我認爲如果你已經走到了盡頭,最終會得到與運行代碼鏈接的同一個庫的2個副本,那麼你已經犯了嚴重的戰略錯誤。 –

相關問題