有關Linux的.a、.so和.o文件

 .o.a.so文件都是Linux下的程序函數庫,即編譯好的可以供其他程序使用的代碼和數據。

優點:程序模塊化,容易重新編譯,方便升級。

分類:靜態函數庫(對應.a文件)、共享函數庫(對應.so文件,類似於Windowsdll文件)、動態加載函數庫(對應.o文件,相當於Windows裏的.obj文件)

靜態函數庫

特點:實際上是簡單的普通目標文件的集合,在程序執行前就加入到目標程序中。

優點:可以用以前某些程序兼容;描述簡單;允許程序員把程序link起來而不用重新編譯代碼,節省了重新編譯代碼的時間(該優勢目前已不明顯);開發者可以對源代碼保密;理論上使用ELF格式的靜態庫函數生成的代碼可以比使用共享或動態函數庫的程序運行速度快(大概1%-5%

生成:使用ar程序(archiver的縮寫)。ar rcs my_lib.a f1.o f2.o是把目標代碼f1.of2.o加入到my_lib.a這個函數庫文件中(如果my_lib.a不存在則創建)

使用:gcc生成可執行代碼時,使用-l參數指定要加入的庫函數。也可以用ld命令的-l-L參數。

共享函數庫

    共享函數庫在可執行程序啓動的時候加載,所有程序重新運行時都可自動加載共享函數庫中的函數。.so文件感覺很複雜,光是命名規則就已經看得我很暈了~整理一下,共享庫需要:sonamereal name,另外編譯的時候名字也有說法。依次解釋下:

soname必須的格式:lib+函數庫名+.so+版本號信息(但是記住,非常底層的C庫函數都不是以lib開頭命名的)。例子:/usr/lib/libreadline.so.3

real name:顧名思義是真正的名字啦,有主版本號和發行版本號。但是沒找到實例……

編譯器編譯的時候需要的函數庫的名字就是不包含版本號信息的soname,例如上面的例子把最後的.3去掉就可以了。

位置:共享函數庫文件必須放在特定目錄,對於開放源碼來說,GNU標準建議所有的函數庫文件都放在/usr/local/lib目錄下,而且建議命令、可執行程序都放在/usr/local/bin目錄下。不過這個只是習慣啦,可以改變,具體的位置信息可以看/etc/ld.so.conf裏面的配置信息。當然,也可以修改這個文件,加入自己的一些特殊的路徑要求。

創建:在網上找到了gcc方式和easyeclipse環境下兩種創建方式。

gcc方式:

    首先創建object文件,這個文件將加入通過gcc –fPIC 參數命令加入到共享函數庫裏面,標準格式:gcc -shared -Wl,-soname,your_soname -o library_name file_list library_list(說實話這個標準格式看起來好複雜,我找了個實例,但是好像和那個標準格式稍有不同:gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so

easyeclipse環境下生成.so文件:

        1.選擇新建工程,建立一個c++工程

        2.在工程類型選項裏選擇 Shared Library,然後填入工程名字PXXX點擊完成即可。

        3.編寫程序,然後編譯就會在debug或者release裏生成一個libPXXX.so文件,如果不要lib的起頭標記點擊project菜單的Properties選項,然後在彈出的界面的右邊點擊Build artifact頁面,將Output prefix選項的內容清空即可。

        4.如果是C++程序,注意在接口函數的前面加上extern "C"標記,在頭文件加上如下標記:

#ifdef   __cplusplus  

#extern   "C"{  

#endif  

   

頭文件主體  

   

#ifdef   __cplusplus  

}  

#endif  

     如果不加以上標記,經過編譯後,so裏的函數名並非你編寫程序時設定的函數名,在開發環境左側的工程文件列表中點開debug項裏的PXXX.o可以看到so文件裏的函數名都是在你設定的函數名後面加了一個__Fi標記,比如你用的設定的函數名稱是Func(), so裏的函數名則爲Func__Fi()或者其他的名稱。

安裝:拷貝共享庫文件到指定的標準的目錄,然後運行ldconfig。如果沒有權限這樣做,那麼就只好通過修改環境變量來實現這些函數庫的使用了。方法不再說了,很複雜。

查看:可以通過運行ldd來看某個程序使用的共享函數庫。例如ldd /bin/ls。查看.so文件使用nm命令,如nm libXXX.so。(注意,nm對於靜態的函數庫和共享的函數庫都起作用)

關於覆蓋:如果想用自己的函數覆蓋某個庫中的一些函數,同時保留該庫中其他的函數的話,可以在/etc/ld.so.preload中加入要替換的庫(.o結尾的文件),這些preloading的庫函數將有優先加載的權利。

關於更新:每次新增加動態加載的函數庫、刪除某個函數庫或者修改某個函數庫的路徑時,都要重新運行ldconfig來更新/etc/ld.so.cache

發佈了7 篇原創文章 · 獲贊 0 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章