天天看點

在Linux系統(Ubuntu)下靜态庫與動态庫檔案的生成與使用一、Linux系統中函數庫的類型二、hello執行個體使用庫三、靜态庫執行個體四、動态庫執行個體五、實驗總結六、參考文獻

目錄

一、Linux系統中函數庫的類型

二、hello執行個體使用庫

(一)、準備步驟

(二)、靜态庫使用

(三)、動态庫使用

(四)、靜态庫與動态庫比較

三、靜态庫執行個體

(一)、建構新檔案夾,編寫程式

(二)、靜态庫.a 檔案的生成與使用

(三)、共享庫.so 檔案的生成與使用

四、動态庫執行個體

(一)、程式編寫 

(二)、用gcc分别編譯為3個.o 目标檔案 

(三)、将目标檔案生成靜态.a檔案

(四)、觀察檔案大小

(五)、将目标檔案生成動态庫.so檔案并與main函數連結

(六)、記錄大小并與靜态庫對比

五、實驗總結

六、參考文獻

一、Linux系統中函數庫的類型

函數庫分為靜态庫和動态庫。

  • 靜态庫

    在程式編譯時會被連接配接到目标代碼中,程式運作是則不需要靜态庫的存在。

  • 動态庫

    在程式編譯時不會被連接配接到目标代碼中,而是程式運作時載入的。

    兩者差別:前者是編譯連接配接的,後者是程式運作載入的。

二、hello執行個體使用庫

(一)、準備步驟

1.建立一個作業目錄test1,儲存本次練習檔案。

mkdir test1
cd test1
           
在Linux系統(Ubuntu)下靜态庫與動态庫檔案的生成與使用一、Linux系統中函數庫的類型二、hello執行個體使用庫三、靜态庫執行個體四、動态庫執行個體五、實驗總結六、參考文獻

2.hello代碼 ,使用gedit文本編輯器生成hello.c,hello.h,main.c三個檔案,三個檔案源代碼如下

程式一:hello.h檔案

#ifndef HELLO_H
#define HELLO_H
void hello(const char *name);
#endif //HELLO_H
           

 程式二:hello.c 

#include <stdio.h>
void hello(const char *name)
{
printf("Hello %s!\n", name);
}
           

程式三:main.c

#include "hello.h"
int main()
{
hello("everyone");
return 0;
}
           

3.将 hello.c 編譯成.o 檔案并觀察是否編譯成功 

gcc -c hello.c
 ls
           
在Linux系統(Ubuntu)下靜态庫與動态庫檔案的生成與使用一、Linux系統中函數庫的類型二、hello執行個體使用庫三、靜态庫執行個體四、動态庫執行個體五、實驗總結六、參考文獻

 4.由.o 檔案建立靜态庫并觀察

建立靜态庫的工具:ar

靜态庫檔案命名規範:以lib作為字首,是.a檔案

ar -crv libmyhello.a hello.o
 ls
           
在Linux系統(Ubuntu)下靜态庫與動态庫檔案的生成與使用一、Linux系統中函數庫的類型二、hello執行個體使用庫三、靜态庫執行個體四、動态庫執行個體五、實驗總結六、參考文獻

(二)、靜态庫使用

 1.含這些公用函數的原型聲明,然後在用 gcc 指令生成目标檔案時指明靜态庫名,gcc 将會從 靜态庫中将公用函數連接配接到目标檔案中。注意,gcc 會在靜态庫名前加上字首 lib,然後追 加擴充名.a 得到的靜态庫檔案名來查找靜态庫檔案。

方法一:

gcc -o hello main.c -L. –lmyhello
           

方法二:

gcc main.c libmyhello.a -o hello
           

 方法三:

先生成 main.o,再生成可執行檔案

gcc -c main.c
gcc -o hello main.o libmyhello.a
           

本次采用的是方法三,操作結果為:  

在Linux系統(Ubuntu)下靜态庫與動态庫檔案的生成與使用一、Linux系統中函數庫的類型二、hello執行個體使用庫三、靜态庫執行個體四、動态庫執行個體五、實驗總結六、參考文獻

 2.驗證靜态庫是否生成成功

打開檔案

./hello
           

删除靜态庫檔案試試公用函數 hello 是否真的連接配接到

rm libmyhello.a
           
在Linux系統(Ubuntu)下靜态庫與動态庫檔案的生成與使用一、Linux系統中函數庫的類型二、hello執行個體使用庫三、靜态庫執行個體四、動态庫執行個體五、實驗總結六、參考文獻

 3.通過觀察發現程式照常運作,證明表明靜态庫跟程式執行沒有聯系以及靜态庫中的公用函數是在編譯過程中直接被調用的。 

在Linux系統(Ubuntu)下靜态庫與動态庫檔案的生成與使用一、Linux系統中函數庫的類型二、hello執行個體使用庫三、靜态庫執行個體四、動态庫執行個體五、實驗總結六、參考文獻

 (三)、動态庫使用

1.建立動态庫

建立動态庫的工具:gcc

動态庫檔案命名規範:以lib作為字首,是.so檔案

gcc -shared -fPIC -o libmyhello.so hello.o

shared:表示指定生成動态連結庫,不可省略

-fPIC:表示編譯為位置獨立的代碼,不可省略

gcc -shared -fPIC -o libmyhello.so hello.o
ls
           
在Linux系統(Ubuntu)下靜态庫與動态庫檔案的生成與使用一、Linux系統中函數庫的類型二、hello執行個體使用庫三、靜态庫執行個體四、動态庫執行個體五、實驗總結六、參考文獻

 2.在程式中使用動态庫 

輸入指令gcc main.c libmyhello.so -o hello 或 gcc -o hello main.c -L. -lmyhello

在Linux系統(Ubuntu)下靜态庫與動态庫檔案的生成與使用一、Linux系統中函數庫的類型二、hello執行個體使用庫三、靜态庫執行個體四、動态庫執行個體五、實驗總結六、參考文獻

發現在顯示檔案時沒有問題,但在./hello 會提示出錯,因為雖然連接配接時用的是目前目錄的動态庫,但是運作時,是到 /usr/lib 中找庫檔案的,将檔案 libmyhello.so 複制到目錄/usr/lib 中就可以了。 

mv libmyhello.so /usr/lib
           
在Linux系統(Ubuntu)下靜态庫與動态庫檔案的生成與使用一、Linux系統中函數庫的類型二、hello執行個體使用庫三、靜态庫執行個體四、動态庫執行個體五、實驗總結六、參考文獻

 發現無權限,此時我們可以用sudo指令解決

sudo mv libmyhello.so /usr/lib
           
在Linux系統(Ubuntu)下靜态庫與動态庫檔案的生成與使用一、Linux系統中函數庫的類型二、hello執行個體使用庫三、靜态庫執行個體四、動态庫執行個體五、實驗總結六、參考文獻

(四)、靜态庫與動态庫比較

1.先删除除.c 和.h 外的所有檔案,恢複成我們剛剛編輯完舉例程式狀态

sudo rm -f hello hello.o /usr/lib/libmyhello.so
ls
           

2.再來建立靜态庫檔案 libmyhello.a 和動态庫檔案 libmyhello.so 

gcc -c hello.c
ar -cr libmyhello.a hello.o
gcc -shared -fPIC -o libmyhello.so hello.o
ls
           

3.運作 gcc 指令來使用函數庫 myhello 生成目 标檔案 hello,并運作程式 hello

gcc -o hello main.c -L. -lmyhello
           

 4.結果觀察

在Linux系統(Ubuntu)下靜态庫與動态庫檔案的生成與使用一、Linux系統中函數庫的類型二、hello執行個體使用庫三、靜态庫執行個體四、動态庫執行個體五、實驗總結六、參考文獻

 發現在執行可執行檔案,會報一個錯誤,可見當靜态庫和動态庫同時存在的時候,程式會優先使用動态庫。

三、靜态庫執行個體

(一)、建構新檔案夾,編寫程式

A1.c

#include <stdio.h>
void print1(int arg){
printf("A1 print arg:%d\n",arg);
}
           

A2.c

#include <stdio.h>
void print2(char *arg){
printf("A2 printf arg:%s\n", arg);
}
           

A.h

#ifndef A_H
#define A_H
void print1(int);
void print2(char *);
#endif
           

test.c

#include <stdlib.h>
#include "A.h"
int main(){
print1(1);
print2("test");
exit(0);
}
           

 程式建構如下: 

在Linux系統(Ubuntu)下靜态庫與動态庫檔案的生成與使用一、Linux系統中函數庫的類型二、hello執行個體使用庫三、靜态庫執行個體四、動态庫執行個體五、實驗總結六、參考文獻

(二)、靜态庫.a 檔案的生成與使用

1.生成目标檔案

gcc -c A1.c A2.c
           
在Linux系統(Ubuntu)下靜态庫與動态庫檔案的生成與使用一、Linux系統中函數庫的類型二、hello執行個體使用庫三、靜态庫執行個體四、動态庫執行個體五、實驗總結六、參考文獻

 2.生成靜态庫.a 檔案

ar crv libafile.a A1.o A2.o
           
在Linux系統(Ubuntu)下靜态庫與動态庫檔案的生成與使用一、Linux系統中函數庫的類型二、hello執行個體使用庫三、靜态庫執行個體四、動态庫執行個體五、實驗總結六、參考文獻

 3.使用.a 庫檔案,建立可執行程式(若采用此種方式,需保證生成的.a 檔案與.c 檔案保 存在同一目錄下,即都在目前目錄下)

gcc -o test test.c libafile.a
./test
           
在Linux系統(Ubuntu)下靜态庫與動态庫檔案的生成與使用一、Linux系統中函數庫的類型二、hello執行個體使用庫三、靜态庫執行個體四、動态庫執行個體五、實驗總結六、參考文獻

(三)、共享庫.so 檔案的生成與使用

1.生成目标檔案(xxx.o)(此處生成.o 檔案必須添加"-fpic"(小模式,代碼少),否則在生成.so 檔案時會出錯)

gcc -c -fpic A1.c A2.c
           

 2.生成共享庫.so 檔案

gcc -shared *.o -o libsofile.so
           
在Linux系統(Ubuntu)下靜态庫與動态庫檔案的生成與使用一、Linux系統中函數庫的類型二、hello執行個體使用庫三、靜态庫執行個體四、動态庫執行個體五、實驗總結六、參考文獻

 3.使用.so 庫檔案,建立可執行程式

gcc -o test test.c libsofile.so
./test
           
在Linux系統(Ubuntu)下靜态庫與動态庫檔案的生成與使用一、Linux系統中函數庫的類型二、hello執行個體使用庫三、靜态庫執行個體四、動态庫執行個體五、實驗總結六、參考文獻
 解決辦法:這是由于 linux 自身系統設定的相應的設定的原因,即其隻在/lib and /usr/lib 下搜尋對應 的.so 檔案,故需将對應 so 檔案拷貝到對應路徑。 
sudo cp libsofile.so /usr/lib
           
在Linux系統(Ubuntu)下靜态庫與動态庫檔案的生成與使用一、Linux系統中函數庫的類型二、hello執行個體使用庫三、靜态庫執行個體四、動态庫執行個體五、實驗總結六、參考文獻
 同時可直接使用 gcc -o test test.c -L. -lname,來使用相應庫檔案 其中, -L.:表示在目前目錄下,可自行定義路徑 path,即使用-Lpath 即可。 -lname:name:即對應庫檔案的名字(除開 lib),即若使用 libafile.a,則 name 為 afile; 若要使用 libsofile.so,則 name 為 sofile)。

四、動态庫執行個體

詳細過程可參照hello程式過程

(一)、程式編寫 

 程式一:lcx.c

float x2x(int a,int b)
{
	float c=0;
	c=a+b;
	return c;
}
           

程式二:lcy.c

float x2y(int a,int b)
{
	float c=0;
	c=a*b;
	return c;
}
           

 程式三:lc.h

#ifndef LC_H
#define LC_H
float x2x(int a,int b);
float x2y(int a,int b);
#endif
           

程式四:main.c

#include<stdio.h>
#include"lc.h"
void main()
{
	int a,b;
	printf("Please input the value of a:");
	scanf("%d",&a);
	printf("Please input the value of b:");
	scanf("%d",&b);
	printf("a+b=%.2f\n",x2x(a,b));
	printf("a*b=%.2f\n",x2y(a,b));
}
           

 代碼運作如下:

在Linux系統(Ubuntu)下靜态庫與動态庫檔案的生成與使用一、Linux系統中函數庫的類型二、hello執行個體使用庫三、靜态庫執行個體四、動态庫執行個體五、實驗總結六、參考文獻

(二)、用gcc分别編譯為3個.o 目标檔案 

gcc -c lcx.c lcy.c main.c
           
在Linux系統(Ubuntu)下靜态庫與動态庫檔案的生成與使用一、Linux系統中函數庫的類型二、hello執行個體使用庫三、靜态庫執行個體四、動态庫執行個體五、實驗總結六、參考文獻

(三)、将目标檔案生成靜态.a檔案

ar crv liblc.a lcx.o lcy.o
gcc -o main main.o liblc.a
           
注:在進行檔案連結時,務必要注意需要用之前生成的.o檔案,不然的話會報錯 

代碼運作如下:

在Linux系統(Ubuntu)下靜态庫與動态庫檔案的生成與使用一、Linux系統中函數庫的類型二、hello執行個體使用庫三、靜态庫執行個體四、動态庫執行個體五、實驗總結六、參考文獻

(四)、觀察檔案大小

在linux下使用“ls -l”或者“ls -al”或者“ll”指令檢視檔案及目錄詳情
在Linux系統(Ubuntu)下靜态庫與動态庫檔案的生成與使用一、Linux系統中函數庫的類型二、hello執行個體使用庫三、靜态庫執行個體四、動态庫執行個體五、實驗總結六、參考文獻

(五)、将目标檔案生成動态庫.so檔案并與main函數連結

gcc -shared -fPIC -o liblc.so lcx.o lcy.o
gcc -o main main.o liblc.so
           

 代碼運作如下:

在Linux系統(Ubuntu)下靜态庫與動态庫檔案的生成與使用一、Linux系統中函數庫的類型二、hello執行個體使用庫三、靜态庫執行個體四、動态庫執行個體五、實驗總結六、參考文獻

(六)、記錄大小并與靜态庫對比

動态庫:

在Linux系統(Ubuntu)下靜态庫與動态庫檔案的生成與使用一、Linux系統中函數庫的類型二、hello執行個體使用庫三、靜态庫執行個體四、動态庫執行個體五、實驗總結六、參考文獻

 靜态庫:

在Linux系統(Ubuntu)下靜态庫與動态庫檔案的生成與使用一、Linux系統中函數庫的類型二、hello執行個體使用庫三、靜态庫執行個體四、動态庫執行個體五、實驗總結六、參考文獻

 對比可知,靜态庫占用空間更少。

五、實驗總結

       通過本次實驗,使我初次了解并熟悉了靜态庫和動态庫的相關知識,使我能夠自主的生成靜态庫和動态庫,進一步了解二者之間的差别。同時通過本次實驗,加強了我對 Linux系統的運作操作,加強了對gcc等相關編譯工具的運用。

六、參考文獻

gcc生成靜态庫.a和動态庫.so_Harriet的部落格-CSDN部落格

Ubuntu實操二:靜态庫與動态庫檔案的生成與使用_Lc-Yusheng的部落格-CSDN部落格