一、介紹
在軟件編程中,通常會把功能或接口函數封裝成庫的形式,供給其它模塊或第三方使用。在linux系統中存在動態庫和靜態庫兩種形式。
靜態庫:以libxxx.a形式命名,編譯程序時,會將靜態庫數據編譯進可執行程序中。
動態庫:以libxxx.so形式命名,編譯程序時,不會被編譯進可執行程序中,而在程序運行時,動態的加載該動態庫
二、生成(以libmath_method.a/so爲例)
2.1 靜態庫的生成
gcc -c math_method.c
ar cr libmath_method.a math_method.o
ranlib libmath_method.a
查看庫中包含的文件:
ar -t libmath_method.a
math_method.o
2.2 動態庫的生成
gcc -fPIC -c math_method.c
gcc -shared -o libmath_method.so math_method.o
三、編譯鏈接
-L 指定搜尋庫的目錄
如指定當前目錄 gcc -L .
-l 指定要鏈接的庫的名稱
加入庫的名稱是libmath_method.a(.so),則gcc -lmath_method
鏈接時,如果動態庫和靜態庫同時存在,優先使用動態庫。也可以通過以下的參數指定動態或靜態庫
-Wl,-dn :指定動態庫
-Wl,-dy:指定動態庫
四、查看程序鏈接的動態庫庫
$ ldd a.out
linux-vdso.so.1 => (0x00007ffff47cb000)
libmath_method.so => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd659906000)
/lib64/ld-linux-x86-64.so.2 (0x00007fd659cdb000)
五、程序運行
4.1 靜態庫程序的運行
./a.out
4.2 動態庫版本程序的運行
./a.out: error while loading shared libraries: libmath_method.so: cannot open shared object file: No such file or directory
出現上述錯誤是因爲找不到動態庫,有以下兩種方式可以解決:
一、可以把當前路徑加入 /etc/ld.so.conf中然後運行ldconfig
二、把當前路徑加入環境變量LD_LIBRARY_PATH中,僅在當前環境有效
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
六、靜態庫和動態庫優缺點
1. 靜態庫程序會將函數庫編譯時程序,因此程序較大, 而動態庫程序較小
2. 由於靜態庫在編譯時已經將函數庫編譯進程序中,因此運行時不需要庫的支持;而動態庫程序在運行時必須提供相應的庫程序
3. 庫文件變化時,靜態庫程序需要重新編譯; 而動態庫只需要替換運行環境中的庫文件
4. 多個程序使用庫文件時,靜態庫需要每個程序都編譯時各自的程序中,而動態庫只需要在運行環境共享一份即可
七、源碼
Makefile:
CC=gcc
LIBRARY=-L. -Wl,-dy -lmath_method -Wl,-dy -lgcc_s
TARGET=a.out
$(TARGET): libmath_method.a libmath_method.so
gcc -o $@ main.c $(LIBRARY)
math_method.o: math_method.c
$(CC) -fPIC -c math_method.c
libmath_method.a: math_method.o
ar cr $@ $^
ranlib $@
libmath_method.so: math_method.o
$(CC) -shared -o $@ $^
.PHONY:
clean:
-rm -rf *.o *.a
-rm $(TARGET)
main.c:
#include <stdio.h>
#include "math_method.h"
int main(int arc, char *argv[])
{
printf("hello world\n");
printf("%d + %d = %d\n", 1, 9, math_add(1, 9));
return 0;
}
math_method.c:
#include <stdio.h>
int math_add(int a, int b)
{
return a + b;
}
int math_sub(int a, int b)
{
return a - b;
}
math_method.h:
#ifndef __MATH_METHOD_H__
#define __MATH_METHOD_H__
int math_add(int a, int b);
int math_sub(int a, int b);
#endif