segfault at xxx的地址是物理地址還是線性地址,objdump出來的呢?

Linux 程序出現溢出錯誤時,會從dmesg中查找出 segfault at xxx ip xxx sp xxx 那麼 at的這個xxx是什麼地址呢?是物理地址還是線性地址?

同樣 ObjDump 出來的彙編使用的地址是線性地址還是物理地址?

物理地址如何轉化為線性地址?


扁平的線性空間(例如 2^32 bytes)里的地址,叫做線性地址;

把線性空間分成幾個獨立的段(segment),由 段選擇符:有效地址(段內偏移) 組成的地址,叫做邏輯地址;(邏輯地址通常又經常用「遠指針」稱呼)。

線性空間可以直接映射到物理地址,也可以採用分頁(paging),先映射到虛擬內存,再映射到物理地址。(分頁對應用程序這一層 透明,即應用程序只能看到線性空間,對分頁無感知)。

以上關係大概如下(【】括起來的是 optional , 可以不存在):

【分段內存模型(邏輯地址)】 &<----&> 線性空間(線性地址) &<----&> 【(對 APP 透明的)分頁的虛擬內存】 &< ----&> 物理內存(物理地址)


@張洪吉 謝邀。

抱歉,之前的答案有些錯誤。

Linux的內存定址採用了分段機制和分頁機制。邏輯地址在分段機制的作用下,被轉換成線性地址;線性地址在分頁機制的作用下,被映射成物理地址。

邏輯地址由段選擇符和偏移量組成。段選擇符負責選擇選擇相應的段,而相應的段加上偏移量則是線性地址。

嚴格意義上來說,對應用程序可見的是邏輯地址的偏移量部分。然而,因為Linux所有的段都以0開始,所以,在Linux下邏輯地址的偏移量部分的值與線性地址是一致的。

因此,題主所問的是邏輯地址的偏移量部分,但由於Linux特殊的內存定址方式,說是線性地址也無傷大雅。


同樣 ObjDump 出來的彙編使用的地址是線性地址還是物理地址?

這個顯然必須是(用戶空間的、虛擬的)邏輯地址。因為程序直到真的被載入之前,根本沒法知道自己會被載入到哪塊物理地址上。

物理地址如何轉化為線性地址?

硬體層次上,CPU會有一些指令用於操縱內存映射。軟體層次上,操作系統在編寫的時候會使用這些指令來實現自己的分頁、許可權控制等「高級」的內存概念。


操作系統所能直接觀測到的地址均為虛擬內存地址,轉化過程可以參照《深入理解linux內核》第二章內存定址


都是邏輯地址,通常是指虛擬地址,也有有可能是物理地址。


推薦閱讀:

Linux的啟動過程中,滿足什麼條件可以不用initramfs而直接掛載/?
ELF文件裡面section的虛擬地址是如何在鏈接(link)時確定的?

TAG:Linux | C編程語言 | C | Linux內核 | 軟體調試 |