公司名稱 | 諸暨漫游未來影院有限公司 | 成立時間 | 2015年08月18日 |
---|---|---|---|
總部地點 | 諸暨市暨陽街道苧蘿東路122號朗臻新天地B212-B222 |
諸暨永利房產(chǎn)開發(fā)有限公司還是不錯的,技術支持、健全的售后服務,我們有好的產(chǎn)品和專業(yè)的銷售和技術團隊,目前團隊人數(shù)有30人。 地址:紹興 暨陽街道友誼路158號 主要經(jīng)營一般經(jīng)營項目:房地產(chǎn)咨詢 房地產(chǎn)...
諸暨市品位銅門制造有限公司的產(chǎn)品防盜性特強。專業(yè)高級防盜鎖、保險栓、門縫明暗栓、外口看不見鎖體和鎖芯、屬標準內(nèi)置鎖。貴而層次高,銅門豪華氣派,顯示貴族身份,品味上升,價值位高。拿不銹鋼本錢和加工費與市...
諸暨興達家居市場有限公司是不錯的,家居產(chǎn)品種類豐富,價格實惠,產(chǎn)品做工很精湛,看得出在做工方面非常用心,沒有發(fā)現(xiàn)瑕疵,材料選用純正材質(zhì),架構結實。非常符合日常使用要求,產(chǎn)品憑借美觀,舒適,實用,人性話...
格式:pdf
大?。?span id="eb47mva" class="single-tag-height">65KB
頁數(shù): 16頁
評分: 4.6
諸暨市城市建設投資發(fā)展有限公司 諸暨市濱江北路延伸段綠地公園建設項目 環(huán) 境 影 響 報 告 表 (簡要本) 紹興市環(huán)球環(huán)境保護科學設計研究院有限公司 國環(huán)評證乙字號第 2005號 二 0一三年二月 目 錄 第一章 建設項目基本情況 ............................................................................. 1 1.1項目由來 ................................................................................................. 1 第二章 項目周邊環(huán)境及保護目標 ............................................................... 3 2.1項目地理位置
格式:pdf
大?。?span id="iwm6e62" class="single-tag-height">65KB
頁數(shù): 5頁
評分: 4.5
每日 條信息更新,多維度檢索、企業(yè)資80000+ 質(zhì)匹配、甲方監(jiān)控等功能,讓中標快人一步! www.bidizhaobiao.com 本報告于 2019年9月19日 生成 1/5 www.bidizhaobiao.com 招標投標企業(yè)報告 杭州經(jīng)緯工程管理咨詢有限公司諸暨分公司 每日 條信息更新,多維度檢索、企業(yè)資80000+ 質(zhì)匹配、甲方監(jiān)控等功能,讓中標快人一步! www.bidizhaobiao.com 本報告于 2019年9月19日 生成 2/5 www.bidizhaobiao.com 本報告于 2019年9月19日 生成 您所看到的報告內(nèi)容為截至該時間點該公司的數(shù)據(jù)快照 目錄 1. 基本信息:工商信息 2. 招投標情況: 招標數(shù)量、招標情況、招標行業(yè)分布、投標企業(yè)排名、中標企業(yè) 排名 3. 股東及出資信息 4. 風險信息:經(jīng)營異常、股權出資、動產(chǎn)抵押、稅務信息
影院建設項目在籌備后,進入設計施工期,由施工方代為設計電影院,或者進行設計招標,而電影院設計就是整個影院建設的關鍵部分,它一般的住宅設計不同,因為電影院建成后五到十年內(nèi)不會更換裝修風格,要保持該階段內(nèi)的時尚新穎感。
影院設計構成
通用的電影院設計結構包括等候大廳、票房、賣品部、檢票口、過道走廊、影廳、放映室、廁所,有條件的還要建設貴賓室、吸煙區(qū)、貴賓廳、員工休息室、辦公區(qū)等。
影院元素
影院設計。影院元素包括幾個系統(tǒng):等候大廳主題系統(tǒng)、售票系統(tǒng)、賣品系統(tǒng)、影務系統(tǒng)、電影放映系統(tǒng)、影廳、廁所、影院文化系統(tǒng)、影訊發(fā)布系統(tǒng)、影院輔助系統(tǒng)等。 售票系統(tǒng)是指由賣票柜臺和電子售票系統(tǒng)組成的設備設施,包括售票柜臺、選座電腦顯示屏、會員通道、Led大屏幕等。 賣品系統(tǒng)是指由賣品柜臺、賣品銷售系統(tǒng)、各種可樂機、飲料柜員機、爆米花機、各種冰柜、賣品庫房、賣品制作間等組成。 影務系統(tǒng)是指由檢票口票臺、進場時鐘組成。
電影放映系統(tǒng)是指放映室內(nèi)設施和各種放映設備、放映工作區(qū)、停片區(qū)、倒片區(qū)、撿片區(qū)等組成。
影廳由廳號、隔音幕墻、階梯座位、放映窗口、控制臺、溫濕度儀、銀幕及輔助設施、環(huán)繞立體聲音箱、清潔燈、測光等、散場燈、地角燈、其他各種修飾燈,一級出入場通道組成。
影院文化系統(tǒng)主要是指在一些等候區(qū)域和諧的融入一些電影院特色的文化宣傳圖片或文化墻,還包括影城大廳主題海報燈箱、國道走廊海報燈箱等。
影訊發(fā)布系統(tǒng)是指電影院大廳、廁所、吸煙區(qū)的各種電視墻和電視。
大廳主題系統(tǒng)包括大廳雕飾、大廳四周高層相應象征物件和各種效果的燈組。
影院的設計風格和色彩
影院設計。電影院的設計風格除了時尚、三五年不落伍之外,一般都要與國際接軌。電影院的風格要融入當?shù)氐奈幕厣?,在色彩方面慣用藍色主題、紅色主題和黃色主題,凸顯現(xiàn)代影院娛樂功能,因此顏色鮮艷明快,同時又有一定的厚重感,不張揚。大廳、走廊裝飾凸顯層次。
項目施工
項目施工是在現(xiàn)有電影院設計圖紙的基礎上進行的,對一些圖紙未提及文化,要進行重新創(chuàng)意設計。
項目施工期從原材料送達之日起算起,一般需要3個月(90天)時間,先從框架結構做起,分離出等候大廳、影廳區(qū)、放映去、辦公區(qū),然后再進行影廳拆分、座位鋼結構搭建、再到天花板、各種空燈、幕墻、座椅、地毯安裝,最后是立體聲系統(tǒng)安裝、銀幕安裝和地角燈的安裝調(diào)試。最后是影城票房、賣品部進駐和大廳施工。
影城施工通常由4~5個施工隊伍同時施工,包括鋼結構施工隊、幕墻施工隊、地磚施工隊、地毯座椅施工隊和造景施工隊組成,一級強電、弱電等。
城市中越來越多的購物中心出現(xiàn),電影院幾乎成了其標配之一。但就像是購物中心的服飾品牌、餐飲種類大同小異,電影院的空間設計也罕有新意。
4D動感影院介紹
4D動感影院,由三維立體電影和周圍的環(huán)境模擬組成的四維空間,它是在3d立體電影的基礎上加環(huán)境特效、模擬仿真而組成的新型影視產(chǎn)品,通過給觀眾以電影內(nèi)容聯(lián)動的物理刺激,來增強臨場感的效果。隨著影院娛樂技術的發(fā)展和娛樂市場的需求,人們不僅將震動、墜落、吹風、噴水、撓癢等特技引入3D影院,還根據(jù)影片的情景精心設計出煙霧、雨、光電、氣泡等效果,形成了一種獨特的體驗,這就是當今十分流行的4D影院。
4D動感影院組成
4D動感影院整體系統(tǒng)由專業(yè)級、震撼的立體投影,銀幕, 4D座椅,環(huán)境特效, 數(shù)碼音響,影院總控制系統(tǒng)等組成。其相比較于其他類型影院,具有主題突出、科技含量高、效果逼真、娛樂性強等特點和優(yōu)勢。
動感影院環(huán)境特效
廣州全影匯VR“4D動感影院”可以添加刮風,下雨,下雪,閃電,煙霧,泡泡等特效,觀影時影片里會出現(xiàn)風,雨,電,煙霧,泡泡等自然現(xiàn)象時,特效設備也將同步出現(xiàn)這些自然現(xiàn)象,讓體驗者感受到近乎極致和身臨其境的參與感與互動性!
系統(tǒng)框架結構圖
4D動感影院與4D游戲采用相同的工作原理,是利用專業(yè)的3D開發(fā)引擎,借助3D立體電視、投影器等顯示設備、立體眼鏡等接收設備,通過兩部具有一定視覺差的影像(即模擬人體雙眼的立體成像功能所塑造的影像)組合,在觀眾或玩家參與過程體現(xiàn)出較強互動性的效果。
4D動感座椅特效
全影匯VR4D動感平臺可以精準模擬前傾、后仰、左傾、右傾、墜落、顛簸、吹風、噴水、掃腿、捅背、震股等動作。當影片出現(xiàn)以下場景時,你會體驗到相對應的特效。例如:影片情節(jié)里摩托向左或向右拐彎時,座椅會做出相應的動作;影片情節(jié)里從高空向下墜落時,座椅會模擬快速向下。這一系列電影情節(jié)動感座椅都能模擬并且完全同步!
多款連排動感座椅
4D動感座椅是建立4D動感影院必不可少的構成元素之一,4D動感座椅可以根據(jù)4D動感影院中特效座椅的布置故事情節(jié)的不同而由計算機控制做出不同的特技效果來,例如,墜落,震蕩,噴風,噴雨等等,再配上精心設計出來的煙霧、雨、光電、氣泡、氣味等,從而營造一種與影片內(nèi)容相一致的全感知環(huán)境。
4D動感影院施工案例
環(huán)幕4D動感影院不同于一般的電影屏幕,采用柱面環(huán)幕投影顯示方式,將觀賞著圍繞在中心。屏幕上的超長跨度的廣闊畫面充滿觀賞者的視野,全方位立體聲與影片情節(jié)相輔相成、完美配合,演繹精彩絕倫的沉浸式視聽享受。柱面投影屏幕的弧度有360度、270度、180度等多種選擇,可根據(jù)場地具體情況進行個性化設計和施工,保證4D環(huán)幕動感影院效果。
4D動感影院成功案例
全影匯VR科技貴州遵義動感影院成功案例等采用立體投影系統(tǒng),結合擁有自主知識產(chǎn)權的動感設備、環(huán)境特效、燈光特效系統(tǒng), 將從視覺、聽覺、嗅覺、感覺等方面,為觀眾帶來身臨其境前所未有的刺激體驗。
全影匯:http://www.chinavrway.com
來源:MRRiddler ,
blog.mrriddler.com/2017/02/10/計算機體系-編譯體系漫游/
要想讓代碼乖乖運行,自然代碼要先經(jīng)過編譯,這篇文章就來聊聊編譯體系。
代碼的編譯過程分為四個階段,預處理、編譯、匯編、鏈接。而編譯階段是整個過程中最復雜的階段,編譯階段還可以分為詞法分析、語法分析、語義分析。
在一頭扎進這四個階段之間,先聊一下語法、語義。人類之所以能在進化的歷史長河中,成為動物中的佼佼者,進化出的復雜的溝通機制—語言功不可沒。假如,我說出這句話:你個產(chǎn)品狗還在改需求!那么語法是啥呢?簡單說就是構成這句話的順序,假如順序錯亂意思就不同了。那么語義是啥呢?就是語境,根據(jù)我說這句話的情景,才能解釋出你指的是誰。語法在編程語言中,表現(xiàn)出來的就是語法結構和結合律。語義表現(xiàn)出來的就是上下文(context)。
預處理(Preprocess):處理預處理符(#),包括宏展開、頭文件引入。 詞法分析(Lexical Analysis、Tokenizer):寫出的代碼實際上就是字符串,此階段需要對字符串進行掃描(Scanner),將字符串掃描出分析的最基本單位(token),并在掃描過程中將它們分類,此階段是沒有任何語義的。也可以理解成將代碼掃描出基本表達式。 語法分析(Syntactic analysis、Parser):生成AST抽象語法樹,檢查語法結構,此階段是上下文無關的。也可以理解成將基本表達式按語法結構組合成復合表達式。 語義分析(Semantic Analysis):語義檢查(比如檢查浮點數(shù)乘以指針,雖然語法結構正確但是語義檢查不合格),將程序與上下文結合,進行靜態(tài)類型分析,確定AST每個節(jié)點的類型。也可以理解將復合表達式結合環(huán)境(Environment),并且確定基本表達式、復合表達式的類型。 中間碼(Intermediate Representation):與語言無關、平臺無關的中間碼。如果編譯器面向多語言,對于任意語言編譯階段后可以生成通用的中間碼,這樣編譯器就有多語言的高拓展性了。生成中間碼后再交給匯編階段,再生成與平臺相關的匯編,這樣使編譯器將平臺相關性盡量往后推移。中間碼除了做為“橋接“,對中間碼的優(yōu)化也是整個編譯過程中的關鍵優(yōu)化。 匯編(Assemble):對中間碼生成平臺具體的匯編,在這個階段添加對多個平臺的支持,編譯器就可以跨平臺了。最后生成機器碼。 鏈接(Link):將每個機器碼編譯單位中引用的其他編譯單位中的變量、函數(shù)符號修正(fix)成真實地址。編譯歷史
編譯的歷史基本就是計算機的進化史,是很有趣的一段故事。Long time ago… 程序員寫程序都是用紙帶,那時候還在寫0、1機器碼。紙帶上打孔就是0,不打孔就是1。然后計算機讀取紙帶就是讀取指令。但是就像互聯(lián)網(wǎng)本質(zhì)就是提高效率一樣,這樣寫程序的效率怎能接受?并且,寫程序如果犯了錯誤怎么辦?重新從頭到尾再用新紙帶搞一遍?程序員們機智的開始想辦法了,先是這樣搞:
將指帶有誤的地方,用黑黑的小貼紙?zhí)钌先ィ@樣將0改成1了。這也是Patch名字的由來。但是這樣寫指令效率還是太低,程序員們再機智的想辦法。后來將指令進行符號化(Symbol),抽象出指令集,這時就出現(xiàn)了匯編,程序員的效率上了一個檔次。但是新的問題又出現(xiàn)了。在寫過程調(diào)用的時候,要寫jmp 具體的函數(shù)地址。如果后來要在被調(diào)用的函數(shù)前面添加指令,那么函數(shù)地址也要跟著改。這樣牽一發(fā)動全身的感覺可不好,為了讓影響(impact)縮減到最小,不如將函數(shù)地址也符號化。凡是寫過程調(diào)用先寫成jmp func,等到程序生成機器碼的時候,再將func換成真正的函數(shù)地址,這一步也就是將程序員手動修正交由匯編器修正。
隨著生產(chǎn)力的提升,程序的規(guī)模越來越大,新的問題出現(xiàn)了,程序膨脹到難以維護和閱讀了。程序員們就將程序模塊化、層次化。這樣也使編譯的單位更小粒度化。編譯的時候,不同編譯單位之間的細節(jié)是互相隔離的。比如,對于C語言系,一個.h和一個.m就構成了一個編譯單位。.m匯編時,是不知道其他.m的全局變量、函數(shù)地址的,而調(diào)用的時候就只能用符號進行調(diào)用,等到最后所有.m都生成機器碼后再進行統(tǒng)一的修正。而負責這一步的就是鏈接器(Linker),這一步也叫重定位(Relocation)。
目標文件
經(jīng)過匯編這一階段后,就會生成目標文件。目標文件和可執(zhí)行文件已經(jīng)非常相近了,只是有些符號還未修正,結構上會進行調(diào)整。Windows平臺下為PE(Portable Executable),Linux平臺下為ELF(Executable Linkable Format),Mac平臺下為Mach-O。雖然不同平臺都有自己的格式,但是它們實際上都大同小異。下面大體聊一下文件的實際字段,這些知識會為后面我們搞一些符號重綁定做鋪墊。
section
首先,文件分段(section)。不同的Section放置不同的信息,文件還有一個section header table放置控制信息。實際上,就類似圖片格式和mutipart的HTTP報文。以下是一個ELF目標文件的常見section:
—— —— —— —— —— —— ——
|header | -----> 文件頭
|—— —— —— —— —— —— ——|
|.text | -----> 代碼段
|—— —— —— —— —— —— ——|
|.data | -----> 已初始化全局變量、靜態(tài)變量
|—— —— —— —— —— —— ——|
|.bss | -----> 未初始化全局變量、靜態(tài)變量
|—— —— —— —— —— —— ——|
|other sections... |
|—— —— —— —— —— —— ——|
|section header table| -----> section控制信息表
|—— —— —— —— —— —— ——|
|.strtab | -----> 字符串表
|—— —— —— —— —— —— ——|
|.symtab | -----> 符號表
|—— —— —— —— —— —— ——|
|..... |
—— —— —— —— —— —— —— —
.text放置代碼,.data放置已初始化的全局變量和靜態(tài)變量,.bss放置未初始化的全局變量和靜態(tài)變量。為什么代碼和全局變量、靜態(tài)變量要分開放?實際上,這就是個等同性問題。代碼段就是可讀的數(shù)據(jù),而全局變量、靜態(tài)變量是可讀可寫的數(shù)據(jù)。如果有多個進程進行同一份代碼,這些代碼都是等同的,不需要各自復制一份。而全局變量、靜態(tài)變量是不等同的,需要各自復制一份。而分什么又要分已初始化、未初始化呢?目標文件未初始化的全局、靜態(tài)變量只需要放置一個占位符,代表其在.bss。而.bss在鏈接階段,變量不占空間,在裝載時由操作系統(tǒng)再分配空間。可以看到,既然是文件格式,不管怎么設計,主要的目的就是占更少的空間。
header有很多文件控制信息,就不一一表述了,其中最重要的就是記錄了section header table的起始地址。而section header table記錄了所有section的名字、類型、長度、在文件中的偏移量(offset)等。如果想要尋址到任意section都要通過這個header table。section header table實際上是由struct構成的數(shù)組。
.strtab放置section名、變量名,包括符號名的字符串。由于在整個結構中,字符串的長度是不定的,一般將這些字符串統(tǒng)一放置在一個table中,然后存儲table中的offset,最后尋址到字符串。比如,在下表中,我想找到girlfriend一詞,我只要拿到.strtab的base地址,加上girlfriend的offset 9就可以找到這個字符串。
0 1 2 3 4 5 6 7 8
i 0 w a n t 0 a 0
g i r l f r i e n
d
.symtab就是大名鼎鼎的符號表。每個目標文件都有自己的符號表,符號表記錄符號的映射,符號可以這樣分:文件外符號和文件內(nèi)符號,文件外符號就是使用在其他文件定義的符號,文件內(nèi)符號除了在文件內(nèi)定義給其他文件使用的符號,還包括每個section符號,在文件內(nèi)定義光是文件內(nèi)使用的符號。光文件內(nèi)使用的符號,對鏈接沒有幫助,主要為了崩潰后分析而存在。符號表也是一個由struct構成的數(shù)組。ELF的32位符號sturct:
typedef struct {
int32_t st_name;
uint32_t st_value;
int32_t st_size;
unsigned char st_info;
unsigned char st_other;
uint16_t st_shndx;
} ELF32_Sym;
st_name字段就是符號的名字,表示為在.strtab中的字符串offset。st_info表示是局部符號、全局符號還是弱符號。符號也可以分為強符號(Strong Symbol)、弱符號(Weak Symbol),顧名思義,強符號有唯一性,弱符號沒有唯一性,一個強符號可以和多個弱符號共存,多個重復的強符號不可以共存,鏈接器會報出duplicate dymbol,可以用attribute((weak))指明弱符號。相對的,符號也有強引用(Strong Reference)、弱引用(Weak Reference),在鏈接進行符號修正的時候,強引用必須修正,而弱引用可以不修正,可以用attribute((weakref))指明符號弱引用。
st_shndx字段指明了符號是文件外符號,還是文件內(nèi)符號。如果是文件外符號就為SHN_UNDEF。如果是文件內(nèi)符號包括給其他文件使用的、光自己使用的、section符號,就為所在section的索引號,而st_value表示所在section的offset。等到鏈接過后,不管是文件外符號還是文件內(nèi)符號,st_value指明實際地址。
符號修飾(Symbol-Decoration)與函數(shù)簽名(Function-Signature)
機智的同學已經(jīng)發(fā)現(xiàn)了,如果光按上面聊的方式進行符號鏈接是有問題的,假如目標文件有個func符號又引用了其他文件同名的func符號,那符號不就出現(xiàn)沖突了?這里就需要引入函數(shù)簽名,函數(shù)簽名是一個函數(shù)的名字、參數(shù)類型、所在類名組成的字符串,不同語言、不同編譯器對同一個函數(shù)生成的函數(shù)簽名是不一樣的,比如OC中函數(shù)簽名還要加上返回變量類型,C++中還要加上NameSpace。在鏈接的時候,過程調(diào)用符號不光是函數(shù)名,是對函數(shù)簽名處理后的結果,全局變量符號也是經(jīng)過類似用函數(shù)簽名處理后的結果。這一處理過程就是符號修飾。
fishhook
fishhook是facebook開源的重綁定Mach-O符號的庫,最常用來hook C語言函數(shù),而且實際上只能重新綁定C符號,因為符號修飾這一步只去掉了”_”,相當于只針對C語言做了符號修飾。在了解了目標文件后,重綁定就不是那么困難了。最基本的思路就是先拿到header,然后通過header拿到section header table,再找到.hash,.hash是一個用于加快訪問.symtab的哈希結構,再索引到.symtab,詳見這里,通過name去.strtab比對符號名,如果匹配就置換value。
https://docs.oracle.com/cd/E2382401/html/819-0690/chapter6-48031.html
fishhook大體實現(xiàn)原理就是這樣,只不過對Mach-O平臺特性改進一下方案就行。在Mach-O中類似于section header table的段叫做load commands。并且Mach-O中使用二級命名空間,先分segment,就相當于上文中的section,然后再在同一segment中區(qū)分section。
先拿到header,通過header中的ncmds(segment的個數(shù))和cmdsize(segment的大小)字段就可以找到所有的segment。然后找到.strtab、.symtab、indirect symbol table。這個indirect symbol table是一個uint32_t的數(shù)組。它就是nl_symbol_ptr(non-lazy)和la_symbol_ptr(lazy )對應的.symtab struct數(shù)組的索引。nl_symbol_ptr和la_symbol_ptr section section中的reserved1字段指明對應的indirect symbol table起始offset。只要從這兩個section對應的indirect symbol table起始表項再跳到.symtab去匹配、置換就可以了。
下面是32位下.symtab的struct,可以看到和上段文章講的幾乎一致:
struct nlist {
union {
char *n_name; /* for use when in-core */
uint32_t n_strx; /* index into the string table */
} n_un;
uint8_t n_type; /* type flag, see below */
uint8_t n_sect; /* section number or NO_SECT */
int16_t n_desc; /* see <mach-o/stab.h> */
uint32_t n_value; /* value of this symbol (or stab offset) */
};
上文提到的Mach-O格式如下:
—— —— —— —— —— —— ——
|header |
|—— —— —— —— —— —— ——|
|load commands |
|—— —— —— —— —— —— ——|
|__Text |
|—— —— —— —— —— —— ——| —— __nl_symbol_ptr
|__Data | -----> |
|—— —— —— —— —— —— ——| —— __la_symbol_ptr
|other sections... |
|—— —— —— —— —— —— ——|
|.strtab |
|—— —— —— —— —— —— ——|
|.dynsym | -----> indirect symbol table
|—— —— —— —— —— —— ——|
|..... |
—— —— —— —— —— —— —— —
更加詳細的格式,推薦這篇文章。
http://turingh.github.io/2016/03/07/mach-o文件格式分析/
鏈接
上面聊了這么多 ,那靜態(tài)鏈接到底是如何將多個目標文件鏈接成一個可執(zhí)行文件的呢?
靜態(tài)鏈接分為兩階段(Two-pass Linking),第一階段先掃描所有目標文件,調(diào)整結構。將所有目標文件相同section合并,包括.symtab合并成全局.symtab,然后為每個section分配虛擬地址,再將全局.symtab中的符號進行置換成虛擬地址。
這里如何將全局.symtab中的符號置換成虛擬地址呢?實際上,在分配section虛擬地址后,符號的虛擬地址按所在section虛擬地址加offset就可以計算出了。
第二階段將所有符號進行修正。通過重定位表找到所有section中需要被修正的符號位置,然后從全局.symtab查詢出虛擬地址置換。
每個section都會對應一個重定位段,這些重定位段組成一個重定位表。每個重定位表項叫做重定位入口(Relocation Entry),它記錄了所需重定向符號所在段的offset。
靜態(tài)鏈接庫
靜態(tài)鏈接庫就是一組目標文件,經(jīng)過壓縮、索引而成的一個文件形式。當我們平時在使用靜態(tài)鏈接庫的時候,實際上鏈接器會根據(jù)所需的符號,在庫中搜索到相應的目標文件,并將其鏈接入最終可執(zhí)行文件。
動態(tài)鏈接
隨著靜態(tài)鏈接慢慢發(fā)展起來,靜態(tài)鏈接也暴露出了問題。靜態(tài)鏈接將鏈接與被鏈接的目標文件結合的太緊密了,導致如果多個目標文件要鏈接同一個目標文件,那這個被鏈接的目標文件相當于要被復制多份,每個可執(zhí)行文件都要包含這個被鏈接的目標文件的內(nèi)容,這樣會占太多冗余空間。那怎么辦?將鏈接與被鏈接的目標文件先隔離開,將鏈接的時機往后推移,等到裝載的時候再進行鏈接。這樣,讓被鏈接的目標文件只占一份空間就好。
既然動態(tài)鏈接隔離開了鏈接、被鏈接目標文件,鏈接目標文件需動態(tài)鏈接的符號,就需要先做個動態(tài)鏈接占位符。這也就是說,在目標文件鏈接成可執(zhí)行文件時,即使是用作動態(tài)鏈接的目標文件也要作為動態(tài)鏈接庫輸入到鏈接階段,以供目標文件識別哪些符號是動態(tài)符號。
動態(tài)鏈接重定位
上面已經(jīng)聊完了在鏈接階段對靜態(tài)鏈接進行重定位,根據(jù)符號所在section的虛擬地址和所在section的offset。而動態(tài)鏈接可以這樣重定位嗎?不行,這時動態(tài)鏈接庫的地址還沒有確定,必須等到裝載以后操作系統(tǒng)分配。那可以等到裝載以后,確定地址后再直接進行重定位嗎?不行,假如動態(tài)鏈接庫被多個進程引用,裝載時動態(tài)鏈接庫進行重定位,動態(tài)鏈接庫映射到每個進程中的虛擬地址都不一樣,動態(tài)鏈接庫只能對一個進程重定位,那么動態(tài)鏈接庫就不是共享的了。那怎么搞?
通過.got(global offset table),.got就是一個指針數(shù)組,.got存儲引用符號的實際地址。而代碼段引用符號直接更改為引用.got項的位移,這在鏈接階段以后就不會再改變了。然后將.got分配在.data section,裝載時每個進程復制一份并修正。實際上,動態(tài)鏈接重定位指的就是在裝載的時候,根據(jù)全局符號表修正.got表項。動態(tài)鏈接庫使用全局變量、靜態(tài)變量、引用文件外過程調(diào)用都要經(jīng)過.got。.got就像indirection table一樣,解決多進程共享動態(tài)鏈接庫。
這樣,動態(tài)鏈接庫雖然在不同進程中有不同的映射虛擬空間,但物理空間上共享。.got在不同進程中,虛擬空間和物理空間都不共享。如下圖所示:
virtual address -> physical address
—— —— —— —— —— —— ——
|processA |
|—— —— —— —— —— —— ——|
|..... |
|—— —— —— —— —— —— ——|
|dynamic libiraries |----------
|—— —— —— —— —— —— ——| |
|..... | | |..... |
|—— —— —— —— —— —— ——| | |—— —— —— —— —— —— ——|
|.got |---------|---------->|.got |
|—— —— —— —— —— —— ——| | |—— —— —— —— —— —— ——|
|..... | | |..... |
|—— —— —— —— —— —— ——| | |—— —— —— —— —— —— ——|
----------->|dynamic libiraries |
—— —— —— —— —— —— —— | |—— —— —— —— —— —— ——|
|processB | | |..... |
|—— —— —— —— —— —— ——| | |—— —— —— —— —— —— ——|
|..... | | ------>|.got |
|—— —— —— —— —— —— ——| | | |—— —— —— —— —— —— ——|
|dynamic libiraries |---------- | |..... |
|—— —— —— —— —— —— ——| |
|..... | |
|—— —— —— —— —— —— ——| |
|.got |---------------
|—— —— —— —— —— —— ——|
|..... |
|—— —— —— —— —— —— ——|
動態(tài)鏈接庫文件外符號重定位用.got就搞定了,那動態(tài)鏈接庫文件內(nèi)符號呢?靜態(tài)鏈接同樣是在鏈接階段重定位就搞定了。動態(tài)鏈接將絕對尋址指令更換成相對尋址指令,只要指令的offset不變,相對尋址指令就可根據(jù)當前地址和offset得到正確的地址,這樣文件內(nèi)符號根本不需要重定位了。基于以上兩點的處理,代碼段在鏈接后就不需要更改了,這樣的代碼段也叫做地址無關碼(PIC),也就是說代碼段和裝載后的地址無關。
延遲綁定(PLT)
由于要跳過.got引用動態(tài)鏈接庫的符號,動態(tài)鏈接庫比靜態(tài)鏈接庫慢5%左右,但相比于節(jié)省的大量空間還是很劃算的。除此之外,動態(tài)鏈接還會有其他的問題,裝載時需要進行重定位,會導致性能下降。不如,直接延遲綁定,等到過程調(diào)用符號運行時被用到再進行重定位。
整個過程強烈推薦這篇文章,要想理解動態(tài)鏈接重定位,沒有比追匯編更好的方法了。動態(tài)鏈接和延遲綁定整個過程都是由動態(tài)鏈接器幫我們完成的。當引用符號(callq)時,先jmpq去plt結構,使用了PLT,引用符號就要先jmpq去plt結構。如果沒找到相應的地址,然后再jmpq去.got.plt或.got中。再把符號相應.rela.plt表中的索引和.got.plt相應的表項,pushq入棧,rela.plt中有符號的類型和名字。再jmp到動態(tài)鏈接庫中(_dl_fixup),去全局符號表中找到符號相應的地址。再將地址reloc到.got.plt或.got相應表項。然后就完成了延遲綁定,下次引用同樣的符號就可以jmpq去plt結構找到地址。
http://sysfork.com/post/linux-dynamic-lib-lazy-load/
引用
程序員的自我修養(yǎng)—鏈接、裝載與庫關注「ImportNew」,看技術干貨