日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

linux 进程内存分布及 堆分配和栈分配的特点

發(fā)布時(shí)間:2023/11/27 生活经验 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux 进程内存分布及 堆分配和栈分配的特点 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

        • 進(jìn)程內(nèi)存空間分布
        • size命令查看內(nèi)存分布
        • 堆方式內(nèi)存分配和棧方式內(nèi)存分配比較
        • 使用stap 深入追蹤malloc邏輯

進(jìn)程內(nèi)存空間分布

一個程序的內(nèi)存空間主要如下:

  • 代碼段(text segment):只讀權(quán)限;常是指用來存放程序執(zhí)行代碼的一塊內(nèi)存區(qū)域,這部分區(qū)域的大小在程序運(yùn)行前就已經(jīng)確定,并且內(nèi)存區(qū)域通常屬于只讀, 某些架構(gòu)也允許代碼段為可寫,即允許修改程序。在代碼段中,也有可能包含一些只讀的常數(shù)變量,例如字符串常量等。
  • 數(shù)據(jù)段(data segment):讀寫權(quán)限;存已被初始化了的靜態(tài)數(shù)據(jù)。數(shù)據(jù)段(data segment )通常是指用來存放程序中已初始化的全局變量或者靜態(tài)變量的一塊內(nèi)存區(qū)域。
  • BSS 段(Block Started by Symbol ):未初始化的數(shù)據(jù)段. 通常是指用來存放程序中未初始化的全局變量的一塊內(nèi)存區(qū)域,當(dāng)全局變量未初始化(或者被初始化為0時(shí))時(shí)在bss段會為該變量填充0。 關(guān)于.data,.bss.text段的內(nèi)存分布驗(yàn)證可以參考后面描述size binary_name命令驗(yàn)證
  • 常量數(shù)據(jù)段(.rodata)
    ro表read only,用于存放不可變修改的常量數(shù)據(jù),一旦程序中對其修改將會出現(xiàn)段錯誤
    (1) 程序中的常量不一定就放在rodata中,有的立即數(shù)和指令編碼放在.text中
    (2)對于字符串常量,若程序中存在重復(fù)的字符串,編譯器會保證只存在一個,一般聲明形式為const char * xxx
    (3)rodata是在多個進(jìn)程間共享的
    該數(shù)據(jù)段的查看方式如下:size -A test_memory
  • 堆(heap ): 堆是用于存放進(jìn)程運(yùn)行中被動態(tài)分配的內(nèi)存段,它的大小并不固定,可動態(tài)擴(kuò)張或縮減。當(dāng)進(jìn)程調(diào)用malloc 等函數(shù)分配內(nèi)存時(shí),新分配的內(nèi)存就被動態(tài)添加到堆上(堆被擴(kuò)張);當(dāng)利用free 等函數(shù)釋放內(nèi)存時(shí),被釋放的內(nèi)存從堆中被剔除(堆被縮減)
  • 棧(stack) :是用戶存放程序臨時(shí)創(chuàng)建的局部變量,也就是說我們函數(shù)括弧“{} ”中定義的變量(但不包括static 聲明的變量,static 意味著在數(shù)據(jù)段中存放變量)
  • comment段
    它存放的是編譯器版本等信息。除了.comment,還有.note、.hash等其他段,了解即可。
    以上中:.bss,.text,.data,.rodata,堆,棧為主要內(nèi)存占用數(shù)據(jù)區(qū),其他并非重要內(nèi)存占用,想要詳細(xì)了解的可以通過size -A binary_file或者 objdum -x binary_file查看。

在32位操作系統(tǒng)下,進(jìn)程內(nèi)存的分布如下,當(dāng)前進(jìn)程總共可用內(nèi)存空間大小是4G,因?yàn)楝F(xiàn)階段我們的操作系統(tǒng)普遍為多任務(wù)實(shí)時(shí)操作系統(tǒng),用戶態(tài)的進(jìn)程處理結(jié)果最終是需要內(nèi)核去完成,所以此時(shí)一個進(jìn)程空間會預(yù)留1G讓內(nèi)核使用:

而64位操作系統(tǒng)理論上是對進(jìn)程內(nèi)存空間的占用不做限制。

size命令查看內(nèi)存分布

使用命令size binary_file 可以看到當(dāng)前二進(jìn)制文件中text,data,bss段內(nèi)存占用情況,如下代碼,針對初始化全局變量和未初始化全局變量的data,bss段內(nèi)存分布查看如下。

#include <stdio.h>
int a[10];
//全局變量/靜態(tài)變量未初始化,或者被初始化為0時(shí)分布在bss段
//int b[0]={0};
int main()
{return 0;
}

此時(shí)全局變量未初始化,將分布在bss段。輸出如下:

zhanghuigui@ubuntu:~/test$ size test_memorytext	   data	    bss	    dec	    hex	filename1358	    544	     72	   1974	    7b6	test_memory

使用非0初始化全局變量后內(nèi)存分布如下

#include <stdio.h>
int a[10]={1,2,3,4,5,6,7,8,9,10};
int main()
{return 0;
}

使用非0初始化全局變量后,該內(nèi)存將分布在data段,輸出如下

zhanghuigui@ubuntu:~/test$ size test_memorytext	   data	    bss	    dec	    hex	filename1358	    600	      8	   1966	    7ae	test_memory

堆方式內(nèi)存分配和棧方式內(nèi)存分配比較

  1. 申請方式
    stack: 由系統(tǒng)自動分配。
    heap: 需要程序員自己申請,并指明大小,在 C 中 用malloc 函數(shù), C++ 中是 new 運(yùn)算符。
  2. 申請后系統(tǒng)的響應(yīng)
    棧:只要棧的剩余空間大于所申請空間,系統(tǒng)將為程序提供內(nèi)存,否則將報(bào)異常提示棧溢出。
    堆:首先應(yīng)該知道操作系統(tǒng)有一個記錄空閑內(nèi)存地址的鏈表,當(dāng)系統(tǒng)收到程序的申請時(shí),會遍歷該鏈表,尋找第一個空間大于所申請空間的堆結(jié)點(diǎn),然后將該結(jié)點(diǎn)從空閑結(jié)點(diǎn)鏈表中刪除,并將該結(jié)點(diǎn)的空間分配給程序。
    由于找到的堆結(jié)點(diǎn)的大小不一定正好等于申請的大小,系統(tǒng)會自動的將多余的那部分重新放入空閑鏈表中
  3. 申請大小的限制
    棧:在Windows下,棧是向低地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu),是一塊連續(xù)的內(nèi)存的區(qū)域。意思是棧頂?shù)牡刂泛蜅5淖畲笕萘渴窍到y(tǒng)預(yù)先規(guī)定好的,在Windows下,棧的大小是 2M (也有的說是 1M ,總之是一個編譯時(shí)就確定的常數(shù)),如果申請的空間超過棧的剩余空間時(shí),將提示overflow。因此,能從棧獲得的空間較小。
    堆:堆是向高地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu),是不連續(xù)的內(nèi)存區(qū)域。這是由于系統(tǒng)是用鏈表來存儲的空閑內(nèi)存地址的,自然是不連續(xù)的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限于計(jì)算機(jī)系統(tǒng)中有效的虛擬內(nèi)存。由此可見,堆獲得的空間比較靈活,也比較大。
  4. 申請效率的比較
    棧由系統(tǒng)自動分配,存在棧操作的機(jī)器指令,速度較快。但程序員是無法控制內(nèi)存分配的 。
    堆是由 new /malloc分配的內(nèi)存,一般速度比較慢,而且容易產(chǎn)生內(nèi)存碎片 , 不過用起來方便 ,可以通過delete/free進(jìn)行回收。
  5. 存儲內(nèi)容比較
    棧中主要存放的是函數(shù)名,變量,返回值等,函數(shù)運(yùn)行時(shí)以棧幀的形式push到棧中,函數(shù)退出時(shí)按照棧的方式pop出棧。
    堆中存儲的內(nèi)容可以自己去設(shè)定,比較自由

使用stap 深入追蹤malloc邏輯

關(guān)于systemtap工具的使用可以參考s-systemtap工具使用圖譜
想要查看glibc對malloc從用戶態(tài)到內(nèi)核態(tài)的實(shí)現(xiàn),可以參考如下步驟
測試代碼:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main()
{char *str;str = (char *)malloc(sizeof(char));if (!str) {printf("malloc_error\n");_exit(-1);	}return 0;
}

編譯gcc test.c -o test
編寫stp探測腳本對malloc流程進(jìn)行監(jiān)控

#!/usr/bin/stapprobe begin {printf("begin to probe\n");
}probe syscall.* { #對系統(tǒng)所有的系統(tǒng)調(diào)用進(jìn)行探測procname=execname();if(procname=="test") {  #匹配以上c代碼編譯好的test二進(jìn)制文件printf("%s[%d]: %s -> %s\n", procname,pid(),name,ppfunc()); #name 為此時(shí)malloc實(shí)現(xiàn)(glibc)中的函數(shù),ppfunc為系統(tǒng)調(diào)用名稱}
}probe end {printf("end to probe\n");
}

運(yùn)行探測腳本,當(dāng)輸出begin to probe的時(shí)候運(yùn)行test,則會有如下輸出,調(diào)用過程較為清晰

begin to probe
test[1461716]: brk -> SyS_brk      #brk為glibc實(shí)現(xiàn)的函數(shù),而Sys_brk則為系統(tǒng)調(diào)用
test[1461716]: mmap2 -> SyS_mmap_pgoff
test[1461716]: access -> SyS_access
test[1461716]: open -> SyS_open
test[1461716]: fstat -> SyS_newfstat
test[1461716]: mmap2 -> SyS_mmap_pgoff
test[1461716]: close -> SyS_close
test[1461716]: open -> SyS_open
test[1461716]: read -> SyS_read
test[1461716]: fstat -> SyS_newfstat
test[1461716]: mmap2 -> SyS_mmap_pgoff
test[1461716]: mprotect -> SyS_mprotect
test[1461716]: mmap2 -> SyS_mmap_pgoff
test[1461716]: mmap2 -> SyS_mmap_pgoff
test[1461716]: close -> SyS_close
test[1461716]: mmap2 -> SyS_mmap_pgoff
test[1461716]: mmap2 -> SyS_mmap_pgoff
test[1461716]: arch_prctl -> sys_arch_prctl
test[1461716]: mprotect -> SyS_mprotect
test[1461716]: mprotect -> SyS_mprotect
test[1461716]: mprotect -> SyS_mprotect
test[1461716]: munmap -> SyS_munmap
test[1461716]: brk -> SyS_brk
test[1461716]: brk -> SyS_brk
test[1461716]: brk -> SyS_brk
test[1461716]: exit_group -> SyS_exit_group

參考文檔:
https//blog.csdn.net/jirryzhang/article/details/79518408
https://blog.csdn.net/baidu_37964071/article/details/81428139
https://www.jianshu.com/p/f9760cb3cea2
https://blog.csdn.net/DLUTBruceZhang/article/details/9080157?utm_source=copy

總結(jié)

以上是生活随笔為你收集整理的linux 进程内存分布及 堆分配和栈分配的特点的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。