<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 程序結(jié)構(gòu)分析和理解

          程序結(jié)構(gòu)分析和理解

          作者: 時(shí)間:2016-12-01 來源:網(wǎng)絡(luò) 收藏
          最近的一段時(shí)間又溫習(xí)了一下嵌入式開發(fā)的基本工具和程序的一些基本結(jié)構(gòu),逐漸脫離了機(jī)械學(xué)習(xí)的過程,在學(xué)習(xí)的過程中了解到自己需要了解的東西還很多。記得我在大學(xué)期間學(xué)習(xí)DSP,當(dāng)時(shí)的任務(wù)是完成2048點(diǎn)數(shù)據(jù)的FFT變換,記得當(dāng)時(shí)程序(C語言)完成很快,但是在后期總是不能出現(xiàn)正確的效果,最后發(fā)現(xiàn)原來是CMD(配置)文件存在問題,通過老師的講解以及自己的學(xué)習(xí)了解到了程序的基本結(jié)構(gòu),也就是所謂的代碼段,數(shù)據(jù)段等,以及具體的存儲(chǔ)器管理問題。這些都是鏈接器的基本功能。從此也就知道了程序的一些特點(diǎn)。

          本文引用地址:http://www.ex-cimer.com/article/201612/324539.htm

          1、目標(biāo)文件的構(gòu)成

          二進(jìn)制文件是由一系列的段構(gòu)成的,當(dāng)然也會(huì)存在一些符號(hào),存儲(chǔ)器分配等等,從鏈接文本其實(shí)就能大概知道程序的組成,各個(gè)目標(biāo)文件的同一段結(jié)合起來就實(shí)現(xiàn)了可執(zhí)行程序的鏈接,當(dāng)然具體的鏈接方式和原則都是工具設(shè)計(jì)好的。比如鏈接的順序按著輸入的順序等。

          記得在移植u-boot到TQ2440的過程中,曾經(jīng)就修改過鏈接文本,也就是u-boot.lds文件,當(dāng)時(shí)因?yàn)樽约禾砑恿艘粋€(gè)關(guān)于nand flash 操作的函數(shù),為了保證添加的函數(shù)不會(huì)在鏈接的過程中將啟動(dòng)代碼之前而導(dǎo)致芯片啟動(dòng)存在問題,我特意修改了程序的鏈接順序,保證鏈接文檔正確鏈接。

          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)于二進(jìn)制文件中的基本內(nèi)容主要是包括幾個(gè)段的。當(dāng)然還需要其他的一些條件,在鏈接的過程中,好像還需要一些C語言運(yùn)行的環(huán)境,主要是用來控制程序的啟動(dòng)和關(guān)閉。這些都是crt*(C RunTime)目標(biāo)文件實(shí)現(xiàn)的。這些目標(biāo)文件在我們程序設(shè)計(jì)中不經(jīng)常看到,如果分析過u-boot的編譯過程就會(huì)發(fā)現(xiàn),這些目標(biāo)文件確實(shí)存在。

          鏈接文本使得文件的鏈接更加的方便和實(shí)用。因此了解目標(biāo)的最基本段落是非常的必要的。

          在其中需要注意的幾點(diǎn):

          1、靜態(tài)變量不管是局部還是全局的都是在數(shù)據(jù)段中,而不想局部變量在堆棧中,當(dāng)棧彈出以后,其中的內(nèi)容也就釋放了,靜態(tài)變量不會(huì)改變,但是對(duì)于局部靜態(tài)變量則只能被定義該變量的函數(shù)訪問,不能被其他的函數(shù)訪問。

          2、全局變量、靜態(tài)變量如果被初始化為0,或者沒有被初始化,則該變量被分配到.bss(未初始化部分),只有當(dāng)全局變量和靜態(tài)變量初始化為非零數(shù)值時(shí)才會(huì)分配到.data段中。

          3、全局變量和靜態(tài)變量如果沒有被初始化一般都會(huì)默認(rèn)為0,這也是為什么將這兩個(gè)數(shù)初始化為0,仍然處在.bss段的原因。因此需要注意全局變量和靜態(tài)變量在沒有初始化時(shí)的值,但是對(duì)于局部變量則沒有這個(gè)特點(diǎn),如果沒有初始化則會(huì)出現(xiàn)一個(gè)隨機(jī)值。

          以上的結(jié)論可以通過代碼進(jìn)行手動(dòng)測(cè)試。

          2、Linux中程序結(jié)構(gòu)

          在Linux中每一個(gè)進(jìn)程都存在一個(gè)4G的虛擬空間,其中前3G空間是用戶空間,而后1G空間則是內(nèi)核空間,這4G的空間在各個(gè)進(jìn)程之間都是相互獨(dú)立的。但是這些內(nèi)存空間的區(qū)域分配確實(shí)相同的,而且各個(gè)區(qū)域的起始地址也是固定好的,Linux程序的結(jié)構(gòu)如下:

          由于各個(gè)段的起始地址都是固定的,這樣就便于虛擬地址到物理地址的映射,方便了程序的加載。特別是共享庫的實(shí)現(xiàn)。

          3、堆棧和堆

          其實(shí)我對(duì)這兩個(gè)概念在剛開始的時(shí)候也存在很大的誤解,不明白其中的關(guān)系,總是把堆棧理解成堆和棧,實(shí)質(zhì)上堆棧就是指棧,搞清楚這個(gè),兩者的區(qū)別就容易理解啦。堆棧其實(shí)也可以認(rèn)為是一種數(shù)據(jù)結(jié)構(gòu),典型的先進(jìn)后出特點(diǎn)。

          一般而言堆棧都是反向增長(zhǎng)的,也就是所謂的從高地址到低地址的增長(zhǎng)方式,但是也有其他的增長(zhǎng)方式,比如ARM有4種不同的增長(zhǎng)模式,所以堆棧的增長(zhǎng)方向只能依據(jù)CPU而言,不同的CPU其堆??赡艽嬖谝欢ǖ牟顒e。堆棧主要用來實(shí)現(xiàn)函數(shù)的調(diào)用。

          堆一般而言都是在bass段的上面,主要用來實(shí)現(xiàn)動(dòng)態(tài)內(nèi)存的分配和釋放,在C語言中主要是通過malloc/free函數(shù)實(shí)現(xiàn),在C++中則主要采用new/delete實(shí)現(xiàn)。但是對(duì)于這一塊的內(nèi)存通常會(huì)不斷的分配和釋放以及滿足基本的對(duì)齊形式,這樣就導(dǎo)致了內(nèi)存碎片的產(chǎn)生,減小了訪問的速率。同時(shí)因?yàn)樵谶@段區(qū)域運(yùn)行零空間申請(qǐng),以及釋放后指針仍然有效等問題,所以在釋放完畢以后通常將指針指向NULL。



          評(píng)論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();