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