linux程序設計第四版
庫:預先編譯好的方法/函數的集合
.c文件編譯成.o文件,再將.o文件的方法放入庫文件
存放庫文件的標準路徑 /usr/lib 用戶安裝的 /lib 系統本身的
所有的頭文件.h存放在 usr/include
命令在 /usr/bin /bin
比如:
list.h 聲明
list.c 實現 編譯生成 list.o 鏈接到main裏面 每個人使用都要list.c文件編譯 如果多次就會重複多次
靜態庫命名規則 : libmylist.a 共享庫:liblist.so
.查看程序使用了哪些共享庫 ldd main(main爲程序名字)
使用庫的意義
省去了每一次編譯的過程,提高了程序生成的速度,避免重複做無用的事情
隱藏我們自己代碼的實現,對代碼形成一種保護
靜態庫
靜態庫的創建與使用
add.c
#include "my.h"
int add(int x,int y)
{
return x+y;
}
max.c
#include "my.h"
int max(int x ,int y)
{
return x>y ? x:y;
}
my.h
int max(int x,int y);
int add(int x,int y);
main.c
#include<stdio.h>
#include<stdlib.h>
#include"my.h"
int main()
{
int a = 3;
int b = 2;
printf("add=%d\n",add(a,b));
printf("max=%d\n",max(a,b));
exit(0);
}
libxx.a lib爲前綴 .a爲擴展名
1.所有.c文件編譯成.o文件
2.打包做出庫,ar crv libxx.a *.o
ar是建立或修改備存文件的命令,參數c表示建立備存文件,r表示插入備存文件,v表示顯示執行過程。
共享庫 libxx.so 《程序員自我修養》第八章
1.將所有.c文件編譯成.o文件
2.生成共享庫 gcc -shared -fPIC -o libmyfoo.so *.o/*.c
參數的意義《C專家編程》
shared的意義
-fPIC 作用於編譯階段,告訴編譯器產生與位置無關代碼(Position-Independent Code),則產生的代碼中,沒有絕對地址,全部使用相對地址,故而代碼可以被加載器加載到內存的任意位置,都可以正確的執行
使用庫
gcc -o main main.c -L路徑 -l庫名
沒有指定庫,編譯會失敗,要加路徑和庫名 路徑在標準目錄下不用加 在當前位置要加 -L路徑 -l庫名
執行可執行程序時還會調用庫文件(共享庫特點),因此有兩種辦法 改變環境變量LD_LIBRARY_PATH,將路徑爲本地路徑,可以系統會在本地路徑搜索共享庫,或者直接吧共享庫放入標準庫文件目錄下
系統的頭文件一般放在/usr/include 系統的庫文件一般放在/usr/lib /lib 可執行程序 /usr/bin /bin
環境變量 LD_LIBRARY_PATH : 系統搜索標準庫文件的路徑 可在一個終端中指定搜索路徑,指定程序運行時鏈接共享庫的位置
終端關閉後失效,臨時改變LD_LIBRARY_PATH=. ( . 爲當前位置 ,中間不能有空格,此時LD_LIBRARY_PATH爲本地變量,可通過 echo $LD_LIBRARY_PATH 查看)
export LD_LIBRARY_PATH ( 將LD_LIBRARY_PATH 設爲環境變量)
共享庫與靜態庫的區別
靜態庫 裏面的方法會編譯鏈接包含到程序 體積太大
共享庫 編譯鏈接,只做標記 沒有包含方法的實現 運行程序時 動態加載(速度較慢),並且裏面方法可以被多個程序共享使用
靜態庫是在生成可執行程序時,將靜態庫的方法包含在了可執行程序中,即刪除靜態庫,但由於靜態庫方法已經被包含在了可執行程序中,則程序仍可執行,不再依賴於外部靜態庫。
共享庫是在運行程序時才動態加載庫方法,若刪除共享庫,則程序運行時進行動態加載庫方法時找不見共享庫,程序將無法執行。
靜態庫的運行速度快,但程序體積相對較大,不易版本升級,若升級,則程序需要重新編譯;
共享庫由於運行要動態加載庫文件,則運行速度慢,但程序體積小,方便版本升級,程序不用重新編譯
問題
- 使用什麼命令可以查看某個進程使用了哪些庫
使用ldd main命令
- 製作共享庫時,-fPIC含義是什麼
表示編譯爲位置獨立的代碼,不用此選項的話編譯後的代碼是位置相關的,所以動態載入時是通過代碼拷貝的方式來滿足不同的調用,而不能達到真正的代碼段共享的目的
關於gcc的編譯參數:
-fPIC 生成與位置無關的代碼,這樣庫就可以在任何位置被連接和裝載
-shared 代表共享庫
-o 鏈接生成指定名字的庫或程序
-l 指定要鏈接的共享庫
-L 指定共享庫所在路徑