專利名稱:一種構(gòu)造中間庫(kù)的方法
技術(shù)領(lǐng)域:
本發(fā)明涉及一種軟件優(yōu)化方法,尤其涉及一種嵌入式系統(tǒng)中對(duì)共享庫(kù)的優(yōu)化方法,具體 涉及 一種嵌入式系統(tǒng)中構(gòu)造中間庫(kù)的方法。本發(fā)明主要應(yīng)用于嵌入式系統(tǒng)軟件中,也可用于普通的PC機(jī)軟件和服務(wù)器軟件系統(tǒng)中。
背景技術(shù):
在支持動(dòng)態(tài)鏈接的系統(tǒng)中, 一個(gè)應(yīng)用程序通常依賴一個(gè)或多個(gè)共享庫(kù), 一個(gè)共享庫(kù)也可 能會(huì)依賴一個(gè)或多個(gè)其它的共享庫(kù)。這種依賴關(guān)系模型如附圖l所示。嵌入式系統(tǒng)的存儲(chǔ)資源通常十分有限,而且對(duì)響應(yīng)速度要求較高。嵌入式系統(tǒng)的專用性 使得開發(fā)人員有可能采用某些特殊的技術(shù)手段對(duì)嵌入式軟件進(jìn)行優(yōu)化,達(dá)到降低成本,提高 性能的目的。許多編譯鏈接工具(如GNUgcc、 ld等)提供了一T、 一R等編譯鏈接選項(xiàng)來對(duì)共享庫(kù)和 應(yīng)用程序進(jìn)行優(yōu)化。在編譯鏈接共享庫(kù)時(shí),使用連接器的一T選項(xiàng)把共享庫(kù)的虛擬地址映射 到應(yīng)用程序的一維虛擬地址空間中(為方便表述,本文后面把這類共享庫(kù)稱為映射庫(kù)),編譯 鏈接應(yīng)用程序時(shí),使用連接器的一R選項(xiàng)從映射庫(kù)中讀入符號(hào)表,具體實(shí)施流程如附圖2所 示,采用這種方式編譯鏈接的應(yīng)用程序的虛擬地址空間可以按照?qǐng)D3布局。實(shí)踐表明,上述方法可使目標(biāo)文件的大小減少20%~30% (不同體系結(jié)構(gòu)略有不同),而 且程序運(yùn)行時(shí)的響應(yīng)速度更快。但是,映射庫(kù)失去了動(dòng)態(tài)鏈接特性,普通動(dòng)態(tài)加載機(jī)制不再有效。通常情況下,這并不 成問題,只需要按照上述方法把相關(guān)的共享庫(kù)和應(yīng)用程序重新編譯鏈接就可以了。但是,在 嵌入式系統(tǒng)開發(fā)中,經(jīng)常會(huì)遇到下面這種情況如附圖1所示,某些應(yīng)用程序沒有源代碼,只有二進(jìn)制可執(zhí)行文件(為方便描述,本文 后面把這類軟件稱為第三方軟件),而第三方軟件依賴共享庫(kù)有源代碼。由于第三方軟件所依賴的共享庫(kù)有源代碼,因此可以按照上述方法,把這些共享庫(kù)編譯 鏈接成映射庫(kù),從而節(jié)省20% 30%的存儲(chǔ)空間。但是,如前面所述,映射庫(kù)不再適用于普 通的動(dòng)態(tài)加載和動(dòng)態(tài)鏈接機(jī)制,而第三方軟件又沒有源代碼,不能重新編譯鏈接。因此,有 第三方軟件存在的場(chǎng)合,很難使用上述方法對(duì)嵌入式系統(tǒng)軟件進(jìn)行優(yōu)化。 發(fā)明內(nèi)容為了克服現(xiàn)有技術(shù)中存在的問題,本發(fā)明提出一種構(gòu)造中間庫(kù)的方法,在不對(duì)第三方軟 件做任何修改的前提下,通過構(gòu)造中間庫(kù),解決了上述難題。 本發(fā)明具體是這樣實(shí)現(xiàn)的一種構(gòu)造中間庫(kù)的方法,其特征在于,包括如下步驟 第1步,生成實(shí)現(xiàn)函數(shù)跳轉(zhuǎn)的中間文件; 第2步,為每個(gè)映射庫(kù)生成一個(gè)初始化文件;第3歩,編譯鏈接中間文件和初始化文件,得到與映射庫(kù)一一對(duì)應(yīng)的中間庫(kù); 第4步,修改映射庫(kù)的文件名;第5步,把中間庫(kù)放到目標(biāo)文件系統(tǒng)中所對(duì)應(yīng)的映射庫(kù)目錄下。 所述第一歩,具體包括如下步驟(1) 分析映射庫(kù)的符號(hào)表,為映射庫(kù)生成一個(gè)符號(hào)列表文件;(2) 從第三方軟件的符號(hào)表中獲取第三方軟件引用的外部符號(hào);(3) 生成第三方軟件引用的外部符號(hào)以及每一個(gè)符號(hào)所對(duì)應(yīng)的映射地址;(4) 生成實(shí)現(xiàn)函數(shù)跳轉(zhuǎn)的中間文件。重復(fù)上述步驟(1)至(4),可為其他映射庫(kù)生成跳轉(zhuǎn)函數(shù)中間文件。 所述第2步中的為每個(gè)映射庫(kù)初始化,包括以下一個(gè)或幾個(gè)步驟 加載映射庫(kù)的符號(hào)表;完成映射庫(kù)中全局變量和全局對(duì)象的初始化;完成虛函數(shù)表初始化; 完成映射庫(kù)中全局對(duì)象的析構(gòu)操作。所述全局變量和全局對(duì)象的初始化,可在中間庫(kù)中重定義映射庫(kù)中的全局變量或全局對(duì) 象,并賦以映射庫(kù)中相同的初始值。所述虛函數(shù)的初始化,通過把映射庫(kù)中各個(gè)虛函數(shù)表的內(nèi)容拷貝到中間庫(kù)地址空間中實(shí)現(xiàn)。由于第三方軟件不能按照普通的動(dòng)態(tài)加載和動(dòng)態(tài)鏈接的方式調(diào)用映射庫(kù)中的函數(shù),也不 能J下確地訪問映射庫(kù)中的全局變量和全局對(duì)象。本發(fā)明通過為每一個(gè)映射庫(kù)構(gòu)造一個(gè)中間庫(kù), 在中間庫(kù)內(nèi)部完成函數(shù)跳轉(zhuǎn)、全局變量和全局對(duì)象初始化等操作,解決了上述難題。采用本發(fā)明所述方法,通過構(gòu)造中間庫(kù),解決了第三方軟件不能訪問映射庫(kù)中的函數(shù)和 全局變量的難題;把共享庫(kù)編譯鏈接為映射庫(kù),雖然增加了一些中間庫(kù),但是由于這些中間 庫(kù)都非常小,總體來看,整個(gè)軟件系統(tǒng)的大小可減少20% 30%;并且應(yīng)用程序的運(yùn)行時(shí)響 應(yīng)速度也更快。軟件變小意味著存儲(chǔ)空間需求的減少,也就意味著硬件成本的降低,響應(yīng)速 度的提高意味更好的客戶體驗(yàn)和更高的市場(chǎng)占有率。
圖1是支持動(dòng)態(tài)鏈接的系統(tǒng)中應(yīng)用程序和共享庫(kù)的依賴關(guān)系模型; 圖2是采用地址空間映射方式優(yōu)化嵌入式軟件的處理流程; 圖3是采用地址空間映射方式編譯的應(yīng)用程序的虛擬地址空間布局; 圖4是本發(fā)明所述方法的體系結(jié)構(gòu)圖;圖5是本發(fā)明所述方法的實(shí)施步驟。
具體實(shí)施方式
下面結(jié)合附圖,對(duì)本發(fā)明所述方法進(jìn)行詳細(xì)的描述。圖1 圖3是描述本發(fā)明相關(guān)背景技術(shù)的。圖1展示了支持動(dòng)態(tài)連接的系統(tǒng)中應(yīng)用程序和共享庫(kù)的依賴關(guān)系模型。其中實(shí)線表示應(yīng) 用程序?qū)蚕韼?kù)的依賴關(guān)系,虛線表示共享庫(kù)對(duì)其它共享庫(kù)的依賴關(guān)系。通常情況下, 一個(gè) 應(yīng)用程序經(jīng)常會(huì)依賴一個(gè)或多個(gè)共享庫(kù),一個(gè)共享庫(kù)也可能會(huì)依賴一個(gè)或多個(gè)其它的共享庫(kù)。圖2描述采用地址空間映射方法優(yōu)化嵌入式軟件的處理流程。按照此流程編譯生成的應(yīng) 用程序和共享庫(kù)的虛擬地址空間布局如圖3所示。圖3顯示采用地址空間映射方式編譯的應(yīng)用程序的虛擬地址空間布局。如圖所示,如果 一個(gè)應(yīng)用程序依賴多個(gè)共享庫(kù),那么這些共享庫(kù)的虛擬地址從addrl丌始依次分布,每一個(gè) 共享庫(kù)占一個(gè)虛擬地址的槽位,虛擬地址槽位互不重疊和覆蓋,應(yīng)用程序的虛擬地址從addr2開始。實(shí)踐表明,映射庫(kù)和使用映射庫(kù)編譯鏈接的應(yīng)用程序的大小要比按照普通動(dòng)態(tài)鏈接方式 編譯鏈接的結(jié)果小約20 30% (不同體系結(jié)構(gòu)略有不同),而且,使用映射庫(kù)的應(yīng)用程序運(yùn) 行時(shí),不再執(zhí)行普通的動(dòng)態(tài)鏈接過程,因此程序的響應(yīng)速度更快。下面結(jié)合附圖4,以本發(fā)明在Linux操作系統(tǒng)上的應(yīng)用為列來做進(jìn)一步的詳細(xì)說明 圖4是本發(fā)明的體系結(jié)構(gòu)圖。如圖所示,第三方軟件通過中間庫(kù)訪問映射庫(kù)中的函數(shù)和 全局變量。對(duì)于普通的動(dòng)態(tài)鏈接,應(yīng)用程序訪問共享庫(kù)中的函數(shù)時(shí),首先檢査被調(diào)用的函數(shù) 是否已經(jīng)加載到內(nèi)存中,如果已經(jīng)加載,則通過動(dòng)態(tài)鏈接跳轉(zhuǎn)到共享庫(kù)中的函數(shù)執(zhí)行,如果
被調(diào)用的函數(shù)還沒有加載到內(nèi)存,則首先執(zhí)行庫(kù)的加載過程,然后在通過動(dòng)態(tài)鏈接跳轉(zhuǎn)到共 享庫(kù)中的函數(shù)執(zhí)行。在本發(fā)明中,映射庫(kù)是不能被動(dòng)態(tài)加載的,第三方軟件調(diào)用映射庫(kù)中的函數(shù)都已經(jīng)被轉(zhuǎn) 換成了對(duì)中間庫(kù)里面對(duì)應(yīng)的跳轉(zhuǎn)函數(shù)的調(diào)用,中間庫(kù)中的跳轉(zhuǎn)函數(shù)把程序流程跳轉(zhuǎn)到映射庫(kù) 中指定函數(shù)的起始映射地址。例如某個(gè)第三方軟件依賴于映射庫(kù)1和映射庫(kù)2,在如圖3所示的虛擬地址布局中,映射庫(kù)l的起始虛擬地址是maplibladdr,映射庫(kù)2的起始虛擬地址是maplib2addr,第三方軟 件的起始虛擬地址是appaddr,第三方軟件調(diào)用了映射庫(kù)1中的函數(shù)mapliblfunc和映射庫(kù)2 中的函數(shù)maplib2func,這兩個(gè)函數(shù)的虛擬地址在編譯鏈接時(shí)已經(jīng)確定,分別是 maplibladdr+offsetl禾fl maplib2addr+offset2,中間庫(kù)中與這兩個(gè)函數(shù)對(duì)應(yīng)的跳轉(zhuǎn)函數(shù)可以用 ARM匯編指令描述如下.globl mapliblfunc的符號(hào).type mapliblfhnc的符號(hào),#function mapliblfimc的符號(hào)add ip, pc, #4ldr ip,[ip〗mov pc, ip.word maplibladdr+offsetl .globl maplib2fiinc的符號(hào) .type maplib2fimc的符號(hào),#flinction maplib2ftinc的符號(hào) add ip, pc, #4 ldr ip,[ip] mov pc, ip.word maplib2addr+offset2 當(dāng)?shù)谌杰浖{(diào)用映射庫(kù)1中的mapliblfunc函數(shù)時(shí),程序?qū)嶋H調(diào)用中間庫(kù)的mapliblfunc函數(shù),從上面的代碼可以看到,緊接著執(zhí)行的四行代碼將把流程跳轉(zhuǎn)到虛擬地址 maplibladdr+offsetl,這正好就是映射庫(kù)1中mapliblfunc函數(shù)的虛擬地址,這樣就實(shí)現(xiàn)了對(duì) 映射庫(kù)中函數(shù)的調(diào)用。中間庫(kù)對(duì)映射庫(kù)的初始化包括加載映射庫(kù)的符號(hào)表、映射庫(kù)中的全局變量和全局對(duì)象的 初始化、以及虛函數(shù)表初始化。全局變量和全局對(duì)象的初始化可以在中間庫(kù)中重定義映射庫(kù)中的全局變量或全局對(duì)象,
并賦以映射庫(kù)中相同的初始值。初始化函數(shù)可以這樣定義:void —attribute一 ((constructor)) lib—init()加載映射庫(kù)符號(hào)表; 中間庫(kù)虛函數(shù)表初始化;依次調(diào)用映射庫(kù)中的構(gòu)造函數(shù),直到所有構(gòu)造函數(shù)都已被執(zhí)行在Linux操作系統(tǒng)上,加載映射庫(kù)的符號(hào)表可以通過設(shè)置環(huán)境變量LD—PRELOAD實(shí)現(xiàn); 虛函數(shù)表的初始化可以通過把映射庫(kù)中各個(gè)虛函數(shù)表的內(nèi)容拷貝到中間庫(kù)的地址空間中 實(shí)現(xiàn)。此外,中間庫(kù)還要完成第三方軟件退出時(shí)的善后工作,即執(zhí)行映射庫(kù)中全局對(duì)象的析構(gòu) 函數(shù),釋放資源。在Linux操作系統(tǒng)上,可以在中間庫(kù)中定義如下函數(shù)來實(shí)現(xiàn) void —attribute一 ((destructor)) lib一finit()圖5展示了本發(fā)明的具體實(shí)施步驟。下面描述在Linux環(huán)境中各個(gè)子步驟的實(shí)現(xiàn)方法。 構(gòu)造函數(shù)跳轉(zhuǎn)中間文件,由以下幾個(gè)步驟來具體完成1、 分析映射庫(kù)的符號(hào)表,為映射庫(kù)生成一個(gè)符號(hào)列表文件可以用nm工具方便地提取 出ELF文件的符號(hào)表和它們的地址,在普通的共享庫(kù)中,這個(gè)地址是共享庫(kù)內(nèi)部的偏移量;對(duì)映射庫(kù)而言,這個(gè)地址是函數(shù)的絕對(duì)虛擬地址;2、 從第三方軟件的符號(hào)表中獲取第三方軟件引用的外部符號(hào)可以借助readdf、 grep 工具編寫腳本實(shí)現(xiàn);3、 生成第三方軟件引用的外部符號(hào)以及每一個(gè)符號(hào)所對(duì)應(yīng)的映射地址前兩步的輸出是 文本文件,可以編寫一個(gè)shell腳本或者c程序,分析前兩個(gè)子步驟輸出的文本文件,從而提 取出所需要的信息;4、 生成實(shí)現(xiàn)函數(shù)跳轉(zhuǎn)功能的中間文件跳轉(zhuǎn)函數(shù)的功能簡(jiǎn)單,結(jié)構(gòu)單一,因此可以用shell 腳本或者c程序,根據(jù)上一步獲得的第三方軟件引用的外部符號(hào)和它們對(duì)應(yīng)的虛擬地址,構(gòu) 造出跳轉(zhuǎn)函數(shù)的匯編代碼。跳轉(zhuǎn)函數(shù)的具體處理流程參見前面對(duì)附圖4的詳細(xì)描述部分;5、 重復(fù)上述四個(gè)子步驟步,依次為其它的映射庫(kù)生成函數(shù)跳轉(zhuǎn)中間文件。依次調(diào)用映射庫(kù)中的析構(gòu)函數(shù),直到所有析構(gòu)函數(shù)都已被執(zhí)行7
構(gòu)造中間庫(kù)的初始化文件初始化文件要完成的功能包括加載映射庫(kù)的符號(hào)表、映射庫(kù) 中的全局變量和全局對(duì)象的初始化、以及虛函數(shù)表初始化,可以用匯編語(yǔ)言實(shí)現(xiàn),也可以用 c或者其它高級(jí)編程語(yǔ)言實(shí)現(xiàn),該文件要完成的功能和具體實(shí)現(xiàn)參見前面對(duì)附圖4的詳細(xì)描 述部分;編譯鏈接生成中間庫(kù)這是按照編譯普通的共享庫(kù)的方式,編譯鏈接函數(shù)跳轉(zhuǎn)中間文件 和中間庫(kù)的初始化文件,得到中間庫(kù)。所有中間庫(kù)都是標(biāo)準(zhǔn)的動(dòng)態(tài)鏈接庫(kù)。映射庫(kù)更名修改映射庫(kù)的文件名,以免與中間庫(kù)文件名沖突。 最后,把每一個(gè)中間庫(kù)都放到目標(biāo)文件系統(tǒng)中它所對(duì)應(yīng)的映射庫(kù)所在的目錄下。 完成上述操作,第三方軟件就可以按照普通的方式正常運(yùn)行了,不同之處在于這樣生成 的映射庫(kù)、中間庫(kù)和第三方軟件的大小要比按照標(biāo)準(zhǔn)動(dòng)態(tài)鏈接方式編譯的文件小約20%~30%,而且軟件的運(yùn)行時(shí)響應(yīng)速度更快。軟件變小意味著硬件成本的降低,響應(yīng)速度的提高意味更好的客戶體驗(yàn)和更高的市場(chǎng)占有率。
權(quán)利要求
1、一種構(gòu)造中間庫(kù)的方法,其特征在于,包括如下步驟第1步,生成實(shí)現(xiàn)函數(shù)跳轉(zhuǎn)的中間文件;第2步,為每個(gè)映射庫(kù)生成一個(gè)初始化文件;第3步,編譯鏈接中間文件和初始化文件,得到與映射庫(kù)一一對(duì)應(yīng)的中間庫(kù);第4步,修改映射庫(kù)的文件名;第5步,把中間庫(kù)放到目標(biāo)文件系統(tǒng)中所對(duì)應(yīng)的映射庫(kù)目錄下。
2、 如權(quán)利要求l所述的構(gòu)造中間庫(kù)的方法,其特征在于 所述第一歩,具體包括如下步驟(1) 分析映射庫(kù)的符號(hào)表,為映射庫(kù)生成一個(gè)符號(hào)列表文件;(2) 從第三方軟件的符號(hào)表中獲取第三方軟件引用的外部符號(hào);(3) 生成第三方軟件引用的外部符號(hào)以及每一個(gè)符號(hào)所對(duì)應(yīng)的映射地址;(4) 生成實(shí)現(xiàn)函數(shù)跳轉(zhuǎn)的中間文件。
3、 如權(quán)利要求2所述的構(gòu)造中間庫(kù)的方法,其特征在于-重復(fù)上述步驟(1)至(4),可為其他映射庫(kù)生成跳轉(zhuǎn)函數(shù)中間文件。
4、 如權(quán)利要求l所述的構(gòu)造中間庫(kù)的方法,其特征在于-所述第2歩中的為每個(gè)映射庫(kù)初始化,包括以下一個(gè)或幾個(gè)步驟 加載映射庫(kù)的符號(hào)表;完成映射庫(kù)中全局變量和全局對(duì)象的初始化;完成虛函數(shù)表初始化;完成映射庫(kù)中全局對(duì)象的析構(gòu)操作。
5、 如權(quán)利要求4所述的構(gòu)造中間庫(kù)的方法,其特征在于所述全局變量和全局對(duì)象的初始化,可在中間庫(kù)中重定義映射庫(kù)中的全局變量或全局對(duì) 象,并賦以映射庫(kù)中相同的初始值。
6、 如權(quán)利要求4構(gòu)造中間庫(kù)的方法,其特征在于-所述虛函數(shù)的初始化,通過把映射庫(kù)中各個(gè)虛函數(shù)表的內(nèi)容拷貝到中間庫(kù)地址空間中實(shí)
全文摘要
本發(fā)明公開了一種構(gòu)造中間庫(kù)的方法,包括,生成實(shí)現(xiàn)函數(shù)跳轉(zhuǎn)的中間文件;為每個(gè)映射庫(kù)生成一個(gè)初始化文件;編譯鏈接中間文件和初始化文件,得到與映射庫(kù)一一對(duì)應(yīng)的中間庫(kù);修改映射庫(kù)的文件名;把中間庫(kù)放到目標(biāo)文件系統(tǒng)中所對(duì)應(yīng)的映射庫(kù)目錄下。本發(fā)明在不對(duì)第三方軟件做任何修改的前提下,通過構(gòu)造中間庫(kù),解決了第三方軟件不能訪問映射庫(kù)中的函數(shù)和全局變量的難題;把共享庫(kù)編譯鏈接為映射庫(kù),使整個(gè)軟件系統(tǒng)的大小減少20%~30%,應(yīng)用程序的運(yùn)行時(shí)響應(yīng)速度加快。
文檔編號(hào)G06F9/44GK101165648SQ20061014966
公開日2008年4月23日 申請(qǐng)日期2006年10月16日 優(yōu)先權(quán)日2006年10月16日
發(fā)明者翌 李, 程圣宇, 敬 繆 申請(qǐng)人:中興通訊股份有限公司