對不起,如果問題是愚蠢的,但他們真的讓我困惑! 根據elf標準,二進制文件被分割爲如文本段(包含代碼和RO數據)和數據段(包含RW B0)的數據段,當程序執行並創建進程時,該段被加載到內存中,段提供信息用於流程執行的環境準備。 現在的問題是,如何決定在進程創建期間我沒有提供堆棧大小時要分配多少堆棧來處理? 此外,使用數據段,我們可以確定進程需要多少內存(對於全局變量),但是一旦分配了這個內存,如何將變量映射到分配的內存中的地址空間? 最後,這與分散加載有任何關係嗎?我認爲情況並非如此,因爲要將圖像加載到內存中並且一旦將控制權傳遞給操作系統時,分散加載就完成了,要分配給可執行文件或應用程序的內存由操作系統本身決定! 我知道這些問題太多,但任何幫助將不勝感激。 如果你可以提供任何參考書或鏈接,我可以詳細研究這一點,這也是讚賞。 謝謝你! :)堆棧分配過程及其數據段的佔用情況
回答
The question is, how it is decided that how much stack to allocate to process, when i am not providing stack size during process creation?
當一個新的過程中產生的,execve()
系統調用用於將新的節目作爲處理圖像從當前運行中的進程圖像加載到存儲器中。當加載新程序時,這意味着execve替換舊的.text
,.data
段,heap
並重置stack
。現在,ELF可執行文件被映射到內存地址空間中,使得使用環境數組和參數數組初始化堆棧空間爲main()
。
在根據子程序bprm_mm_init()do_execve_common()過程調用處理任務,比如,
- 的
mm_struct
新實例使用呼叫管理進程的地址空間mm_alloc()。 - 用init_new_context()初始化此實例。
- bprm_mm_init()初始化堆棧。
search_binary_handler()爲合適的binary format即load_binary,load_shlib常規搜索,以分別加載程序或動態庫。隨後將內存映射到虛擬地址空間,並在調度程序識別進程時使進程準備好運行。
因此,堆棧內存最終看起來像下圖,這在執行開始時會出現在
main()
例程中。現在,當調用發生時,函數調用子集中的每個環境(包括參數和局部變量)將被動態存儲或推入堆棧內存區域。----------------- | | <--- Top of the Stack | environmental | | variables and | | the other | | parameters to | | main() | _________________ <--- Stack Pointer | | | Stack Space | | |
Also, using the data segment we can determine how much memory the process requires (for global variables) but once this memory is allocated how mapping of variables is done with the address space inside this allocated memory?
讓嘗試通過如下調試簡單C
程序找出變量如何映射到存儲器段的不同部分,
/* File Name: elf.c : Demonstrating Global variables */
#include <stdio.h>
int add_numbers(void);
int value1 = 10; // Global Initialized: .data section
int value2; // Global Initialized: .bss section
int add_numbers(void)
{
int result; // Local Uninitialized: Stack section
result = value1 + value2;
return result;
}
int main(void)
{
int final_result; // Local Uninitialized: Stack section
value2 = 20;
final_result = add_numbers();
printf("The sum of %d + %d is %d\n",
value1, value2, final_result);
}
使用readelf
顯示.data
部分標題如下,
$readelf -a elf
...
Section Headers:
[26] .data PROGBITS 00000000006c2060 000c2060
00000000000016b0 0000000000000000 WA 0 0 32
[27] .bss NOBITS 00000000006c3720 000c3710
0000000000002bc8 0000000000000000 WA 0 0 32
...
$readelf -x 26 elf
Hex dump of section '.data':
0x006c2060 00000000 00000000 00000000 00000000 ................
0x006c2070 0a000000 00000000 00000000 00000000 ................
...
讓我們使用GDB來看看這些部分包括,
(gdb) disassemble 0x006c2060
Dump of assembler code for function `data_start`:
0x00000000006c2060 <+0>: add %al,(%rax)
0x00000000006c2062 <+2>: add %al,(%rax)
0x00000000006c2064 <+4>: add %al,(%rax)
0x00000000006c2066 <+6>: add %al,(%rax)
End of assembler dump.
.data
部分的上述第一個地址是指data_start
子程序。
(gdb) disassemble 0x006c2070
Dump of assembler code for function `value1`:
0x00000000006c2070 <+0>: or (%rax),%al
0x00000000006c2072 <+2>: add %al,(%rax)
End of assembler dump.
....
以上拆機轉儲初始化 10.全局變量value1
的地址,但我們沒有看到全球未初始化的變量value2
在明年地址。
讓我們來看看在印刷value2
地址,
(gdb) p &value2
$1 = (int *) 0x6c5eb0
(gdb) info symbol 0x6c5eb0
value2 in section **.bss**
(gdb) disassemble 0x6c5eb0
Dump of assembler code for function `value2`:
0x00000000006c5eb0 <+0>: add %al,(%rax)
0x00000000006c5eb2 <+2>: add %al,(%rax)
End of assembler dump.
田田!拆解變量存儲在.bss
部分中的value2
revels的參考指針。這解釋了未初始化的全局變量如何映射到進程內存空間。
Lastly, is there any relation of this with scatter loading?
號
- 1. 堆VS數據段VS堆棧分配
- 2. 明確堆棧分配的數據
- 3. 3活動堆棧情況
- 4. 線程堆棧分配
- 5. 只跟蹤子進程的堆和堆棧使用情況
- 6. 堆棧和隊列的使用情況?
- 7. ARM-gcc堆棧使用情況清空
- 8. C++堆棧與堆分配
- 9. 堆棧或堆棧分配不正確
- 10. 內存分配,堆棧和堆棧
- 11. C堆棧分配
- 12. 以下情況下的數據結構如何? (最大堆棧)
- 13. 迫不及待情況下同步部分被佔用
- 14. 數據和堆棧部分
- 15. 檢索堆內存大小及其使用情況統計等...?
- 16. C中的堆棧分配
- 17. 堆棧vs堆棧內存使用情況C++用於動態創建的類
- 18. 在堆棧上分配大數組時分段錯誤
- 19. 在堆上分配vs在遞歸函數中分配堆棧
- 20. 堆分配的對象是否將其成員分配到堆棧上?
- 21. 堆/堆棧上的類成員分配?
- 22. 堆棧或堆上的對象分配
- 23. C++在沒有初始化的情況下在堆棧上分配
- 24. 如何在沒有%rbp寄存器的情況下重新分配堆棧幀?
- 25. 受保護的堆對象堆棧vs堆棧分配
- 26. 如何測量Rust中的函數堆棧使用情況?
- 27. 內存佔用情況分析
- 28. 分配在堆或棧上?
- 29. 分配struct堆棧:Pthread_create
- 30. C++循環堆棧分配