關於linux下的.a文件與 .so 文件


  連續幾天終於將一個又一個問題解決了,這里說其中一個問題

  描述問題:使用多線程pthread的時候,(我用的IDE,CODEBOLCKS)編譯后發現直接彈出窗口,程序還沒有被Build。。巴拉巴拉,然后陷入了這個循環。提示有一句pthead_create未定義。

  發現:pthread要用到動態鏈接庫(libpthread.a)才能使用。

  解決辦法:后來在setting->complies and link->link setting里面加入了系統中這個文件的地址。

  詳細查了一下,.a與.so的區別,其實就是靜態鏈接庫與動態鏈接庫。有一篇博文,很詳細,附上鏈接:http://blog.csdn.net/nieyinyin/article/details/6890557

  Linux下的.so是基於Linux下的動態鏈接,其功能和作用類似與windows下.dll文件。

  下面是關於.so的介紹:

一、引言

  通常情況下,對函數庫的鏈接是放在編譯時期(compile time)完成的。所有相關的對象文件(object file)與牽涉到的函數庫(library)被鏈接合成一個可執行文件(executable file)。程序在運行時,與函數庫再無瓜葛,因為所有需要的函數已拷貝到自己門下。所以這些函數庫被成為靜態庫(static libaray),通常文件名為“libxxx.a”的形式。


  其實,我們也可以把對一些庫函數的鏈接載入推遲到程序運行的時期(runtime)。這就是如雷貫耳的動態鏈接庫(dynamic link library)技術。

二、動態鏈接庫的特點與優勢

  首先讓我們來看一下,把庫函數推遲到程序運行時期載入的好處:

  1. 可以實現進程之間的資源共享。

  什么概念呢?就是說,某個程序的在運行中要調用某個動態鏈接庫函數的時候,操作系統首先會查看所有正在運行的程序,看在內存里是否已有此庫函數的拷 貝了。如果有,則讓其共享那一個拷貝;只有沒有才鏈接載入。這樣的模式雖然會帶來一些“動態鏈接”額外的開銷,卻大大的節省了系統的內存資源。C的標准庫 就是動態鏈接庫,也就是說系統中所有運行的程序共享着同一個C標准庫的代碼段。

  2. 將一些程序升級變得簡單。用戶只需要升級動態鏈接庫,而無需重新編譯鏈接其他原有的代碼就可以完成整個程序的升級。Windows 就是一個很好的例子。

  3. 甚至可以真正坐到鏈接載入完全由程序員在程序代碼中控制。

  程序員在編寫程序的時候,可以明確的指明什么時候或者什么情況下,鏈接載入哪個動態鏈接庫函數。你可以有一個相當大的軟件,但每次運行的時候,由於 不同的操作需求,只有一小部分程序被載入內存。所有的函數本着“有需求才調入”的原則,於是大大節省了系統資源。比如現在的軟件通常都能打開若干種不同類 型的文件,這些讀寫操作通常都用動態鏈接庫來實現。在一次運行當中,一般只有一種類型的文件將會被打開。所以直到程序知道文件的類型以后再載入相應的讀寫 函數,而不是一開始就將所有的讀寫函數都載入,然后才發覺在整個程序中根本沒有用到它們。

三、動態鏈接庫的創建

  由於動態鏈接庫函數的共享特性,它們不會被拷貝到可執行文件中。在編譯的時候,編譯器只會做一些函數名之類的檢查。在程序運行的時候,被調用的動態 鏈接庫函數被安置在內存的某個地方,所有調用它的程序將指向這個代碼段。因此,這些代碼必須實用相對地址,而不是絕對地址。在編譯的時候,我們需要告訴編 譯器,這些對象文件是用來做動態鏈接庫的,所以要用地址不無關代碼(Position Independent Code (PIC))。

  對gcc編譯器,只需添加上 -fPIC 標簽,如:

  gcc -fPIC -c file1.c
  gcc -fPIC -c file2.c
  gcc -shared libxxx.so file1.o file2.o

  注意到最后一行,-shared 標簽告訴編譯器這是要建立動態鏈接庫。這與靜態鏈接庫的建立很不一樣,后者用的是 ar 命令。也注意到,動態鏈接庫的名字形式為 “libxxx.so” 后綴名為 “.so”

四、動態鏈接庫的使用

a.隱式調用 (靜態庫與此相同的方式)

  使用動態鏈接庫,首先需要在編譯期間讓編譯器檢查一些語法與定義。

  這與靜態庫的實用基本一樣,用的是 -Lpath 和 -lxxx 標簽。如:

  gcc file1.o file2.o -Lpath -lxxx -o program.exe

  編譯器會先在path文件夾下搜索libxxx.so文件,如果沒有找到,繼續搜索libxxx.a(靜態庫)。

  在程序運行期間,也需要告訴系統去哪里找你的動態鏈接庫文件。在UNIX下是通過定義名為 LD_LIBRARY_PATH 的環境變量來實現的。只需將path賦值給此變量即可。csh 命令為:

  setenv LD_LIBRARY_PATH   your/full/path/to/dll

  一切安排妥當后,你可以用 ldd 命令檢查是否連接正常。

  ldd program.exe

動態鏈接庫*.so的編譯與使用

b.顯示調用:

  這種方式更加靈活。在代碼中需要調用的地方使用 #include <dlfcn.h>這個頭文件中的以下函數來調用:

 

void  *dlopen(const char *, int);
void  *dlsym(void *, const char *);
int    dlclose(void *);
char  *dlerror(void);

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM