關於linux下的庫檔案

來源:互聯網
上載者:User

先說說庫檔案是怎麼來的吧。

以C為例,我們寫一個程式,一般都不會把所有的函數都寫在一個檔案裡面,通常都是劃分模組,然後一個模組若干個檔案,然後在main檔案裡面調用這些模組。我這裡用一個magic.c檔案代替實際程式中的所有的檔案,你就當這個magic.c檔案非常神奇,你調用裡面的magic()函數後,它會自動按你的想法把剩下的工作都完成。下面是兩個檔案:

mian.c

int main(){  magic();}

magic.c:

#include <stdio.h>void magic(){  printf("This is a magic function\n");}

main.c檔案裡面沒有包括任何標頭檔,因為我們的編譯是手動按步驟的,實際編碼不推薦這樣做,這裡可以更加清楚的知道標頭檔的作用。

一般從C源檔案到可執行代碼要經過以下4個步驟:先行編譯(preprocess  gcc -E,產生.i檔案),編譯(compile gcc -S,產生.s檔案),彙編(assemble  gcc -c,產生.o檔案),連結(link  產生可執行檔)。這裡只討論最後兩個步驟,彙編和連結。

彙編後的結果是每個源檔案都有了對應的二進位代碼;連結是把所有的二進位代碼打包成一個檔案,最後得到可執行檔。

使用這個命令彙編main.c:gcc -Wall -c main.c 

-Wall 是列出警告的開關,如果沒有這個開關,彙編成功,什麼提示都沒有,如果開啟這個開關,會得到如下一個警告:

main.c:2:3: warning: implicit declaration of function ‘magic’ [-Wimplicit-function-declaration]

要消除這個警告很容易,有兩個辦法:

1)前面加個聲明就好了,void magic();  

2)寫個magic.h的標頭檔:

void magic();

然後在main.c裡麵包含進來:#include "magic.h"。

這兩種辦法的作用是告訴main,現在沒有magic的實現不要緊,我確定一定以及肯定這個magic函數是存在的,放心使用就好了,而且告訴了main這個magic該怎麼用,參數是什麼,傳回值是什麼。

但是沒有magic的聲明也沒有問題,只是警告,不是錯誤,因為我們知道我們的magic是怎麼定義的,而且我們也確定會在後面連結magic函數。

但是問題就出在這裡了,比如我們寫了一個超級牛逼的函數想讓別人使用,但是這個超級牛逼的函數要下個禮拜才能給別人怎麼辦呢?我們可以先給個標頭檔,然後拍著胸脯說你就按照我這個函式宣告寫,只要你的調用(call)沒問題,程式啟動並執行結果就沒問題。

一個禮拜後到了可以給別人我們的超級牛逼函數的時候了,這時候我們也有兩種選擇可以選。

第一,發源檔案,這個沒話說了,很棒,互相學習進步,讓別人自己把源檔案彙編成二進位代碼,然後再和他的main代碼連結成可執行代碼就好了。

第二,如果涉及商業或者著作權因素,那麼我們就只能自己把彙編後的二進位代碼給別人,然後讓別人再去連結。這裡又體現了標頭檔的好處,只需要知道函數怎麼調用就可以了,不用去知道函數內部怎麼寫的。比如剛開始學C只需要知道怎麼使用 fopen, fclose, fprintf, fscanf 等等就好了,等以後慢慢深入再去探個究竟。

好了,那麼庫檔案究竟是什麼呢?其實就是彙編後的二進位代碼,是別人寫好的超級牛逼的代碼彙編以後放在那裡讓我們使用的。但是這個彙編後的二進位代碼和我們自己產生的還有些不同,具體來說有兩種。

庫檔案本身分為兩種:靜態庫檔案(static library)和動態庫檔案(dynamic library),linux下,靜態庫檔案以.a結尾(archive),動態庫檔案以.so結尾(shared object)。

靜態庫檔案其實就是彙編後的二進位代碼的一個壓縮檔(archive),裡面可以有一個或者N個.o檔案。比如上面的magic.c,可以這樣產生靜態庫檔案:

首先彙編:gcc -c magic.c ,產生magic.o,然後使用壓縮檔命令(ar)產生靜態庫檔案:ar rc libmagic.a magic.o ,其中rc是壓縮選項,libmagic.a是給靜態庫檔案起的名字,magic.o 就是用來產生靜態庫檔案的二進位檔案,當然後面可以接很多個.o檔案,把他們壓縮成一個靜態庫檔案給別人使用。

libmagic.a 弄好以後就可以和main的二進位檔案連結在一起了: gcc -o main main.o -lmagic -L.

-o main 選項是把產生的可執行檔命名為main,沒有的話預設名字是a.out,-lmagic表示使用庫檔案libmagic.so(後面介紹)或者libmagic.a,如果都存在的話使用.so檔案。現在還沒有libmagic.so檔案,所以連結了libmagic.a裡面的magic函數。

動態庫檔案有些不同,直接使用gcc產生,首先還是彙編:gcc -fPIC -c magic.c ,因為彙編後的二進位代碼要拿去做動態庫,所以多了一個-fPIC選項,用來確定庫中函數的連結位置。然後從二進位檔案產生動態庫檔案:gcc -shared -o libmagic.so magic.o。後面可以接很多.o檔案。

動態庫的連結的命令和靜態庫一樣,但是做的事情不一樣。連結靜態庫檔案是把庫裡面的函數複製了到了可執行檔裡面,所以可執行檔產生以後有沒有靜態庫檔案就不重要了。而動態連結只是在可執行檔裡面記錄了那個函數需要使用的動態庫檔案,真正的連結是在運行(run)的時候,只有運行我們產生的可執行檔,到了要使用動態庫檔案裡面函數的時候,那個函數才會被載入到記憶體中再執行。所以涉及到了作業系統尋找動態連結程式庫的路徑問題。可以使用ldd程式查看我們的程式都用到了哪些動態庫檔案: ldd main,輸出如下:

linux-vdso.so.1 =>  (0x00007fff8c9dd000)

libmagic.so => not found

libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb0f846c000)

/lib64/ld-linux-x86-64.so.2 (0x00007fb0f8829000)

可以看到libmagic.so沒有找到,所以如果運行main也會報錯:./main: error while loading shared libraries: libmagic.so: cannot open shared object file: No such file or directory   。要讓系統找到動態庫檔案就必須設定動態庫檔案的路徑了(不同於可執行檔路徑PATH,標頭檔路徑INCLUDE 哦),如果要在動態庫檔案的搜尋路徑裡面加上當前路徑,可以如下設定:

LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.       /* 當前路徑是. */

export LD_LIBRARY_PATH

設定好路徑以後動態庫檔案就能被找到了,再運行ldd main,輸出下面的結果:

linux-vdso.so.1 =>  (0x00007fffb55ff000)

libmagic.so (0x00007ff515fa7000)

libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff515bec000)

/lib64/ld-linux-x86-64.so.2 (0x00007ff5161ab000)

關於連結再多說一句吧,gcc的連結是調用了另一個程式:ld。可以自己手動調用ld或者寫在Makefile裡面,不過一般不用那麼麻煩,用gcc就好了。

由於連結方法不用,所以連結靜態庫檔案後的可執行檔一般都比較大,比如上面的例子,連結靜態庫檔案後的main大小是8498個位元組,而連結動態庫檔案後的main的大小是8401位元組。好像檔案大小沒少多少,那是因為我們的magic函數小,大一點區別就很明顯了。

謝謝觀賞,歡迎點評。

參考文獻:

The art of debugging with gdb,ddd, and eclipse. Norman Matloff and Peter Jay Salzman. 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.