我們本節(jié)來看看程序的結(jié)構(gòu)體系。我們在平時所編寫的程序中,其實(shí)它的結(jié)構(gòu)是非常值得研究的,這樣有助于我們編寫出效率更高的代碼,并且也有助于我們理解整個可執(zhí)行文件的架構(gòu)。好了,廢話不多說。那么我們的程序究竟是由什么構(gòu)成的呢?它是由不同的段所構(gòu)成的,包括代碼段、數(shù)據(jù)段等。
從事四川綿陽服務(wù)器托管,服務(wù)器租用,云主機(jī),雅安服務(wù)器托管,申請域名,CDN,網(wǎng)絡(luò)代維等服務(wù)。程序有兩個特征,靜態(tài)特征和動態(tài)特征。靜態(tài)特征指的是指令和數(shù)據(jù),而動態(tài)特征則指的是執(zhí)行指令處理數(shù)據(jù)的動作。下來我們來看看程序源代碼到可執(zhí)行程序文件的對應(yīng)關(guān)系,如下圖所示
我們之前在 C 語言中曾經(jīng)也說過這方面的知識,今天我們再次回顧下。由上圖我們可以看到初始化過的全局變量和初始化過的 static 修飾的局部變量都存儲在 .data 段,而沒有初始化的變量則存儲在 .bss 段,函數(shù)都存儲在 .text 段。
下來我們來一一介紹下上面的幾個段,首先是代碼段(.text),代碼段具有以下特征
1、源代碼中的可執(zhí)行語句編譯后進(jìn)入代碼段;
2、代碼段在有內(nèi)存管理單元的系統(tǒng)中具有只讀屬性;
3、代碼段的大小在編譯結(jié)束后就已經(jīng)固定(不能動態(tài)改變);
4、代碼段中可以包含常量數(shù)據(jù)(如常量字符串)。
其次是數(shù)據(jù)段,它包括(.data, .bss, .rodata)。數(shù)據(jù)段用于處處源代碼中具有全局生命期的變量,其中 .bss 段存儲未初始化(或初始化為 0)的變量、.data 段存儲具有非 0 的初始值的變量、.rodata 存儲 const 關(guān)鍵字修飾的變量。那么我們思考下:我們在前面說初始化過的和未初始化的全局變量和靜態(tài)局部變量是分開來存放的,為什么要搞的如此復(fù)雜呢?一般在程序加載后,.bss 段中的所有內(nèi)存單元被初始化為 0,將程序文件中 .data 段相關(guān)的初始值寫入對應(yīng)的內(nèi)存單元。因?yàn)?.bss 段中的變量不用在程序文件中保存初始值,從而減少可執(zhí)行程序文件的體積,并且提高程序的加載效率。
下來我們還是以代碼為例來進(jìn)行分析說明
int g_no_var_v; int g_var_v = 1; int g_main() { static no_var_v1; static var_v2 = 2; return 0; }
我們編譯來看看結(jié)果
我們看到在 .data 和 .bss 段中各占了8字節(jié)。接下來我們把全局變量 g_no_var_v 的類型改為 char,然后再看看結(jié)果
我們看到結(jié)果還是 8,因?yàn)樗撬淖止?jié)對齊的,因此結(jié)果還是 8,如果我們改為兩個 char 類型的,那么結(jié)果便為 4 了。g_main() 的入口地址便是 .text 段的起始地址了,也再次證明了我們的程序是自己指定入口函數(shù)的了。
下來我們來看看棧(Stack)。棧在程序中的本質(zhì)是一片連續(xù)存儲的內(nèi)存空間,SP 寄存器作為棧頂“指針”實(shí)現(xiàn)入棧操作和出棧操作。如下圖所示
棧的作用大致有以下幾方面:
1、中斷發(fā)生時,棧用于保存寄存器的值;
2、函數(shù)調(diào)用時,棧用于保存函數(shù)的活動記錄(棧幀信息);
3、并發(fā)編程時,每一個線程擁有自己獨(dú)立的棧。
下來我們來看看堆(Heap),堆是一片“閑置”的內(nèi)存空間,其目的是用于提供動態(tài)的內(nèi)存分配;當(dāng)然堆空間的分配是需要 malloc 函數(shù)的支持的,它在使用完成后也需要借助于 free 函數(shù)進(jìn)行手動的釋放空間。再來看看內(nèi)存映射段(Memory Mapping Segment),在內(nèi)核中,是直接將硬盤文件的內(nèi)容直接映射到內(nèi)存映射段(mmap),動態(tài)鏈接庫在可執(zhí)行程序加載時映射到內(nèi)存映射段,以便程序在執(zhí)行時能夠創(chuàng)建匿名映射區(qū)存放程序數(shù)據(jù)。
我們簡單來介紹下內(nèi)存映射文件的原理:
1、將硬盤上的文件數(shù)據(jù)邏輯映射到內(nèi)存中(零耗時);
2、通過缺頁中斷進(jìn)行文件數(shù)據(jù)的實(shí)際載入(一次數(shù)據(jù)拷貝);
3、映射后的內(nèi)存的讀寫就是對文件數(shù)據(jù)的讀寫;
映射關(guān)系如下:
在程序的結(jié)構(gòu)體系中,它的整體分布如下圖所示
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。