關於使用者程式記憶體的管理的實驗(再思考fork)

2021-06-25 21:14:57 字數 4320 閱讀 8337

如題,一般使用者程式的記憶體分配圖,此次使用c程式設計來檢驗,基於window os,使用編譯器 gnu。

**如下,(摘自一位linux 高手的測試**)

#include #include // 未賦值的全域性變數放在bss段

int global_var;

// 已賦值的全域性變數放在data段

int global_initialized_var = 5;

void function()

int main()

執行結果為:

====in data segment====

global_initialized_var is at address 0x00404000

static_initialized_var is at address 0x00404004

====in bss segment====

static_var is at address 0x00407024

global_var is at address 0x00407020

====in heap====

heap_var is at address 0x00581948

====in stack====

the main's stack_var is at address 0x0022feec

the main's heap_var_ptr is at address 0x0022fee8

the function is at address 0x004016b0

the function's stack_var is at address 0x0022febc

將之用 圖表示出來:

以上僅僅是乙個程序的實驗,於是自己改動程式,在linux下 使用fork()觀察。

如下為變動程式

( cat /proc/versionlinux version 3.8.0-29-generic (buildd@akateko) (gcc version 4.6.3 (ubuntu/linaro 4.6.3-1ubuntu5) ) #42~precise1-ubuntu smp wed aug 14 15:31:16 utc 2013)

#include #include #include #include #include int main() 

else

}

執行結果為:

this is father

====in data segment====

static_initialized_var is at address 0x0804a028

====in bss segment====

static_var is at address 0x0804a038

====in heap====

heap_var is at address 0x08789008

====in stack====

the main's stack_var is at address 0xbfd780d0

this is son

====in data segment====

static_initialized_var is at address 0x0804a024

====in bss segment====

static_var is at address 0x0804a034

====in heap====

heap_var is at address0x08789008

====in stack====

the main's stack_var is at address 0xbfd780d0 

在stack 和 heap段  father process 和 son process 有相同的位址。

為此 改了下程式,在if兩個分支中新增下面幾句話

heap_var_ptr = (int *) malloc(4);

(*heap_var_ptr)=1;

printf("son:: heap_var_ptr= %d\n",(*heap_var_ptr));

父程序中

heap_var_ptr = (int *) malloc(4);

printf("heap_var_ptr= %d\n",(*heap_var_ptr));

執行結果:

heap_var_ptr= 0

son:: heap_var_ptr= 1

即雖然同一位址,但是好像並沒有共享資料。

又寫了段簡潔寫的**

#include #include #include #include #include #include int add(int a,int b);

//全域性變數

int global = 99;

char buf = "input a string: ";

int main()

if(pid == 0) //子程序

if(pid >0) //父程序

printf("pid=%d,ppid=%d,global=%d,val=%d\n",getpid(),getppid(),global,val);

//write(stdout_fileno,buf,strlen(buf));

//read(stdin_fileno,str,100);

//write(stdout_fileno,str,strlen(str));

printf("main::str in heap =ox%08x\n",(unsigned int)str);

printf("str=%d \n",(*str));

ret = add(global,val);

printf("global+val=%d\n",ret);

exit(0);

}int add(int a,int b)

執行結果如下

child process start exec.

child::str in heap =ox091aa008

child::p1 in stack =ox0804a054

child::s_str in heap =ox091aa018

son::global in data seg =ox0804a034

pid=3473,ppid=3472,global=100,val=50

main::str in heap =ox091aa008

str=1

global+val=150

parent process start exec.

parent::str in heap =ox091aa008

parent::p2 in stack =ox0804a058

parent::s_str in heap =ox091aa018

parent::global in data seg =ox0804a034

pid=3472,ppid=2260,global=99,val=49

main::str in heap =ox091aa008

str=0

global+val=148

由此 得出初步結論,kernel給程序分配時,使用的是虛擬位址,即雖然父程序和子程序有一樣的位址實際實體地址不一樣,就無法資料共享了。

網上找到一種解釋:

「記憶體總是被程序占用」,這句話換過來可以這麼理解:程序總是需要記憶體。當fork()或者exec()乙個程序的時候,系統核心就會分配一定量的vm給程序,作為程序的記憶體空間,大小由bss段,data段的已定義的全域性變數、靜態變數、text段中的字元直接量、程式本身的記憶體映像等,還有stack段的區域性變數決定。當然,還可以通過malloc()等函式動態分配記憶體,向上擴大heap。

動態分配與靜態分配,二者最大的區別在於:1. 直到run-time的時候,執行動態分配,而在compile-time的時候,就已經決定好了分配多少text+data+bss+stack。2.通過malloc()動態分配的記憶體,需要程式設計師手工呼叫free()釋放記憶體,否則容易導致記憶體洩露,而靜態分配的記憶體則在程序執行結束後系統釋放(text, data), 但stack段中的資料很短暫,函式退出立即被銷毀。

由此又想到之前,一道面試題 關於函式返回變數位址,而此時變數已經釋放的問題

實驗四 uC OS II 的記憶體管理

實驗四 uc os ii 的記憶體管理 一 實驗目的 掌握嵌入式實時作業系統 uc os ii 記憶體管理中記憶體分配和 的功能。二 實驗原理 注意 根據程式中設定的時間延遲,圖中的每個柵格對應100個系統時鐘週期。為了防止記憶體申請和釋放的不合理導致的大塊連續記憶體被分割成可用性小的小片的問題,u...

關於linux記憶體的管理

1 最近又稍微看了linux記憶體的管理,又稍微有一點收穫,來這裡記錄一下,以防以後又忘記了。都是針對32位的線性位址 首先是linux核心中從邏輯位址到實體地址的轉化。由於x86要支援段式對映,l段式對映是將段描述符中的基位址加上偏移量的定址方式。ldtr或者gdtr暫存器指向段描述符表的首位址,...

關於程式記憶體的問題

首先要確定一點就是,乙個程式在啟動以後,系統才會為這個程式分配記憶體,記憶體無非就這幾種 虛擬記憶體,記憶體,快取記憶體,暫存器,姑且叫這些記憶體是物理記憶體吧,因為它們都是以物質形式存在,不是玩概念的.注意,此處說的物理記憶體與大眾說的物理記憶體是不一樣的.然後再來看程式中使用的記憶體,這是玩概念...