裝載、連結與庫總結
1.靜態連結是在生成可執行程式的時候就把庫中的內容加入到程式中。
載入時動態連結是在將功能模組讀入記憶體時把動態庫中呼叫到的相關模組的內容載入記憶體。
執行時動態連結是在執行程式呼叫到模組內容時再將動態庫中的相應模組載入到記憶體。
2、編譯生成的目標檔案是未經連結的中間檔案,從結構上講是可執行檔案,只是沒有經過連結,有些地址和符號沒有調整
是按照可執行檔案格式儲存,與真正的可執行檔案結構不同,可執行檔案覆蓋程式編譯、連結、裝載、執行各個方面
3、ELF:可執行檔案格式,在電腦科學中,是一種用於二進位制檔案、可執行檔案、目的碼、共享庫和核心轉儲格式檔案。
是UNIX系統實驗室(USL)作為應用程式二進位制介面(Application Binary Interface,ABI)而開發和釋出的,也是Linux的主要可執行檔案格式。
1999年,被86open專案選為x86架構上的類Unix作業系統的二進位制檔案標準格式,用來取代COFF。因其可擴充套件性與靈活性,也可應用在其它處理器、計算機系統架構的作業系統上。
4.java編譯:java原始碼(符合語言規範)-->javac-->.class(二進位制檔案)-->jvm-->機器語言(不同平臺不同種類)
如何讓java的語法規則適應java虛擬機器的語法規則?這個任務由javac編譯器來完成java語言規範轉換成java虛擬機器語言規範。
5連結的介面——符號
在連結中,將函式和變數稱為符號,函式名和變數名稱為符號名
C++符號名稱經過修飾防止重名,函式經過簽名用來識別不同的函式
6、中介軟體:介於作業系統和應用程式之間的產品,中介軟體簡單解釋
你可以理解為面向資訊系統互動,整合過程中的通用部分的集合,遮蔽了底層的通訊,互動,連線等複雜又通用化的功能,以產品的形式提供出來,系統在互動時,直接採用中介軟體進行連線和互動即可,避免了大量的程式碼開發和人工成本。其實,理論上來講,中介軟體所提供的功能通過程式碼編寫都可以實現,只不過開發的週期和需要考慮的問題太多,逐漸的,這些部分,以中介軟體產品的形式進行了替代
7、靜態連結把目標檔案的相似段合併,連結器為目標檔案分配地址和空間(只關注於虛擬地址空間的分配)
8、不同編譯器編譯結果怎麼連結到一起?
目標檔案是同樣是檔案格式、同樣的符號修飾標準、變數記憶體分佈相同、函式呼叫方式相同等等,這些跟可執行程式碼二進位制相關的內容稱為ABI(聯結器從連結庫中查詢)
ABI(Application Binary Interface): 應用程式二進位制介面 描述了應用程式和作業系統之間,一個應用和它的庫之間,或者應用的組成部分之間的低介面。
API(Application Programming Interface,應用程式程式設計介面)是一些預先定義的函式,目的是提供應用程式與開發人員基於某軟體或硬體得以訪問一組例程的能力,而又無需訪問原始碼,或理解內部工作機制的細節。定義了原始碼和庫之間的介面,是作業系統提供的,API 介面屬於一種作業系統或程式介面。API 是一套協議,規定了我們與外界的溝通方式:如何傳送請求和接收響應。
9、BFD庫Binary File Discriptor Library:通過一個統一的介面處理不同的目標檔案格式。BFD把目標檔案抽象成一個統一的模型。現在GCC(編譯器)、連結器Id、偵錯程式等都是通過BFD庫處理目標檔案
10、使用ID連結指令碼
11、PE是COFF檔案的一種擴充套件,在window平臺
12、映像:PE檔案在裝載時直接對映到程序的虛擬空間中執行,它是程序的虛擬空間的映像,所以PE檔案也常被叫做映像檔案
13、裝載:將程式執行所需要的指令和資料全都裝入記憶體,這是簡單的靜態裝入。將常用的部分留在記憶體,不常用的放在磁碟,這是動態裝入
覆蓋裝載和頁對映是兩種常見的動態裝載。都是用到程式的區域性性原則,用到的模組裝入記憶體,暫時不用的存放磁碟
覆蓋裝載:把一些不會相互呼叫的模組用公用記憶體,使用時覆蓋管理器覆蓋其他的
頁對映:把一些用到的模組對映到記憶體中,用不到的裝載管理器放棄。裝載管理器使用一定演算法(如先進先出法)。這個裝載管理器就是現代作業系統
精確叫作業系統儲存管理器。現在主流的作業系統就是使用這種方式裝載可執行檔案。window的PE檔案和linux的ELF檔案都是這種方法裝載檔案
14、MMU:是Memory Management Unit的縮寫,中文名是記憶體管理單元,它是中央處理器(CPU)中用來管理虛擬儲存器、物理儲存器的控制線路,同時也負責虛擬地址對映為實體地址,以及提供硬體機制的記憶體訪問授權,多使用者多程序作業系統。
15、程序的建立:建立一個程序,裝載相應的可執行檔案並且執行。
(1)建立獨立的虛擬地址空間。實際上是建立對映函式所需要資料結構或者是頁目錄
(2)讀取可執行檔案頭,並且建立虛擬空間與可執行檔案的對映關係。就是裝載的過程,裝載是一個虛擬空間對映過程,所以可執行檔案也叫映像檔案
(3)將CPU的指令暫存器設定為可執行檔案的入口地址,啟動執行。暫存器把控制權交給程序
16、ELF裝載時把相同許可權的合併一起對映,這樣減少對映頁節省記憶體
17、作業系統通過給程序空間劃分一個個VMA(虛擬地址空間)來管理程序的虛擬空間:基本原則是將相同許可權屬性、有相同映像檔案的對映成一個VMA
如:程式碼VMA,資料VMA,堆VMA,棧VMA
18、動態連結的思想是把程式按照模組拆分成各個獨立的部分,在程式執行時才把他們連結成一個單獨的可執行檔案
19、動態連結和靜態連結:
靜態連線庫就是把(lib)檔案中用到的函式程式碼直接連結進目標程式,程式執行的時候不再需要其它的庫檔案;動態連結就是把呼叫的函式所在檔案模組(DLL)和呼叫函式在檔案中的位置等資訊連結進目標程式,程式執行的時候再從DLL中尋找相應函式程式碼,因此需要相應DLL檔案的支援。靜態連結庫和動態連結庫的另外一個區別在於靜態連結庫中不能再包含其他的動態連結庫或者靜態庫,而在動態連結庫中還可以再包含其他的動態或靜態連結庫。
關於模組:
在靜態連結中,整個程式只有一個可執行檔案是一個不可分割的整體,在動態連結中,把程式即可執行檔案和程式所依賴的共享物件看成程式的一個模組。共享物件的最終裝載地址在編譯時不確定,而是裝載的時候動態的分配的
20、裝載重定位:
為了使共享物件在任意地址裝載,想到靜態連結中的重定位。思路是在連結中對所有絕對地址引用不做重定位,而在裝載時才完成。一旦模組地址確定,即目標地址確定,則系統對程式中所有的絕對地址引用重定位
21、裝載重定位解決動態模組絕對地址引用的方法,但是指令無法在多個執行緒共享,希望把共享指令在裝載時不需要因為裝載地址改變而改變,思路就是把指令中需要被修改的部分分離出來跟資料部分放一起,這樣指令部分不變,資料部分可以在每個執行緒擁有一個副本。稱為地址無關程式碼技術
產生地址無關程式碼並不麻煩,我們把共享物件模組地址引用按照是否跨模組分為模組內部引用和模組外部引用,按照引用方法分為指令引用和資料訪問。模組內部呼叫或者資料訪問都是相對定址。模組間訪問因為地址相關的部分放到資料段裡面,資料段建立一個指向這些變數的指標陣列
22、延遲繫結:動態連結下模組間在程式執行前花費很多事時間用於函式符號的引用以及重定位,延遲繫結是函式第一次呼叫的時候才載入
23、在動態連結下,作業系統會先啟動動態連結器。linux動態連結器是一個共享物件,作業系統通過對映方式載入到程序地址空間,載入完動態連結器後把控制權交到連結器入口。
24、動態連結器的步驟與實現::啟動本身-裝載共享物件-重定位與初始化
(1)動態連結器自舉:
自舉:計算機必須具備自舉能力將自己所有的元件啟用,以便能完成載入作業系統這一目的,然後再由作業系統承擔起那些單靠自舉程式碼無法完成的更復雜的任務。
動態連結器的自舉必須滿足本身不依賴其他物件,並且本身變數重定位由它自己完成。前一個條件可以在編寫時不適用任何系統庫和執行庫,第二條件不用到自身變數。
(2)共享物件裝載:
完成自舉後,將可執行檔案和本身符號合併到一個符號表中,稱為全域性符號表,然後開始尋找可執行檔案所以來共享物件。連結器把共享物件裝載一個集合中,依次載入,然後把程式碼和資料對映到程序中,其中所依賴的共享物件也載入
(3)重定位初始化:
重定位後要是共享物件有init段則執行,完成初始化
25、顯示執行時連結:動態連結旺旺支援更加靈活的模組載入方式,叫顯示執行時連結,也叫執行時載入。也就是程式執行時載入模組,不用時解除安裝。
動態裝載庫:不需進行修改就可以執行裝載的共享物件。比如一些外掛、驅動
26、linux在執行可執行檔案時會啟動動態連結器,會查詢共享庫系統共享庫
環境變數:linux有改變動態連結器裝載共享路徑的方法。LD_LIVRARY_PATH:環境變數,程序啟動時動態連結器查詢共享庫時會先載入環境變數指定路徑。
WINDOW應用
27、window下動態連結庫DDL(Dynamic Link Library),相當於linux共享物件。DDL更加強調模組化,使各個模組更加鬆散的組合、重用和升級。所以window很多通過升級DDL形式自我完善,升級到一定程度我們稱為軟體更新包。早期的window程序沒有獨立空間,都可以呼叫DDL,這種沒有許可權的訪問容易使DDL資料損壞
28、基地址和相對地址:PE檔案被裝載時,其程序地址空間的起始地址就是基地址,它是優先被裝載的,相對地址是相對於基地址的偏移
window提供API實現程序間通訊,其中就有通過DLL實現。每個DLL在各個程序是獨立的,都擁有自己副本,但是window可以把一些共享的DLL資料分離出來,設定為共享的,這樣一個DLL有兩個資料段,一個共享一個私有的
29、匯出表:在DLL中,動態連結所需要的符號集中放在匯出表的結構中,提供了一個符號名和符號地址的對映關係,通過符號查詢相應的地址。匯入函式繫結,匯入函式會在匯入表中,下次不需要重新匯入解析,這個是DLL優化
以前可能會用序號作為查詢手段,但是修改,增加、刪除都會改變,現在不用了
30、棧:經典電腦科學中,棧是一個特殊容器,存函式和區域性變數等,資料入棧和出棧,先入後出原理。棧是向下增長,棧頂由esp暫存器定位,棧底固定。window預設棧空間1M
棧幀:棧儲存函式呼叫所需要的維護資訊稱為堆疊幀或活動記錄。包括函式返回地址和引數、臨時變數、儲存的上下文。
幀指標:一個函式活動記錄由ebp和esp兩個暫存器指定範圍,esp指向棧頂端,也是活動頂端,ebp指向活動記錄的一個固定位置,esp暫存器也稱為幀指標。ebp是固定的位置,定位函式活動記錄中的資料,把ebp壓入棧中為了函式返回恢復以前的ebp的值。
呼叫慣例:函式引數的呼叫按照一定的約定叫做呼叫慣例。引數傳遞通常是棧傳遞,有些呼叫慣例還使用暫存器傳遞。
31、堆:管理堆空間的通常是程式的執行庫。執行庫向作業系統批發較大堆空間,然後零售給程式。通過批發防止多次頻繁操作影響程式效能。
linux通常申請虛擬對映空間,稱為匿名空間,用來作為堆空間。linux堆空間是連續的,window不是,window通過空間連結串列連結在一起
window型別linux申請虛擬對映空間,只是未必用於堆記憶體,申請空間必須為頁的整數倍,window中有堆管理器管理
32、庫:
作業系統層面,檔案操作在linux中稱為檔案描述符,window稱為控制代碼
執行時庫:任何一個程式都需要龐大的程式碼來支撐,它包含入口函式和所依賴函式集合,這樣的程式碼集合稱為執行時庫。glibc是C執行時庫,glibc是早期分散的。MSVC的CRT是後期的分為動態連結和靜態連結版本的,支援與否多執行緒版本,以及是否只支援C不支援C++,window也能用
33、TLS:執行緒區域性儲存:執行緒想要使執行緒獨享,用到執行緒區域性儲存。用法是要定義一個全域性變數為TLS型別,只要在定義前加上相應關鍵字。
window TLS會放在.data或.bss段
在window執行緒會建立一個關於執行緒資訊的結構,叫做執行緒環境塊,儲存堆疊地址和執行緒ID等資訊
window建立執行緒有兩種方法:window API和MSVC CRT
34、系統呼叫:應用程式(執行庫也是應用程式一部分)與作業系統核心之間的介面。window基於DLL機制,通過DLL堆系統呼叫進行包裝,形成所謂windowAPI。這樣應用程式與作業系統之間多一層,應用程式通過windowAPI呼叫
35特權級與中斷:
特權級:現代CPU在截然不同特權級下命令分為使用者模式和核心模式:也稱為使用者臺和核心態,作業系統可以讓不同的程式碼執行在不同的模式下限制他們全力,提高穩定和安全性
中斷:中斷是指計算機執行過程中,出現某些意外情況需主機干預時,機器能自動停止正在執行的程式並轉入處理新情況的程式,處理完畢後又返回原被暫停的程式繼續執行。每個作業系統都會提供中斷的介面
系統呼叫執行在核心態的,而應用程式基本執行在使用者態,系統通過中斷從使用者態切換到核心態。
每一箇中斷對應一箇中斷號,稱為中斷處理程式。在核心中有一箇中斷向量表對應中斷處理程式指標。
36、windowAPI:
windowAPI是window作業系統提供給應用程式開發者最底層、最直接與window打交道的介面。CRT是建立在windowAPI之上的。windowAPI是以DLL匯出函式的形式暴露給應用程式開發者,微軟把這些函式的檔案頭、匯出庫、相關檔案和工具一起提供給開發者稱為SDK(Software Development Kit)
////////////////////////////////////////////////////深入理解java虛擬機器///////////////////////////////////////////////////////
1.虛擬機器:
概論:計算機系統的這種抽象類似於面向物件程式設計(OOP)中的針對介面程式設計泛型(或者是依賴倒轉原則),通過一層抽象提取底層實現中共性的部分,底層實現這個抽象並完成自己個性的部分。也就是說通過一個抽象層次來隔離底層的不同實現。虛擬機器規範定義了這個虛擬機器要完成的功能(也就是介面),底層的作業系統和硬體利用自己提供的功能來實現虛擬機器需要完成的功能(實現)。通過執行在虛擬機器之上,Java才具有很好跨平臺特性。
定義:當Java虛擬機器由主機作業系統上的軟體實現時,Java程式通過呼叫本地方法和主機進行互動。Java方法由Java語言編寫,編譯成位元組碼,儲存在class檔案中。本地方法由C/C++/組合語言編寫,編譯成和處理器相關的機器程式碼,儲存在動態連結庫中,格式是各個平臺專有。所以本地方法是聯絡Java程式和底層主機作業系統的連線方式。
java 命令開始>>>>尋找 配置檔案 定位需要的 .dll>>>>.ddl 初始化 JVM 虛擬機器>>>>獲得 native 介面>>>>找到main 方法執行
JVM的DLL是JVM的主要實現