自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Linux 上靜態(tài)鏈接庫工作原理

系統(tǒng) Linux
學(xué)習(xí)如何用靜態(tài)鏈接庫將多個 C 目標(biāo)文件結(jié)合到一個單個的可執(zhí)行文件之中。在這篇文章中,我將說明如何創(chuàng)建一個靜態(tài)鏈接的可執(zhí)行文件。

學(xué)習(xí)如何用靜態(tài)鏈接庫將多個 C 目標(biāo)文件結(jié)合到一個單個的可執(zhí)行文件之中。

使用 C 編寫的應(yīng)用程序時,通常有多個源碼文件,但最終你需要編譯成單個的可執(zhí)行文件。

你可以通過兩種方式來完成這項工作:通過創(chuàng)建一個 靜態(tài)static 庫 或 一個 動態(tài)dynamic 庫(也被稱為 共享shared 庫)。從創(chuàng)建和鏈接的方式來看,它們是兩種不同類型的庫。選擇使用哪種方式取決于你的的具體場景。

在 上一篇文章 中,我演示了如何創(chuàng)建一個動態(tài)鏈接的可執(zhí)行文件,這是一種更通用的方法。在這篇文章中,我將說明如何創(chuàng)建一個靜態(tài)鏈接的可執(zhí)行文件。

使用靜態(tài)庫鏈接器

鏈接器linker是一個命令,它將一個程序的多個部分結(jié)合在一起,并為它們重新組織內(nèi)存分配。

鏈接器的功能包括:

  • 整合一個程序的所有的部分
  • 計算出一個新的內(nèi)存組織結(jié)構(gòu),以便所有的部分組合在一起
  • 恢復(fù)內(nèi)存地址,以便程序可以在新的內(nèi)存組織結(jié)構(gòu)下運行
  • 解析符號引用

鏈接器通過這些功能,創(chuàng)建了一個名稱為可執(zhí)行文件的一個可運行程序。

靜態(tài)庫是通過復(fù)制一個程序中的所有依賴庫模塊到最終的可執(zhí)行鏡像來創(chuàng)建的。鏈接器將鏈接靜態(tài)庫作為編譯過程的最后一步。可執(zhí)行文件是通過解析外部引用、將庫例程與程序代碼結(jié)合在一起來創(chuàng)建的。

創(chuàng)建目標(biāo)文件

這里是一個靜態(tài)庫的示例以及其鏈接過程。首先,創(chuàng)建帶有這些函數(shù)識別標(biāo)志的頭文件 mymath.h :

    int add(int a, int b);
int sub(int a, int b);
int mult(int a, int b);
int divi(int a, int b);

使用這些函數(shù)定義來創(chuàng)建 add.c 、sub.c 、mult.c 和 divi.c 文件。我將把所有的代碼都放置到一個代碼塊中,請將其分為四個文件,如注釋所示:

    // add.c
int add(int a, int b){
return (a+b);
}
//sub.c
int sub(int a, int b){
return (a-b);
}
//mult.c
int mult(int a, int b){
return (a*b);
}
//divi.c
int divi(int a, int b){
return (a/b);
}

現(xiàn)在,使用 GCC 來生成目標(biāo)文件 add.o 、sub.o 、mult.o 和 divi.o:

(LCTT 校注:關(guān)于“目標(biāo)文件object file”,有時候也被稱作“對象文件”,對此,存在一些譯法混亂情形,稱之為“目標(biāo)文件”的譯法比較流行,本文采用此譯法。)

    $ gcc -c add.c sub.c mult.c divi.c

-c 選項跳過鏈接步驟,而只創(chuàng)建目標(biāo)文件。

創(chuàng)建一個名稱為 libmymath.a 的靜態(tài)庫,接下來,移除目標(biāo)文件,因為它們不再被需要。(注意,使用一個 trash 命令比使用一個 rm 命令更安全。)

    $ ar rs libmymath.a add.o sub.o mult.o divi.o
$ trash *.o
$ ls
add.c divi.c libmymath.a mult.c mymath.h sub.c

現(xiàn)在,你已經(jīng)創(chuàng)建了一個名稱為 libmymath 的簡單數(shù)學(xué)示例庫,你可以在 C 代碼中使用它。當(dāng)然,也有非常復(fù)雜的 C 庫,這就是他們這些開發(fā)者來生成最終產(chǎn)品的工藝流程,你和我可以安裝這些庫并在 C 代碼中使用。

接下來,在一些自定義代碼中使用你的數(shù)學(xué)庫,然后鏈接它。

創(chuàng)建一個靜態(tài)鏈接的應(yīng)用程序

假設(shè)你已經(jīng)為數(shù)學(xué)運算編寫了一個命令。創(chuàng)建一個名稱為 mathDemo.c 的文件,并將這些代碼復(fù)制粘貼至其中:

    #include <mymath.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int x, y;
printf("Enter two numbers\n");
scanf("%d%d",&x,&y);

printf("\n%d + %d = %d", x, y, add(x, y));
printf("\n%d - %d = %d", x, y, sub(x, y));
printf("\n%d * %d = %d", x, y, mult(x, y));
if(y==0){
printf("\nDenominator is zero so can't perform division\n");
exit(0);
}else{
printf("\n%d / %d = %d\n", x, y, divi(x, y));
return 0;
}
}

注意:第一行是一個 include 語句,通過名稱來引用你自己的 libmymath 庫。

針對 mathDemo.c 創(chuàng)建一個名稱為 mathDemo.o 的對象文件:

    $ gcc -I . -c mathDemo.c

-I 選項告訴 GCC 搜索在其后列出的頭文件。在這個實例中,你通過單個點(.)來指定當(dāng)前目錄。

鏈接 mathDemo.o 和 libmymath.a 來生成最終的可執(zhí)行文件。這里有兩種方法來向 GCC 告知這一點。

你可以指向文件:

    $ gcc -static -o mathDemo mathDemo.o libmymath.a

或者,你可以具體指定庫的路徑及名稱:

    $ gcc -static -o mathDemo -L . mathDemo.o -lmymath

在后面的那個示例中,-lmymath 選項告訴鏈接器來鏈接對象文件 mathDemo.o 和對象文件 libmymath.a 來生成最終的可執(zhí)行文件。-L 選項指示鏈接器在下面的參數(shù)中查找?guī)欤愃朴谀闶褂?nbsp;-I 所做的工作)。

分析結(jié)果

使用 file 命令來驗證它是靜態(tài)鏈接的:

    $ file mathDemo
mathDemo: ELF 64-bit LSB executable, x86-64...
statically linked, with debug_info, not stripped

使用 ldd 命令,你將會看到該可執(zhí)行文件不是動態(tài)鏈接的:

    $ ldd ./mathDemo
not a dynamic executable

你也可以查看 mathDemo 可執(zhí)行文件的大?。?/p>

    $ du -h ./mathDemo
932K ./mathDemo

在我 前一篇文章 的示例中,動態(tài)鏈接的可執(zhí)行文件只占有 24K 大小。

運行該命令來看看它的工作內(nèi)容:

    $ ./mathDemo
Enter two numbers
10
5
10 + 5 = 15
10 - 5 = 5
10 * 5 = 50
10 / 5 = 2

看起來令人滿意!

何時使用靜態(tài)鏈接

動態(tài)鏈接可執(zhí)行文件通常優(yōu)于靜態(tài)鏈接可執(zhí)行文件,因為動態(tài)鏈接會保持應(yīng)用程序的組件模塊化。假如一個庫接收到一次關(guān)鍵安全更新,那么它可以很容易地修補,因為它存在于應(yīng)用程序的外部。

當(dāng)你使用靜態(tài)鏈接時,庫的代碼會“隱藏”在你創(chuàng)建的可執(zhí)行文件之中,意味著在庫每次更新時(相信我,你會有更好的東西),僅有的一種修補方法是重新編譯和發(fā)布一個新的可執(zhí)行文件。

不過,如果一個庫的代碼,要么存在于它正在使用的具有相同代碼的可執(zhí)行文件中,要么存在于不會接收到任何更新的專用嵌入式設(shè)備中,那么靜態(tài)連接將是一種可接受的選項。

責(zé)任編輯:未麗燕 來源: Linux中國
相關(guān)推薦

2022-06-08 09:56:46

靜態(tài)鏈接Linux命令

2011-08-02 14:15:05

XCode 靜態(tài) 鏈接庫

2011-09-06 16:30:32

iOS系統(tǒng)靜態(tài)鏈接庫

2024-06-06 08:53:13

動態(tài)鏈接庫共享庫

2012-05-08 14:48:23

LinuxUnix動態(tài)鏈接庫

2012-05-04 08:24:14

LinuxUnix

2009-07-07 20:57:20

LinuxUnix動態(tài)鏈接庫

2023-03-05 16:36:14

Linux鏈接目標(biāo)文件

2011-06-21 18:02:14

Qt 動態(tài) 鏈接庫

2022-07-10 21:20:11

C語言Linux

2022-06-09 09:54:45

編譯軟件開發(fā)

2009-08-28 16:19:30

C#實現(xiàn)修改動態(tài)鏈接庫

2024-03-01 20:59:11

C#DLL開發(fā)

2022-05-03 23:44:21

Python動態(tài)鏈接庫Ctypes

2023-05-09 08:24:11

JNA鏈接庫代碼

2010-02-01 17:37:35

C++調(diào)用C鏈接庫

2009-08-05 16:29:18

C#調(diào)用C++動態(tài)鏈接

2009-12-23 16:28:13

Linux GCC

2010-01-05 13:32:36

.NET Framew

2022-10-24 00:03:21

動態(tài)鏈接庫DLL
點贊
收藏

51CTO技術(shù)棧公眾號