2012-05-22 33 views
1

我正在使用帶有cortex_A9_MPCORE處理器的ARM開發板(雪球),運行Linux 3.0.8+內核。 我使用GDB和openocd進行調試。ARM linux:進程地址空間

我正在尋找一種方法來查找用戶模式進程的地址空間,尤其是文本段和用戶模式堆棧。

首先我看着的/ proc /「PID」 /地圖,比如我得到這個輸出的進程中運行的一個:

# cat /proc/1124/maps 
00008000-000d5000 r-xp 00000000 b3:02 181  /system/bin/lbsd 
000d5000-000f8000 rw-p 000cd000 b3:02 181  /system/bin/lbsd 
000f8000-0014a000 rw-p 00000000 00:00 0   [heap] 
0014a000-0014c000 rw-p 00000000 00:00 0   [heap] 
. 
. 
. 
b0001000-b0009000 r-xp 00001000 b3:02 183  /system/bin/linker 
b0009000-b000a000 rw-p 00009000 b3:02 183  /system/bin/linker 
b000a000-b0015000 rw-p 00000000 00:00 0 
bea00000-bea21000 rw-p 00000000 00:00 0   [stack] 
ffff0000-ffff1000 r-xp 00000000 00:00 0   [vectors] 

然後用GDB我寫的解析列表中的腳本從init_task開始,爲每個任務獲取在task_struct中找到的mm_struct的值,然後提取start_code,end_code和start_stack的值。最後腳本解析mmap指向的不同內存區域。 該腳本而板處於調試狀態運行時,皮質A9的兩個芯被停止

這裏是GDB腳本對相同的過程與上述輸出:

taskaddr 0xdf29f140 
Name: lbsd 
mm start text 8000 
mm end text d4ba4 
mm start stack bee63df0 
####MEMORY REGIONS##### 
vm_start 0x8000 
vm_end 0xd5000 
vm_flags 0x8001875 
----------------------- 
vm_start 0xd5000 
vm_end 0xf8000 
vm_flags 0x8101873 
----------------------- 
vm_start 0xf8000 
vm_end 0x14a000 
vm_flags 0x100073 
----------------------- 
vm_start 0x14a000 
vm_end 0x14c000 
vm_flags 0x100073 
----------------------- 
. 
. 
. 
----------------------- 
vm_start 0xb0001000 
vm_end 0xb0009000 
vm_flags 0x8000875 
----------------------- 
vm_start 0xb0009000 
vm_end 0xb000a000 
vm_flags 0x8100873 
----------------------- 
vm_start 0xb000a000 
vm_end 0xb0015000 
vm_flags 0x100073 
----------------------- 
vm_start 0xbee42000 
vm_end 0xbee64000 
vm_flags 0x100173 
----------------------- 
vm_start 0xffff0000 
vm_end 0xffff1000 
vm_flags 0x40c0055 
----------------------- 

存儲器區域相匹配對於除堆棧之外的所有方法,在/ proc方法的輸出中,它始於bea00000,而在mm_struct的start_stack字段中,它位於bee63df0處,而由vm_struct指向的內存區域指示bee42000。 有人可以解釋這些值的差異嗎?

我的第二個問題是關於00008000和000d5000之間的第一個內存區域的值,它對應於進程的文本部分。我注意到很多進程共享這些地址。內核如何管理文本內存區域的真實地址?

回答

1

在ARM上,堆棧增長減少。這意味着堆棧從更高的地址開始。這在vm_flags中對於vma堆棧可見,其具有VM_GROWSDOWN位設置。

堆棧vma具有0xbee64000一個vm_end,這正是比0xbee63df0start_stack更高528個字節。發生這種情況是因爲在同一個VMA中,堆棧頂部有一些東西:命令行,環境和輔助向量。

我不知道爲什麼堆棧(只有它)在不同的地址/proc/<pid>/maps。縱觀內核源代碼,我看到一個vma可以顯示爲[stack]當且僅當start_stack距離,所以如果start_stack是一樣的,當你看着/proc/<pid>/maps,即vma不可能被標記爲[stack]。我能想到的唯一解釋是它來自可執行文件的不同運行,並且地址佈局隨機化對於堆棧中的所有內容都是禁用的。


現在是第二個問題。

當您的進程正在運行時,硬件會使用頁表從虛擬地址(例如0x8000)映射到頁面的物理地址。內核可以做同樣的事情;它有一個指向根頁表(pgd)的指針,指向其mm_struct中的進程。一旦它有物理頁碼(pfn),它可以到達相應的struct page。有大量的宏和函數來完成所有這些操作。

但是頁面可能會丟失。例如,可執行文件的其中一頁可能尚未出現故障。該頁面在頁面表中的條目將顯示爲缺失。然後內核查看相應的vma,它給出vma內的偏移量,它有足夠的信息從某處獲取該頁面,並將其插入到頁表中。