「程序庫」就是包含了一些同音函數的數據和二進制可執行機器碼的文件。這些文件是目標文件的一種,其不能單獨執行。可是若是將其與其餘的可執行代碼結合起來就能夠執行。這些目標文件一般能夠完成同一類功能,他們能夠做爲其餘執行程序的一部分來執行。因爲庫的存在,使得用戶編寫的程序模塊化更強,從而能夠增強程序的再編譯,提升代碼的複用性。linux
從連接方式上,程序庫可分爲靜態庫和動態庫(共享庫)兩種:shell
靜態庫是一些目標代碼的集合。linux環境下的靜態庫目標文件通常以.a做爲擴展名。Linux環境下使用ar命令建立一個靜態庫。靜態庫的優勢在於使用簡單,編譯快速,靜態庫在應用程序生成時,已經編譯成爲可重定位的目標文件,所以可沒必要再編譯。windows
因爲靜態庫在編譯時已經複製到可執行代碼段中,因此不須要像使用動態庫那樣在程序加載時再次連接。bash
建立一個四則運算的靜態庫:模塊化
(1)四則運算的代碼爲:函數
/* 計算加法的函數 */ int add(int a, int b) { return a + b; } /* 計算減法的運算 */ int sub(int a, int b) { return a - b; } /* 計算乘法的運算 */ int mul(int a, int b) { return a * b; } /* 計算除法的運算 */ int div(int a, int b) { return a / b; }
(2)在shell中編譯源文件,生成一個可重定位的目標文件:工具
gcc -c static_lib.c
生成的目標文件爲:spa
static_lib.o
(3)Linux下使用工具ar建立一個靜態庫,或者將目標文件加入到一個已經存在的靜態庫中,使用方法以下:code
ar rcs 靜態庫名 目標文件1 目標文件2...目標文件n
該命令將目標文件1~n加入到指定的靜態庫中。若是該靜態庫不存在,則建立靜態庫文件。其中ar工具的參數rcs起到了重要的做用。這三個參數分別表示:索引
如今使用剛生成的.o文件建立一個靜態庫:
ar rcs libstatic_lib.a static_lib.o
這樣就生成了一個新的靜態庫:
libstatic_lib.a
靜態庫建立成功後,須要連接到應用程序中使用。應用程序能夠引用該庫中的函數或者全局變量。爲了是應用程序能夠正確引用該庫中的全局符號,須要製做一個包含該靜態庫中全局符號聲明的頭文件,這個頭文件能夠包含在應用程序的頭文件中,這樣就可使用靜態庫中的全局符號了。
#include <stdio.h> #include "static_lib.h" int main(void) { int a, b; printf("please input a and b\n"); scanf("%d %d", &a, &b); printf("the add : %d\n", add(a, b)); printf("the sub : %d\n", sub(a, b)); printf("the mul : %d\n", mul(a, b)); printf("the div : %d\n", div(a, b)); return 0; }
使用-l選項來指定靜態庫,-L參數來指定庫文件的搜索路徑。-l和-L以後都櫛jie風沐雨帶參數而不跟空格,因此用一下命令編譯:
gcc -L/home/daowm/WorkSpace/C/linux/ch7 static_main.c -lstatic_lib -o static_main
或者使用 "." 表示當前目錄:
gcc -L. static_main.c -lstatic_lib -o static_main
注意:-l是連接器選項,必定要放在被編譯的源文件以後,即上面的static_main.c以後,若放在前面則會連接失敗。
gcc也支持使用-static選項對靜態庫連接:
gcc static_main.c -static ./libstatic_lib.a -o static_main
以上三種方法均可以。
運行程序以下:
動態庫又稱爲共享庫或者動態連接庫,現代程序中大量地使用動態連接庫,如windows下的dll文件和linux下的so文件,動態庫是在程序啓動時被裝載的。
當一個引用程序裝載了一個動態庫後,其餘應用程序仍能夠裝載同一個動態庫,這個被多個進程同時使用的動態庫在內存中只有一個副本。動態庫的優勢不少:
這裏使用上面的代碼來演示
(1)四則運算代碼
//static_lib.c /* 計算加法的函數 */ int add(int a, int b) { return a + b; } /* 計算減法的運算 */ int sub(int a, int b) { return a - b; } /* 計算乘法的運算 */ int mul(int a, int b) { return a * b; } /* 計算除法的運算 */ int div(int a, int b) { return a / b; }
(2)Linux下使用gcc建立一個動態庫。因爲動態庫能夠被多個進程共享加載,因此須要生成位置無關的目標文件。這時須要使用gcc編譯器的-fPIC選項,該選項用於生成位置無關的代碼。除了須要使用-fPIC選項外,還須要使用-shared選項,該選項將位置無關的代碼製做爲動態庫。
gcc -shared -fPIC -o shared_lib.so static_lib.c
這時一個新的動態庫就建立成功了。以後用戶能夠在本身的應用程序中引用該庫中的函數,在程序加載的時候連接該庫就能夠了。
動態庫建立成功後,應用程序能夠引用該庫中的函數或者全局變量。一樣在.h文件包含該動態庫中的全局符號:
//shared_lib.h extern int add(int a, int b); //加法函數的聲明 extern int sub(int a, int b); //減法函數的聲明 extern int mul(int a, int b); //乘法函數的聲明 extern int div(int a, int b); //除法函數的聲明
編寫程序:
//shared_main.c #include <stdio.h> #include "shared_lib.h" int main(void) { int a, b; printf("please input a and b\n"); scanf("%d %d", &a, &b); printf("the add : %d\n", add(a, b)); printf("the sub : %d\n", sub(a, b)); printf("the mul : %d\n", mul(a, b)); printf("the div : %d\n", div(a, b)); return 0; }
使用動態庫編譯生成可執行程序:
gcc shared_main.c ./shared_lib.so -o shared_main
運行結果同上。
同時,另一個程序也可使用該動態庫,由於動態庫是共享的。