一、庫的簡述
簡單的說,庫(Library)是由系統提供的一組具有特定功能的函數的集合,是為提高開發效率和運行效率而設計的。從本質上來說是一種可執行代碼的二進制格式,可以被載入內存中執行。庫分靜態庫和動態庫兩種。
靜態庫:
靜態是指每個用到該庫的應用程序都會將該庫拷貝到自己的目標代碼中,因此利用靜態庫生成的文件比較大。
命名:lib****.a
動態庫(也叫共享庫):
動態庫在編譯時并沒有將該庫帶進目標代碼中,當程序執行到相關函數時才調用該庫,因此使用這類庫生成的文件會比較小。動態庫的改變并不會影響你自己的程序,因此動態庫的升級比較方便。除此之外,動態庫有一個最顯著的特點就是:當多個程序調用同個共享庫時,內存中只有一個動態庫實例。
命名: lib****.so
linux系統有幾個重要的目錄存放相應的函數庫,如/lib /usr/lib。
二、庫的生成
我們以下列代碼為例講解靜態庫與動態庫的生成,準備好test.c hello.c hello.h文件
"test.c"
#include "hello.h"int main(){ hello("world!"); return 0;}"hello.c"
#include"hello.h"#include<stdio.h>void hello(const char *name){ PRintf("hello %s! /n",name);}"hello.h"
#ifndef _HELLO_H_#define _HELLO_H_void hello(const char *name);#endif無論動態庫或者靜態庫都是從.o文件生成的,因此在講解動態庫和靜態庫之前,我們先執行以下命令生成 hello.o 文件和 test.o 文件:
$ gcc -c hello.c
$ gcc -c test.c
再 ls 一下就可以看到當前目錄下多了兩個文件:hello.o 和 test.o
·生成靜態庫
①通過gcc編譯生成.o文件(無論靜態庫還是動態庫都是由.o文件生成的)
②使用ar命令創建靜態庫,ar命令將很多.o文件轉換成.a文件
命令:ar rcs lib****.a ***.o
舉例,假設我們要生成libmyhello.a的靜態庫文件,就是 ar rcs libmyhello.a hello.o
·生成動態庫
我們從.o文件開始,首先需要創建一個名為myhello的動態庫,則動態庫文件名就是libmyhelli.so
執行這條命令以生成 libmyhello.so 的文件。
$ gcc -shared -fPIC -o libmyhello.so hello.o
·筆記:“PIC”命令行標記告訴gcc產生的代碼不要包含對函數和變量具體內存位置的引用,這是因為現在還無法知道使用該消息代碼的應用程序會將它連接到哪一段內存地址空間。這樣編譯出的 hello.o 可以被用于建立共享鏈接庫。建立共享鏈接庫只需要gcc的“-shared”標記即可。

調用動態庫編譯并鏈接文件,生成可執行程序hello:
$ gcc -o hello test.c -L. -lmyhello
·筆記:“-lmyhello”標記告訴gcc驅動程序在鏈接階段引用共享庫 libmyhello.so
“-L.”標記告訴gcc函數庫可能位于當前目錄。否則GNU連接器會查找標準系統函數目錄,它會先后搜索以下路徑:1. elf文件的 DT_RPATH段; 2. 環境變量LD_LIBRARY_PATH; 3. /etc/ld.so.cache文件列表; 4. /lib/,/usr/lib/ 目錄,找到庫文件后將其載入內存。

繼續,我們接著執行hello:
$./hello
·筆記:當我們在命令行執行該指令后發現會有錯誤“./hello: error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory”,這是由于我們生成的共享庫在當前文件下,而在我們上述的四個路徑的任一個路徑下。因此我們需要將 libmyhello.so 復制到 /usr/lib/下,當再次執行 hello 時便可執行成功。

注意:在我們拷貝 libmyhello.so 文件到 /usr/lib/ 時,要是root用戶才可執行
既然連接器會搜尋LD_LIBRARY_PATH所指定的目錄,所以我們也可以將這個環境變量設置為當前目錄再執行 hello 也可以成功!

今天的分享就是這些了,主要是掌握上面的幾條命令。
新聞熱點
疑難解答