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