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

如何在 Linux 上動(dòng)態(tài)鏈接模塊庫(kù)

開發(fā) 后端 Linux
學(xué)習(xí)如何用動(dòng)態(tài)鏈接庫(kù)將多個(gè) C 目標(biāo)文件結(jié)合到一個(gè)單個(gè)的可執(zhí)行文件之中。

當(dāng)使用 C 編程語(yǔ)言編寫一個(gè)應(yīng)用程序時(shí),你的代碼通常有多個(gè)源文件代碼。

最終,這些文件必須被編譯到一個(gè)單個(gè)的可執(zhí)行文件之中。你可以通過(guò)創(chuàng)建靜態(tài)或動(dòng)態(tài)庫(kù)(后者也被稱為 共享shared 庫(kù))來(lái)實(shí)現(xiàn)這一點(diǎn)。這兩種類型的庫(kù)在創(chuàng)建和鏈接的方式上有所不同。兩者都有缺點(diǎn)和優(yōu)點(diǎn),這取決于你的使用情況。

動(dòng)態(tài)鏈接是最常見的方法,尤其是在 Linux 系統(tǒng)上。動(dòng)態(tài)鏈接會(huì)保持庫(kù)模塊化,因此,很多應(yīng)用程序可以共享一個(gè)庫(kù)。應(yīng)用程序的模塊化也允許單獨(dú)更新其依賴的共享庫(kù)。

在這篇文章中,我將演示動(dòng)態(tài)鏈接是如何工作的。在后期的文章中,我將演示靜態(tài)鏈接。

鏈接器

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

鏈接器的功能包括:

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

鏈接器通過(guò)這些功能,創(chuàng)建了一個(gè)名為可執(zhí)行文件executable的可以運(yùn)行的程序。在你創(chuàng)建一個(gè)動(dòng)態(tài)鏈接的可執(zhí)行文件前,你需要一些用來(lái)鏈接的庫(kù),和一個(gè)用來(lái)編譯的應(yīng)用程序。準(zhǔn)備好你 ??最喜歡的文本編輯器?? 并繼續(xù)。

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

首先,創(chuàng)建帶有這些函數(shù)簽名的頭文件 ??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ù)定義來(lái)創(chuàng)建 ??add.c??? 、??sub.c??? 、??mult.c??? 和 ??divi.c?? 文件。我將把所有的代碼都放置到一個(gè)代碼塊中,請(qǐng)將其分為四個(gè)文件,如注釋所示:

    // 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 來(lái)創(chuàng)建目標(biāo)文件 ??add.o???、??sub.o???、??mult.o??? 和 ??divi.o?? :

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

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

??-c?? 選項(xiàng)跳過(guò)鏈接步驟,并且只創(chuàng)建目標(biāo)文件。

創(chuàng)建一個(gè)共享的目標(biāo)文件

在最終的可執(zhí)行文件的執(zhí)行過(guò)程中將鏈接動(dòng)態(tài)庫(kù)。在最終的可執(zhí)行文件中僅放置動(dòng)態(tài)庫(kù)的名稱。實(shí)際上的鏈接過(guò)程發(fā)生在運(yùn)行時(shí),在此期間,可執(zhí)行文件和庫(kù)都被放置到了主內(nèi)存中。

除了可共享外,動(dòng)態(tài)庫(kù)的另外一個(gè)優(yōu)點(diǎn)是它減少了最終的可執(zhí)行文件的大小。在一個(gè)應(yīng)用程序最終的可執(zhí)行文件生成時(shí),其使用的庫(kù)只包括該庫(kù)的名稱,而不是該庫(kù)的一個(gè)多余的副本。

你可以從你現(xiàn)有的示例代碼中創(chuàng)建動(dòng)態(tài)庫(kù):

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

選項(xiàng) ??-fPIC??? 告訴 GCC 來(lái)生成位置無(wú)關(guān)的代碼position-independent code(PIC)。??-Wall?? 選項(xiàng)不是必需的,并且與代碼的編譯方式是無(wú)關(guān)的。不過(guò),它卻是一個(gè)有價(jià)值的選項(xiàng),因?yàn)樗鼤?huì)啟用編譯器警告,這在排除故障時(shí)是很有幫助的。

使用 GCC ,創(chuàng)建共享庫(kù) ??libmymath.so?? :

    $ gcc -shared -o libmymath.so add.o sub.o mult.o divi.o

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

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

創(chuàng)建一個(gè)動(dòng)態(tài)鏈接的可執(zhí)行文件

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

nclude <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;
}
}

注意:第一行是一個(gè) ??include??? 語(yǔ)句,通過(guò)名稱來(lái)引用你自己的 ??libmymath??? 庫(kù)。要使用一個(gè)共享庫(kù),你必須已經(jīng)安裝了它,如果你沒(méi)有安裝你將要使用的庫(kù),那么當(dāng)你的可執(zhí)行文件在運(yùn)行并搜索其包含的庫(kù)時(shí),將找不到該共享庫(kù)。如果你需要在不安裝庫(kù)到已知目錄的情況下編譯代碼,這里有 ??一些方法可以覆蓋默認(rèn)設(shè)置??。不過(guò),對(duì)于一般使用來(lái)說(shuō),我們希望庫(kù)存在于已知的位置,因此,這就是我在這里演示的東西。

復(fù)制文件 ??libmymath.so??? 到一個(gè)標(biāo)準(zhǔn)的系統(tǒng)目錄,例如:??/usr/lib64???, 然后運(yùn)行 ??ldconfig??? 。??ldconfig?? 命令創(chuàng)建所需的鏈接,并緩存到標(biāo)準(zhǔn)庫(kù)目錄中發(fā)現(xiàn)的最新共享庫(kù)。

    $ sudo cp libmymath.so /usr/lib64/
$ sudo ldconfig

編譯應(yīng)用程序

從你的應(yīng)用程序源文件代碼(??mathDemo.c???)中創(chuàng)建一個(gè)名稱為 ??mathDemo.o?? 的目標(biāo)文件:

    $ gcc -I . -c mathDemo.c

??-I??? 選項(xiàng)告訴 GCC 來(lái)在其后所列出的目錄中搜索頭文件(在這個(gè)示例中是 ??mymath.h???)。在這個(gè)示例中,你指定的是當(dāng)前目錄,通過(guò)一個(gè)單點(diǎn)(??.???)來(lái)表示。創(chuàng)建一個(gè)可執(zhí)行文件,使用 ??-l?? 選項(xiàng)來(lái)通過(guò)名稱來(lái)引用你的共享數(shù)學(xué)庫(kù):

    $ gcc -o mathDynamic mathDemo.o -lmymath

GCC 會(huì)找到 ??libmymath.so??? ,因?yàn)樗嬖谟谝粋€(gè)默認(rèn)的系統(tǒng)庫(kù)目錄中。使用 ??ldd?? 來(lái)查證所使用的共享庫(kù):

    $ ldd mathDemo
linux-vdso.so.1 (0x00007fffe6a30000)
libmymath.so => /usr/lib64/libmymath.so (0x00007fe4d4d33000)
libc.so.6 => /lib64/libc.so.6 (0x00007fe4d4b29000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe4d4d4e000)

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

    $ du ./mathDynamic
24 ./mathDynamic

當(dāng)然,它是一個(gè)小的應(yīng)用程序,它所占用的磁盤空間量也反映了這一點(diǎn)。相比之下,相同代碼的一個(gè)靜態(tài)鏈接版本(正如你將在我后期的文章所看到的一樣)是 932K !

    $ ./mathDynamic
Enter two numbers
25
5
25 + 5 = 30
25 - 5 = 20
25 * 5 = 125
25 / 5 = 5

你可以使用 ??file?? 命令來(lái)查證它是動(dòng)態(tài)鏈接的:

    $ file ./mathDynamic
./mathDynamic: ELF 64-bit LSB executable, x86-64,
dynamically linked,
interpreter /lib64/ld-linux-x86-64.so.2,
with debug_info, not stripped

成功!

動(dòng)態(tài)鏈接

因?yàn)殒溄影l(fā)生在運(yùn)行時(shí),所以,使用一個(gè)共享庫(kù)會(huì)產(chǎn)生一個(gè)輕量型的可執(zhí)行文件。因?yàn)樗谶\(yùn)行時(shí)解析引用,所以它會(huì)花費(fèi)更多的執(zhí)行時(shí)間。不過(guò),因?yàn)樵谌粘J褂玫?Linux 系統(tǒng)上絕大多數(shù)的命令是動(dòng)態(tài)鏈接的,并且在現(xiàn)代硬件上,所能節(jié)省的時(shí)間是可以忽略不計(jì)的。對(duì)開發(fā)者和用戶來(lái)說(shuō),它的固有模塊性是一種強(qiáng)大的功能。

在這篇文章中,我描述了如何創(chuàng)建動(dòng)態(tài)庫(kù),并將其鏈接到一個(gè)最終可執(zhí)行文件。在我的下一篇文章中,我將使用相同的源文件代碼來(lái)創(chuàng)建一個(gè)靜態(tài)鏈接的可執(zhí)行文件。

責(zé)任編輯:龐桂玉 來(lái)源: Linux中國(guó)
相關(guān)推薦

2020-06-09 15:35:46

Linux符號(hào)鏈接

2023-02-06 17:49:35

Linux符號(hào)鏈接

2020-04-21 14:21:31

LinuxPython

2018-12-11 11:00:50

Linux字體命令

2021-10-02 10:10:47

LinuxBusyBox命令

2021-10-12 08:43:19

LinuxSambaWindows

2019-01-07 09:50:06

Linuxtarball命令

2019-11-26 16:58:51

Linuxpkgsrc

2019-11-26 09:20:47

LinuxJava

2023-01-17 07:40:59

LinuxAppImage應(yīng)用程序

2022-07-12 13:23:59

靜態(tài)鏈接庫(kù)可執(zhí)行文件C 目標(biāo)文件

2012-05-04 08:24:14

LinuxUnix

2021-08-18 11:19:25

FedoraLinuxJava

2021-09-11 15:41:55

UbuntuDropbox云服務(wù)

2017-03-29 16:18:11

LinuxUbuntuRedmine

2020-04-30 13:50:11

Linux網(wǎng)卡信息

2021-07-12 14:47:16

UbuntuZlib代碼

2022-09-13 08:40:24

AndroidLinux

2017-09-18 10:05:15

WindowsLinux容器

2020-08-24 12:37:54

Linuxxargs命令
點(diǎn)贊
收藏

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