你的同事給出的目標文件太多了,從 one.o two.o …… …… 一直到 xxx.o。
好的,你如果真正想用,你的同事提供的這些現有的目標文件,你得做三件事:
一,查看自己的源文件,看看用到了哪些函數;
二,明確這些函數來自于哪個目標文件,本例中,很容易,因為函數的名字和目標文件的名字是對應的,比如one.o就會提供一個名稱為one的函數;
三,使用 ld ,將你自己的目標文件和第二步中找到的那些目標文件鏈接起來,生成可執行文件。
第一步就是個很耗時的過程;
第二步其實也不簡單,因為,你根本不能假設,函數的名字和目標文件的名字是對應的,本文只是舉一個例子而已;
第三步嘛,也很麻煩,因為你要手動輸入這些目標文件的名字,萬一打錯字怎么辦?
所以,你的同事,將 one.o two.o …… …… 一直到 xxx.o 統一制作成一個文件,叫做 goodThings.a,這個 goodThings.a 就包含了所有的目標文件了。
你使用的時候,只需要這么做,假設你自己的目標文件叫做 main.o,
ld main.o goodThings.a -o go
簡潔明了!一步成功! ld 這個命令會自動在 goodThings.a 中去查找 main.o 使用的目標文件,并鏈接起來。
好,正式介紹 goodThings.a 這個新“人物”。
這個東西就是靜態庫。(關于靜態這個詞,后面再講)
說白了,就是目標文件的打包,放在一塊而已。
ar 這個命令可以用來制作靜態庫:
ar -r goodThings.a one.o two.o three.o ………… xxx.o
這樣就能把 one.o 一直到 xxx.o 放在 goodThings.a 里了。
你可以查看一個靜態庫文件里有哪些目標文件:
ar -t goodThings.a
不過,建議將靜態庫的名字叫成 libxxx.a 這樣的格式,這樣更符合命名規范,實際上是,這樣的命名規范是有好處的。因為可以這樣用:
ld main.o -L . -lxxx -o go
ld 會在本目錄下去找 libxxx.a。當然,這里假設,你把 libxxx.a 放在本目錄了。其中 -L . 就是說,在本目錄下去找的意思。
前面說到了裝載的概念,就是把程序從硬盤搬到內存去,從而開始執行。
可以簡單的說:
靜態:鏈接過程在裝載之前已經完成。
動態:等到裝載的時候再去找相應的庫文件,進而鏈接。
關于靜態,一勞永逸,所有的東西都在這里了,想什么時候執行就什么時候執行。
動態呢,不是這樣,執行的時候,去找我需要什么,再鏈接,再裝載。
討論一下動態的好處。
舉一個例子,看電視。
小明和小強都要看電視,于是他們一人背著一個電視,似乎,有點累。
小明說,把電視放到房間里吧,嗯,于是,他倆在一個房間里,打開兩個電視,都在看一個臺,似乎,有點浪費。
小明說,既然看一個臺,那關一臺,似乎,這樣很好。
假如小明和小強同時用到了 one.o ,那么可以推出一個結果,小明和小強的 可執行文件里,一定都包含這個 one.o。
第一,浪費硬盤空間;(兩份可執行文件都包含了 one.o )
第二,程序裝載時,浪費內存。(因為 one.o 被裝載了兩次)
動態庫,就可以解決以上兩個問題。
同樣的代碼,硬盤上應該可以只存在一份,內存中也應該只存在一份,以達到節省的效果。
這就是為什么,動態鏈接,是在程序被裝載的時候,才去鏈接。(因為早鏈接了,不就占硬盤空間了么)
這就是為什么,動態鏈接,可以節省內存。(因為相同的庫,我只鏈接一次,放在內存里,第二份可執行文件依然可以共享這個庫)
新聞熱點
疑難解答