Linux下動態庫有三個名字:real name、so name、link name。
- real name:共享庫本身的名字,命名格式爲libname.so.x.y.z,lib是前綴,name是共享庫的名字,so是後綴,x是主版本,y是次版本號,z是發佈版本號。
主版本號、次版本號和發佈版本號的意義如下:
主版本號:表示庫的重大升級,比如改變了原有的接口。不同主版本號的庫是不兼容的,要保證向下兼容就不能刪除舊版本的動態庫。
次版本號:表示庫的增量升級,比如增加了新的接口,但原有接口保持不變。高的次版本號的庫向下兼容低的次版本號的動態庫,原有的版本庫是可以不保留的。
發佈版本號:表示指示改正了一些錯誤或者是性能優化等,接口沒有增加,也沒有改變,因此也是向下兼容的。
- so name:是通過ldconfig命令,來創建的指向真正的動態庫(real name)的鏈接,so name的命名規則是,real name去掉次版本號和發佈版本號,格式爲libname.so.x。
- link name:是so name的軟鏈接,命名規則是,real name去掉主版本號、次版本號和發佈版本號,格式爲libname.so,編譯時,通過參數-lname來鏈接。
下面通過實際的例子來說明動態庫的編譯和鏈接:
首先,建立hello.c和hello.h兩個文件,然後將他們編譯成動態鏈接庫。
hello.c文件:
#include <stdio.h>
void hello (void)
{
printf("Hello, library world.\n");
}
hello.h文件:
#ifndef __HELLO_H__
#define __HELLO_H__
void hello (void);
#endif
執行如下命令,編譯生成共享庫
$gcc hello.c -fPIC -shared -Wl,-soname,libhello.so.0 -o libhello.so.0.0.0
編譯完成後,只生成了libhello.so.0.0.0,並未生成libhello.so.0,若要生成libhello.so.0需要做如下操作:
在/etc/ld.so.conf文件中指定庫的路徑,在文件中添加:libhello.so.0.0.0這個庫所在的絕對路徑。
執行如下命令生成libhello.so.0:
$sudo ldconfig
下面需要爲libhello.so.0建立一個軟鏈接,方便編譯應用程序是鏈接,執行如下命令:
$ln -s libhello.so.0 libhello.so
然後,編寫應用程序來調用動態庫。
main.c文件:
#include "hello.h"
int main(void)
{
hello();
return 0;
}
執行下面的命令編譯生成main的可執行文件:
$gcc main.c -L. -lhello -o main
注:沒有重大升級(主版本號未更改),編譯新版本的動態庫後,執行$sudo ldconfig就可以進行動態庫的升級。如果進行重大升級(更改主版本號),編譯新版本的動態庫後,執行$sudo ldconfig,生成新的so name文件,再執行$ln -s libhello.so.1 libhello.so(主版本號升級爲1).如果想重新恢復爲舊版本的動態庫,只需要執行$ln -s libhello.so.0 libhello.so