【读书笔记】程序员的自我修养总结(七)
【讀書筆記】程序員的自我修養(yǎng)總結(jié)(七)
標(biāo)簽: 【編程開發(fā)】
聲明:引用請(qǐng)注明出處http://blog.csdn.net/lg1259156776/
說明:這是程序員的自我修養(yǎng)一書的讀書總結(jié),隨著閱讀的推進(jìn),逐步增加內(nèi)容。
本文主要介紹可執(zhí)行文件的裝載與進(jìn)程
ELF文件的鏈接視圖和執(zhí)行視圖
當(dāng)段的數(shù)量增多時(shí),會(huì)產(chǎn)生空間浪費(fèi)的問題:因?yàn)镋LF文件被映射時(shí)時(shí)以系統(tǒng)的頁長度作為單位的,那么每個(gè)段在影射時(shí)的長度應(yīng)該都是系統(tǒng)頁長度的整數(shù)倍,如果不是,那么多余部分將占用一個(gè)頁,而一個(gè)ELF文件中往往有十幾個(gè)段,那么內(nèi)存空間將噪聲浪費(fèi)。
解決方法:
操作系統(tǒng)在裝載可執(zhí)行文件時(shí),可以發(fā)現(xiàn)主要關(guān)心的是段的權(quán)限(可讀,可寫,可執(zhí)行)等。比如:
- 以代碼段為代表的權(quán)限為可讀可執(zhí)行的段;
- 以數(shù)據(jù)段和BSS段為代表的權(quán)限為可讀可寫的段;
- 以只讀數(shù)據(jù)段為代表的權(quán)限為只讀的段;
所以,可以將相同權(quán)限的段,合并到一起當(dāng)作一個(gè)段進(jìn)行映射,可以明顯減少頁面內(nèi)部碎片,節(jié)省內(nèi)存空間。在目標(biāo)文件鏈接為可執(zhí)行文件時(shí),鏈接器會(huì)盡量將相同權(quán)限屬性的段分配在同一空間。被稱為Segment。
所以,會(huì)有ELF文件會(huì)有鏈接視圖和執(zhí)行視圖的概念,鏈接視圖以section,而執(zhí)行視圖為Segment,兩者區(qū)別就是相同特性之間的段之間的合并。
堆和棧
堆(heap)和棧(stack)在進(jìn)程的虛擬空間中的表現(xiàn)也是以VMA的形式存在的。C語言中最常用的malloc就是從堆中分配的,堆由系統(tǒng)庫管理。棧一般也叫做堆棧,每個(gè)線程都有自己的堆棧,對(duì)于單線程程序來講,這個(gè)VMA堆棧全歸它使用。那么一個(gè)進(jìn)程基本上可以分為如下幾種VMA區(qū)域:
- 代碼VMA,權(quán)限只讀、可執(zhí)行;有映像文件。
- 數(shù)據(jù)VMA,權(quán)限可讀寫、可執(zhí)行;有映像文件。
- 堆VMA,權(quán)限可讀寫、可執(zhí)行;無映像文件,匿名,可向上擴(kuò)展。
- 棧VMA,權(quán)限可讀寫、不可執(zhí)行;無映像文件,匿名,可向下擴(kuò)展。
堆的最大申請(qǐng)數(shù)量
Linux下虛擬地址空間分給進(jìn)程本身的是3GB,windows大概是默認(rèn)2GB。可以測(cè)試一下malloc函數(shù)進(jìn)行地址空間的申請(qǐng),到底能申請(qǐng)多大內(nèi)存?
#include<stdio.h> #include<stdlib.h> unsigned maximum = 0; int main() {unsigned blocksize[] = {1024 * 1024, 1024, 1};int i, count;for(i = 1; i < 3; i++)for(count = 1; ; count++){void *block = malloc(maximum + blocksize[i] * count);if(block){maximum = maximum + blocksize[i] * count;free(block);}else{break;}}printf("maximum malloc size = %u bytes\n", maximum);}經(jīng)測(cè)試,得到的輸出為:
maximum malloc size = 1826488009 bytes大約是1.7GB左右。
段地址對(duì)齊
要映射一段物理內(nèi)存和進(jìn)程虛擬地址空間之間建立映射關(guān)系,這段內(nèi)存空間的長度必須是4096的整數(shù)倍,并且這段空間在物理內(nèi)存和進(jìn)程虛擬地址空間中的起始地址必須是4096的整數(shù)倍。最簡(jiǎn)單的方法就是每個(gè)段分開映射,不足一個(gè)頁的占據(jù)一個(gè)頁,這樣當(dāng)然會(huì)造成內(nèi)部碎片。而有些UNIX采用各個(gè)段接壤部分共享一個(gè)物理頁面,然后將該物理頁面分別映射兩次。
進(jìn)程棧初始化
進(jìn)程剛開始啟動(dòng)的時(shí)候,須知道一些進(jìn)程運(yùn)行的環(huán)境,最基本的就是系統(tǒng)環(huán)境變量和進(jìn)程的運(yùn)行參數(shù)。很常見的做法是操作系統(tǒng)在進(jìn)程啟動(dòng)前將這些信息提前保存到進(jìn)程的虛擬空間的棧中。
進(jìn)程在啟動(dòng)以后,程序的庫部分會(huì)把堆棧里的初始化信息中的參數(shù)信息傳遞給main(),也就是main函數(shù)中的兩個(gè)argc和argv兩個(gè)參數(shù),分別對(duì)應(yīng)命令行中參數(shù)數(shù)量和命令行參數(shù)字符串指針數(shù)組。
2015-11-01讀書筆記 張朋藝
轉(zhuǎn)載于:https://www.cnblogs.com/huty/p/8518965.html
總結(jié)
以上是生活随笔為你收集整理的【读书笔记】程序员的自我修养总结(七)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 手势
- 下一篇: 在网页中插入时间 自动更新