程序結(jié)構(gòu)分析和理解
1、目標(biāo)文件的構(gòu)成
二進制文件是由一系列的段構(gòu)成的,當(dāng)然也會存在一些符號,存儲器分配等等,從鏈接文本其實就能大概知道程序的組成,各個目標(biāo)文件的同一段結(jié)合起來就實現(xiàn)了可執(zhí)行程序的鏈接,當(dāng)然具體的鏈接方式和原則都是工具設(shè)計好的。比如鏈接的順序按著輸入的順序等。
記得在移植u-boot到TQ2440的過程中,曾經(jīng)就修改過鏈接文本,也就是u-boot.lds文件,當(dāng)時因為自己添加了一個關(guān)于nand flash 操作的函數(shù),為了保證添加的函數(shù)不會在鏈接的過程中將啟動代碼之前而導(dǎo)致芯片啟動存在問題,我特意修改了程序的鏈接順序,保證鏈接文檔正確鏈接。
1. [root@Gong-Computer u-boot-2010.06]# vi arch/arm/cpu/arm920t/u-boot.lds
2. . = ALIGN(4);
3. .text :
4. {
5. arch/arm/cpu/arm920t/start.o (.text)
6. board/samsung/smdk2440/lowlevel_init.o (.text)
7. board/samsung/smdk2440/nand_read.o (.text)
8. *(.text)
9. }
關(guān)于二進制文件中的基本內(nèi)容主要是包括幾個段的。當(dāng)然還需要其他的一些條件,在鏈接的過程中,好像還需要一些C語言運行的環(huán)境,主要是用來控制程序的啟動和關(guān)閉。這些都是crt*(C RunTime)目標(biāo)文件實現(xiàn)的。這些目標(biāo)文件在我們程序設(shè)計中不經(jīng)??吹剑绻治鲞^u-boot的編譯過程就會發(fā)現(xiàn),這些目標(biāo)文件確實存在。
鏈接文本使得文件的鏈接更加的方便和實用。因此了解目標(biāo)的最基本段落是非常的必要的。
在其中需要注意的幾點:
1、靜態(tài)變量不管是局部還是全局的都是在數(shù)據(jù)段中,而不想局部變量在堆棧中,當(dāng)棧彈出以后,其中的內(nèi)容也就釋放了,靜態(tài)變量不會改變,但是對于局部靜態(tài)變量則只能被定義該變量的函數(shù)訪問,不能被其他的函數(shù)訪問。
2、全局變量、靜態(tài)變量如果被初始化為0,或者沒有被初始化,則該變量被分配到.bss(未初始化部分),只有當(dāng)全局變量和靜態(tài)變量初始化為非零數(shù)值時才會分配到.data段中。
3、全局變量和靜態(tài)變量如果沒有被初始化一般都會默認(rèn)為0,這也是為什么將這兩個數(shù)初始化為0,仍然處在.bss段的原因。因此需要注意全局變量和靜態(tài)變量在沒有初始化時的值,但是對于局部變量則沒有這個特點,如果沒有初始化則會出現(xiàn)一個隨機值。
以上的結(jié)論可以通過代碼進行手動測試。
2、Linux中程序結(jié)構(gòu)
在Linux中每一個進程都存在一個4G的虛擬空間,其中前3G空間是用戶空間,而后1G空間則是內(nèi)核空間,這4G的空間在各個進程之間都是相互獨立的。但是這些內(nèi)存空間的區(qū)域分配確實相同的,而且各個區(qū)域的起始地址也是固定好的,Linux程序的結(jié)構(gòu)如下:
由于各個段的起始地址都是固定的,這樣就便于虛擬地址到物理地址的映射,方便了程序的加載。特別是共享庫的實現(xiàn)。
3、堆棧和堆
其實我對這兩個概念在剛開始的時候也存在很大的誤解,不明白其中的關(guān)系,總是把堆棧理解成堆和棧,實質(zhì)上堆棧就是指棧,搞清楚這個,兩者的區(qū)別就容易理解啦。堆棧其實也可以認(rèn)為是一種數(shù)據(jù)結(jié)構(gòu),典型的先進后出特點。
一般而言堆棧都是反向增長的,也就是所謂的從高地址到低地址的增長方式,但是也有其他的增長方式,比如ARM有4種不同的增長模式,所以堆棧的增長方向只能依據(jù)CPU而言,不同的CPU其堆??赡艽嬖谝欢ǖ牟顒e。堆棧主要用來實現(xiàn)函數(shù)的調(diào)用。
堆一般而言都是在bass段的上面,主要用來實現(xiàn)動態(tài)內(nèi)存的分配和釋放,在C語言中主要是通過malloc/free函數(shù)實現(xiàn),在C++中則主要采用new/delete實現(xiàn)。但是對于這一塊的內(nèi)存通常會不斷的分配和釋放以及滿足基本的對齊形式,這樣就導(dǎo)致了內(nèi)存碎片的產(chǎn)生,減小了訪問的速率。同時因為在這段區(qū)域運行零空間申請,以及釋放后指針仍然有效等問題,所以在釋放完畢以后通常將指針指向NULL。
評論