linux系统使用小端内存,linux进程内存管理
1.數(shù)據(jù)的內(nèi)部存儲
大端:起始地址存放數(shù)據(jù)的高位
小端:起始地址存放數(shù)據(jù)的低位
大端小端是由處理器的體系結(jié)構(gòu)決定的,不是操作系統(tǒng)。
測試方法:
點(diǎn)擊(此處)折疊或打開
#include
int main()
{
int a=0x12345678;
char *p=NULL;
p=&a;
if(*p = 0x12)
printf("big endian.\n");
else
printf("little endian.\n");
return 0;
}
2.C程序的存儲布局--代碼段
代碼段是用于存放CPU要執(zhí)行的指令段。代碼段只讀,任何對代碼段的修改,都會(huì)造成段錯(cuò)誤。
一個(gè)程序在多數(shù)情況下是不需要修改自身代碼的,只有一種情況例外,就是一些長時(shí)間運(yùn)行的升級程序。
可以采用共享庫的形式,來修改一個(gè)運(yùn)行中的程序的代碼段。
3.C程序的存儲布局--數(shù)據(jù)段和緩沖段
初始化數(shù)據(jù)段(.data):也稱為數(shù)據(jù)段。包含初始過的全局變量和靜態(tài)變量。該段的大小在編譯時(shí)確定。
未初始化數(shù)據(jù)段(.bss,block start with symbol):這個(gè)段中的數(shù)據(jù)是程序沒有明確初始化的靜態(tài)變量+全局變量。又叫做塊緩存段,塊存儲段
在elf格式的目標(biāo)文件中,bss段并不占用實(shí)際的空間,而只是一個(gè)占位符,已告知指定位置上應(yīng)當(dāng)預(yù)留全局?jǐn)?shù)據(jù)的空間。塊緩存段存在的原因是為了提供磁盤上存儲空間的利用率。
未初始化數(shù)據(jù)段不會(huì)存儲在外存上,在程序運(yùn)行時(shí),由內(nèi)核將段中的數(shù)據(jù)初始化成0或NULL。
4.C程序的存儲布局--棧
所有的自動(dòng)變量+函數(shù)調(diào)用時(shí)所需要保存的信息(返回地址,函數(shù)調(diào)用前各寄存器的值)都保存在棧中。
每個(gè)函數(shù)都有對應(yīng)的棧幀。棧幀在一個(gè)函數(shù)調(diào)用時(shí)被創(chuàng)建,在函數(shù)調(diào)用結(jié)束時(shí)消亡。所有的函數(shù)都是基于進(jìn)程的棧創(chuàng)建的,從全局的角度來看,一個(gè)進(jìn)程只有一個(gè)棧(也只有一個(gè)堆),但每個(gè)函數(shù)執(zhí)行時(shí),都對應(yīng)一塊獨(dú)立的棧幀。所以不應(yīng)該在棧幀上傳遞一個(gè)返回值的地址,因?yàn)楹瘮?shù)調(diào)用結(jié)束后,該棧幀有可能會(huì)被覆蓋掉,相應(yīng)的,對該地址的引用就會(huì)是無效的。
注意:不應(yīng)該將一個(gè)指向局部變量的指針作為返回值返回。在linux環(huán)境下,這種方法是錯(cuò)誤的。但Windows平臺下,似乎是可行的。
函數(shù)調(diào)用結(jié)束后,棧幀上的內(nèi)容還存在,函數(shù)返回的是一個(gè)局部變量的地址。如果該棧幀被其他函數(shù)覆蓋,對該指針的引用也就失效了。
5.C程序的存儲布局--堆
堆,用于存儲用戶申請的內(nèi)存空間,系統(tǒng)通常在堆中進(jìn)行動(dòng)態(tài)內(nèi)存分配。
對于小端處理器,棧地址由高-->低,堆地址由低-->高增長。大端處理器正好相反。
6.常量的存儲
C語言中常量有兩種:簡單常量,如1234,‘c';復(fù)雜常量,如iloveyou等字符串常量。
在匯編語言中,對于常量參與運(yùn)算的C語句,如a+1的匯編代碼被匯編成如下:
點(diǎn)擊(此處)折疊或打開
mov r1, a
add r1, 1
簡單常量,它隨著指令一起存儲,也就是說簡單變量存儲在程序的代碼段里。
對于復(fù)雜常量,長度不定,放在代碼段里面是不明智的,因此編譯器將其存儲在一個(gè)特殊的數(shù)據(jù)段,將其存儲的首地址轉(zhuǎn)換成一個(gè)簡單變量隨著指令存儲。這個(gè)段叫做.rodata段。
7.動(dòng)態(tài)內(nèi)存管理
C語言中只能通過malloc和其他派生函數(shù)動(dòng)態(tài)申請內(nèi)存,malloc作為一個(gè)庫函數(shù),它的linux版本封裝了
sbrk()系統(tǒng)調(diào)用,該系統(tǒng)調(diào)用負(fù)責(zé)向操作系統(tǒng)申請內(nèi)存。malloc函數(shù)分配的內(nèi)存在堆中,全局有效。
文件:malloc.c
點(diǎn)擊(此處)折疊或打開
#include
#include
void fenpei1(int **p)
{
*p = (int *)malloc(sizeof(int));
}
void fenpei2(int *p)
{
printf("the heap is %d\n",*p);
}
int main(void)
{
int *p;
fenpei1(&p);
*p=4;
fenpei2(p);
free(p);
fenpei2(p);
return 0;
}
運(yùn)行:./malloc
the heap 4
the heap 0
做如下改動(dòng):
點(diǎn)擊(此處)折疊或打開
void fenpei1(int *p)
{
p = (int *)malloc(sizeof(int));
}
將fenpei1函數(shù)修改為如上形式。傳遞給fenpei1函數(shù)的是int *p的一份拷貝,p在函數(shù)返回后就消失了。
這時(shí),p所指向的還是一塊未知區(qū)域,再對p進(jìn)行解引用賦值就出錯(cuò)了。
總結(jié)
以上是生活随笔為你收集整理的linux系统使用小端内存,linux进程内存管理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 趣学python3(45)--调用C库-
- 下一篇: linux 裸设备使用,linux裸设备