装入归档文件时出现了一个错误linux_静态链接与动态链接(Linux)
前言
上一篇分享了靜態(tài)鏈接與動態(tài)鏈接的實驗(Windows下)。這一篇分享Linux下的筆記,同時對上一篇筆記做一個補(bǔ)充。
首先,我們把靜態(tài)鏈接與動態(tài)鏈接做一個這樣子的比喻:
把鏈接過程看做我們平時學(xué)習(xí)時做筆記的過程。我們平時學(xué)習(xí)時準(zhǔn)備一本筆記本專門記錄我們的學(xué)習(xí)筆記,比如在某本書的某一頁上看到一個很好很有用的知識,這時候我們有兩種方法記錄在我們的筆記本上,一種是直接把那一頁的內(nèi)容全部抄寫一遍到筆記本上(靜態(tài)鏈接);另一種是我們在筆記本上做個簡單的記錄(動態(tài)鏈接),比如寫上:xxx知識點在《xxx》的xxx頁。
從這兩種方法中我們可以很清楚地知道兩種方式的特點,第一種方式的優(yōu)點就是我們在復(fù)習(xí)的時候就很方便,不用翻閱其它書籍了,但是缺點也很明顯,就是占用筆記本的空間很多,這種方法很快就把我們的筆記本給寫滿了。第二種方式的優(yōu)點就是很省空間,缺點就是每當(dāng)我們復(fù)習(xí)的時候,手頭上必須備著相關(guān)的參考書籍,比如我們?nèi)ソ淌覐?fù)習(xí)的時候,就得背著一大摞書去復(fù)習(xí),這樣我們復(fù)習(xí)的效率可能就沒有那么高了。
這對應(yīng)到我們的動態(tài)鏈接與靜態(tài)鏈接上是不是就很好理解了:
靜態(tài)鏈接與動態(tài)鏈接的主要優(yōu)缺點
(1)靜態(tài)鏈接的優(yōu)缺點:
優(yōu)點:
- 代碼裝載速度快,執(zhí)行速度略比動態(tài)鏈接庫快;
缺點:
- 使用靜態(tài)鏈接生成的可執(zhí)行文件體積較大,包含相同的公共代碼,造成浪費。
(2)動態(tài)鏈接的優(yōu)缺點:
優(yōu)點:
- 生成的可執(zhí)行文件較靜態(tài)鏈接生成的可執(zhí)行文件小;
缺點:
- 速度比靜態(tài)鏈接慢;
動態(tài)、靜態(tài)鏈接實驗
我們先編寫如下代碼(共三個文件):
文件1(main.c):
#include "test.h"?void print_hello(void){ printf("hello world");}文件2(test.c):
#ifndef __TEST_H#define __TEST_H?#include ?void print_hello(void);?#endif文件3(test.h):
#ifndef __TEST_H#define __TEST_H#include void print_hello(void);#endif1、動態(tài)鏈接實驗
首先,將源文件生成目標(biāo)文件(*.o),命令:
gcc -c -fPIC main.c test.c這里得根據(jù)實際編譯環(huán)境加上或者不加上-fPIC參數(shù),這個是與gcc的版本有關(guān),像我這邊的gcc 5.4.0就得顯示加上-fPIC這個參數(shù),若是不加,則會影響下一步的鏈接過程。
在Linux中,動態(tài)庫的擴(kuò)展名一般為.so。針對上面生成的test.o文件,生成動態(tài)庫的命令為:
gcc -shared test.o -o libtest_d.so若是上一步不加-fPIC參數(shù),則會產(chǎn)生如下錯誤:
大概意思就是.rodata不可以拿來制作共享文件,請加上-fPIC參數(shù)重新編譯。問題分析:
-fPIC 作用于編譯階段,告訴編譯器產(chǎn)生與位置無關(guān)代碼(Position-Independent Code),則產(chǎn)生的代碼中,沒有絕對地址,全部使用相對地址,故而代碼可以被加載器加載到內(nèi)存的任意位置,都可以正確的執(zhí)行。這正是共享庫所要求的,共享庫被加載時,在內(nèi)存的位置不是固定的。
從gcc來看,shared應(yīng)該是包含fPIC選項的,但似乎不是所有的版本都支持,所以最好顯式加上fPIC選項。
使用鏈接動態(tài)庫的方式生成可執(zhí)行程序,命令:
gcc main.o -L. -ltest_d -o test_d.out這里的-L.的含義是在搜索庫文件時包含當(dāng)前目錄,-ltest_d的含義是鏈接名稱為libtest_d.so的動態(tài)鏈接庫。
下面運行test_d.out程序,發(fā)現(xiàn)出現(xiàn)如下錯誤:
不能找到共享庫文件libtest_d.so,加載失敗。因為一般情況下Linux會在/usr/lib路徑中搜索需要用到的庫,而libtest_d.so庫并不在這個路徑下。解決方法有兩種:一種就是把這個文件拷貝至/usr/lib路徑下,但是一般不允許這樣做,一般用戶也不允許往這個路徑里拷貝東西。另一種就是把當(dāng)前路徑增加為動態(tài)庫的搜索路徑,命令為:
export LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH這時候就可以正常運行了:
2、靜態(tài)鏈接實驗
靜態(tài)庫用ar工具來制作。ar是一個歸檔工具,用于建立、修改、提取歸檔文件(archive)。一個歸檔文件可以包含多個目標(biāo)文件,也被稱為靜態(tài)庫。在Linux下,靜態(tài)庫的擴(kuò)展名一般為.a。
把目標(biāo)文件test.o做成靜態(tài)庫,命令:
ar -rv libtest_s.a test.o其中rv參數(shù)為組合參數(shù),其中r參數(shù)表示當(dāng)建立的模塊名已經(jīng)存在時,則覆蓋同名模塊,v參數(shù)用來顯示附加信息,比如被處理的文件的名字。
使用鏈接靜態(tài)庫的方法生成可執(zhí)行程序,命令:
gcc main.o -L. -ltest_s -o test_s.out運行程序:
刪除靜態(tài)庫之后,可執(zhí)行程序也是能正常運行的。事實上,使用鏈接靜態(tài)庫的方式生成的可執(zhí)行程序與直接使用目標(biāo)文件生成的可執(zhí)行程序沒有區(qū)別。只是經(jīng)過了靜態(tài)庫的鏈接,變?yōu)榱艘粋€文件,方便于調(diào)用、移植和保存。
歸檔工具ar可以很方便地查看和刪除歸檔文件中的成員。
查看靜態(tài)庫libtest_s.a中的內(nèi)容,命令:
關(guān)于ar工具更多的命令參數(shù)可輸入ar --help進(jìn)行查看:
以上就是關(guān)于靜態(tài)鏈接與動態(tài)鏈接的Linux筆記,如有錯誤,歡迎指出!
總結(jié)
以上是生活随笔為你收集整理的装入归档文件时出现了一个错误linux_静态链接与动态链接(Linux)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: assign深拷贝_Object.ass
- 下一篇: linux网络配置_linux复制和网络