- 論壇徽章:
- 0
|
有關(guān)于上述幾類的地址,最近有做學(xué)習(xí)和整理,基本上是明白其含義,但是還不夠火候
在此一來作為學(xué)習(xí)的標記,二來還希望大家可以不吝賜教
下面篇幅有點長,內(nèi)容有點雜亂,問題也有點小多;望各位耐心看完 :wink:
相關(guān)帖子,有看過一些。比如: http://72891.cn/forum.php?mod=viewthread&tid=2083672
理解上
由于intel(32位)處理器的分段機制,因此有了 邏輯地址的概念,其組成是 段選擇符(16位) + 段內(nèi)偏移量(32位)。該邏輯地址由cpu的分段單元解析后,得到32位線性地址。
如果沒有分頁部件的存在,該線性地址就對應(yīng)于物理地址
分頁部件把該線性地址轉(zhuǎn)化成物理地址。根據(jù)查找頁表來進行轉(zhuǎn)化
在微機原理書上有說明,對于32位微處理器,可以訪問2^32字節(jié)的物理存儲器,但它支持多任務(wù)時,每個任務(wù)又能得到最大為2^46字節(jié)
物理存儲器對應(yīng)于物理上的內(nèi)存,是cpu可以訪問的存儲器空間
虛擬存儲器是程序占有的空間,其容量由cpu的內(nèi)部結(jié)構(gòu)所決定
對于8086cpu來說,程序占有的虛擬存儲器和cpu能訪問的存儲器是一致的,都是1M。(8086的地址總線是20位)
對于 32位的cpu來說,兩者是不同的。cpu最大可以訪問的存儲器是 4G, 而對于存儲在磁盤的程序而言,最大可以寫 2^46字節(jié)的程序
對于以上的理解,有
問題一: 為何在支持多任務(wù)時候,每個任務(wù)會有2^46字節(jié)。同時邏輯地址到底是48位還是46位?
看起來說和 cpu的內(nèi)部結(jié)構(gòu)有關(guān)。對于這個 46字節(jié),根據(jù)后續(xù)的介紹有: 14位的段選擇符 + 32位的段內(nèi)偏移
因為段選擇符的最低兩位是相關(guān)的權(quán)限標志位。不知以上理解是否正確
以上都是有關(guān)理論上的知識,有
問題二:對于邏輯地址,在哪可以比較直白的看到該地址的存在?或者說通過什么方式我們可以看到這 48/46位的邏輯地址
我們可以通過使用 readelf -S a.out(參考下面的問題三中的討論)可以來查看程序的虛擬內(nèi)存空間。理論上我們在此可以看到最大 2^46大小的虛擬內(nèi)存空間。
我理解上,其中列出的就是虛擬地址,也就等同于上述所說的 邏輯地址的偏移量。
對于上述的邏輯地址,后來在翻書時候有注意到,對于匯編語言中的直接尋址方式。(以下是8086cpu,也就是20位地址總線,16位數(shù)據(jù)總線結(jié)構(gòu)的)
比如 “ mov AX, [1070H]“ 該操作是將 DS段的 1070H和 1071H兩單元的內(nèi)容放置到 AX中。因為直接尋址的默認段寄存器是 DS
如果要指定其他段寄存器,應(yīng)該指令前用前綴指定段寄存器名稱,比如 ” CS:mov BX, [3000H]“
以上兩個指令,假設(shè) DS為2000H, CS為5100H
指令一就是將 21070H和 21071H兩單元內(nèi)容存放到 AX中(DS向左偏移4位后加上后續(xù)的偏移量組成)
指令二是將 54000H和 54001H兩單元內(nèi)容存放到 BX中
21070H是邏輯地址還是線性地址??
如果是邏輯地址,是否說在匯編語言中可以查看到 邏輯地址的蹤跡?
對于 程序,參考某網(wǎng)絡(luò)上相關(guān)程序內(nèi)存布局的文章- #include <stdio.h>
- #include <stdlib.h>
- int global_init_a=1;
- int global_uninit_a;
- int main()
- {
- int local_init_a=1;
- int local_uninit_a;
- int * malloc_p_a;
- malloc_p_a=malloc(sizeof(int));
- printf("\n &global_init_a=%p \t "
- "global_init_a=%d\n",&global_init_a,global_init_a);
- printf(" &global_uninit_a=%p \t "
- "global_uninit_a=%d\n",&global_uninit_a,global_uninit_a);
- printf("\n &local_init_a=%p \t "
- "local_init_a=%d\n",&local_init_a,local_init_a);
- printf(" &local_uninit_a=%p \t "
- "local_uninit_a=%d\n",&local_uninit_a,local_uninit_a);
-
- printf(" malloc_p_a=%p \t "
- "*malloc_p_a=%d\n",malloc_p_a,*malloc_p_a);
-
- while(1);
- return 0;
- }
復(fù)制代碼 運行結(jié)果:- [martin@stack]$ gcc process_mem.c
- [martin@stack]$ ./a.out &
- [1] 7418
- [martin@stack]$
- &global_init_a=0x804a024 global_init_a=1
- &global_uninit_a=0x804a02c global_uninit_a=0
- &local_init_a=0xbfb1f5a4 local_init_a=1
- &local_uninit_a=0xbfb1f5a8 local_uninit_a=134513931
- malloc_p_a=0x8758008 *malloc_p_a=0
- [martin@stack]$
復(fù)制代碼 查看進程的maps- [martin@stack]$ sudo cat /proc/7418/maps
- 08048000-08049000 r-xp 00000000 08:08 1700899 /home/martin/debug/work/test/stack/a.out
- 08049000-0804a000 r--p 00000000 08:08 1700899 /home/martin/debug/work/test/stack/a.out
- 0804a000-0804b000 rw-p 00001000 08:08 1700899 /home/martin/debug/work/test/stack/a.out
- 08758000-08779000 rw-p 00000000 00:00 0 [heap]
- b7542000-b7543000 rw-p 00000000 00:00 0
- b7543000-b76ec000 r-xp 00000000 08:0a 1570780 /lib/i386-linux-gnu/libc-2.19.so
- b76ec000-b76ee000 r--p 001a9000 08:0a 1570780 /lib/i386-linux-gnu/libc-2.19.so
- b76ee000-b76ef000 rw-p 001ab000 08:0a 1570780 /lib/i386-linux-gnu/libc-2.19.so
- b76ef000-b76f2000 rw-p 00000000 00:00 0
- b7709000-b770c000 rw-p 00000000 00:00 0
- b770c000-b770d000 r-xp 00000000 00:00 0 [vdso]
- b770d000-b772d000 r-xp 00000000 08:0a 1570756 /lib/i386-linux-gnu/ld-2.19.so
- b772d000-b772e000 r--p 0001f000 08:0a 1570756 /lib/i386-linux-gnu/ld-2.19.so
- b772e000-b772f000 rw-p 00020000 08:0a 1570756 /lib/i386-linux-gnu/ld-2.19.so
- bfb00000-bfb21000 rw-p 00000000 00:00 0 [stack]
- [martin@stack]$
復(fù)制代碼 使用 readelf查看 a.out程序的Stack- [martin@stack]$ readelf -S a.out
- There are 30 section headers, starting at offset 0x1154:
- Section Headers:
- [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
- [ 0] NULL 00000000 000000 000000 00 0 0 0
- [ 1] .interp PROGBITS 08048154 000154 000013 00 A 0 0 1
- [ 2] .note.ABI-tag NOTE 08048168 000168 000020 00 A 0 0 4
- [ 3] .note.gnu.build-i NOTE 08048188 000188 000024 00 A 0 0 4
- [ 4] .gnu.hash GNU_HASH 080481ac 0001ac 000020 04 A 5 0 4
- [ 5] .dynsym DYNSYM 080481cc 0001cc 000060 10 A 6 1 4
- [ 6] .dynstr STRTAB 0804822c 00022c 000053 00 A 0 0 1
- [ 7] .gnu.version VERSYM 08048280 000280 00000c 02 A 5 0 2
- [ 8] .gnu.version_r VERNEED 0804828c 00028c 000020 00 A 6 1 4
- [ 9] .rel.dyn REL 080482ac 0002ac 000008 08 A 5 0 4
- [10] .rel.plt REL 080482b4 0002b4 000020 08 A 5 12 4
- [11] .init PROGBITS 080482d4 0002d4 000023 00 AX 0 0 4
- [12] .plt PROGBITS 08048300 000300 000050 04 AX 0 0 16
- [13] .text PROGBITS 08048350 000350 000222 00 AX 0 0 16
- [14] .fini PROGBITS 08048574 000574 000014 00 AX 0 0 4
- [15] .rodata PROGBITS 08048588 000588 000123 00 A 0 0 4
- [16] .eh_frame_hdr PROGBITS 080486ac 0006ac 00002c 00 A 0 0 4
- [17] .eh_frame PROGBITS 080486d8 0006d8 0000ac 00 A 0 0 4
- [18] .init_array INIT_ARRAY 08049f08 000f08 000004 00 WA 0 0 4
- [19] .fini_array FINI_ARRAY 08049f0c 000f0c 000004 00 WA 0 0 4
- [20] .jcr PROGBITS 08049f10 000f10 000004 00 WA 0 0 4
- [21] .dynamic DYNAMIC 08049f14 000f14 0000e8 08 WA 6 0 4
- [22] .got PROGBITS 08049ffc 000ffc 000004 04 WA 0 0 4
- [23] .got.plt PROGBITS 0804a000 001000 00001c 04 WA 0 0 4
- [24] .data PROGBITS 0804a01c 00101c 00000c 00 WA 0 0 4
- [25] .bss NOBITS 0804a028 001028 000008 00 WA 0 0 4
- [26] .comment PROGBITS 00000000 001028 000024 01 MS 0 0 1
- [27] .shstrtab STRTAB 00000000 00104c 000106 00 0 0 1
- [28] .symtab SYMTAB 00000000 001604 000460 10 29 45 4
- [29] .strtab STRTAB 00000000 001a64 000288 00 0 0 1
- Key to Flags:
- W (write), A (alloc), X (execute), M (merge), S (strings)
- I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
- O (extra OS processing required) o (OS specific), p (processor specific)
- [martin@stack]$
復(fù)制代碼 重點在于進程的 maps表,從 readelf可以看出,程序的 bss和 data數(shù)據(jù)段的虛擬地址是 0804a01c,這個應(yīng)該是程序的虛擬內(nèi)存空間。根據(jù)以上討論,該虛擬內(nèi)存空間可以大于 4G
該地址也可以在進程的maps中看到。
問題三:對于進程的 maps中,stack的地址 bfb00000應(yīng)該是該進程占用的實際物理內(nèi)存空間的物理地址,那為何還會有類似 08049000地址,這個不是程序的虛擬地址么?
這個有可能是針對 linux進程的內(nèi)存管理方面的知識,不是特別清楚,所以也在此咨詢下各位大嬸 |
|