當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 嵌入式悅翔園
[導(dǎo)讀]學(xué)習(xí)Linux動(dòng)態(tài)鏈接庫(kù)是一個(gè)繞不開的話題,我們今天就一起來看一下什么是動(dòng)態(tài)鏈接庫(kù)、動(dòng)態(tài)鏈接庫(kù)有什么好處、如何編譯出一個(gè)動(dòng)態(tài)鏈接庫(kù)等幾個(gè)關(guān)于動(dòng)態(tài)鏈接庫(kù)的幾個(gè)基本概念,廢話少說咱們直接開始

前言

學(xué)習(xí)Linux動(dòng)態(tài)鏈接庫(kù)是一個(gè)繞不開的話題,我們今天就一起來看一下什么是動(dòng)態(tài)鏈接庫(kù)、動(dòng)態(tài)鏈接庫(kù)有什么好處、如何編譯出一個(gè)動(dòng)態(tài)鏈接庫(kù)等幾個(gè)關(guān)于動(dòng)態(tài)鏈接庫(kù)的幾個(gè)基本概念,廢話少說咱們直接開始!

鏈接庫(kù)是什么?

當(dāng)使用 C 編程語(yǔ)言編寫一個(gè)應(yīng)用程序時(shí),我們不可能每個(gè)程序都從最底層開始編寫,這樣的話無論是學(xué)習(xí)還是工作,都會(huì)帶來很多的不便,于是庫(kù)就出現(xiàn)了。

我們可以把庫(kù)理解成前輩給我們寫好的可以直接拿來用的、成熟的代碼。本質(zhì)上來所庫(kù)是一種可執(zhí)行的二進(jìn)制文件,可以直接被操作系統(tǒng)載入內(nèi)存執(zhí)行,庫(kù)有兩種:靜態(tài)庫(kù)(.a、.lib)和動(dòng)態(tài)庫(kù)(.so、.dll)。

你的代碼通常有多個(gè)庫(kù)文件,庫(kù)文件是計(jì)算機(jī)中給我們提供的一類函數(shù)、變量或類,我們無需知道他們是具體是怎么實(shí)現(xiàn)的,我們只需要關(guān)心它是怎么使用的,比如需要哪些參數(shù)、實(shí)現(xiàn)什么功能、返回值是什么樣的等等。

本質(zhì)上來說庫(kù)是一種可執(zhí)行代碼的二進(jìn)制形式,可以被操作系統(tǒng)載入內(nèi)存執(zhí)行。

在這里插入圖片描述

靜態(tài)鏈接庫(kù)

靜態(tài)鏈接庫(kù)是指編譯鏈接時(shí),把庫(kù)文件的代碼全部加入到可執(zhí)行文件中,因此生成的文件比較大,但在運(yùn)行時(shí)也就不再需要庫(kù)文件了。其后綴名一般為 .a。

我們需要注意的是靜態(tài)庫(kù)是會(huì)隨著編譯一起被編譯到 .o文件中的,即一旦程序編譯靜態(tài)庫(kù)與匯編生成的目標(biāo)文件一起鏈接為可執(zhí)行文件,那么靜態(tài)庫(kù)必定跟.o文件格式相似,只有這樣才能和目標(biāo)文件成功鏈接。

靜態(tài)鏈接庫(kù)的特點(diǎn)

  • 靜態(tài)庫(kù)對(duì)函數(shù)庫(kù)的鏈接是放在編譯時(shí)期完成的。

  • 程序在運(yùn)行時(shí)與函數(shù)庫(kù)再無瓜葛,移植方便。

  • 浪費(fèi)空間和資源,因?yàn)樗邢嚓P(guān)的目標(biāo)文件與牽涉到的函數(shù)庫(kù)被鏈接合成一個(gè)可執(zhí)行文件。

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

通過上面對(duì)靜態(tài)鏈接庫(kù)的介紹我們其實(shí)對(duì)庫(kù)應(yīng)該已經(jīng)有個(gè)概念了,既然有靜態(tài)鏈接庫(kù)那肯定就存在動(dòng)態(tài)的鏈接庫(kù),那什么是動(dòng)態(tài)鏈接庫(kù)呢?我們一起來看一下!

我們知道靜態(tài)鏈接庫(kù)會(huì)占用很多不必要的資源,那我們就能想到動(dòng)態(tài)鏈接庫(kù)的第一個(gè)特點(diǎn)肯定就是節(jié)省資源。

動(dòng)態(tài)庫(kù)在程序編譯時(shí)并不會(huì)像靜態(tài)鏈接庫(kù)那樣被連接到目標(biāo)代碼中,而是在程序運(yùn)行是才被載入。不同的應(yīng)用程序如果調(diào)用相同的庫(kù),那么在內(nèi)存里只需要有一份該共享庫(kù)的實(shí)例,規(guī)避了空間浪費(fèi)問題。動(dòng)態(tài)庫(kù)在程序運(yùn)行是才被載入,也解決了靜態(tài)庫(kù)對(duì)程序的更新、部署和發(fā)布頁(yè)會(huì)帶來麻煩。用戶只需要更新動(dòng)態(tài)庫(kù)即可,增量更新。

動(dòng)態(tài)庫(kù)一般后綴名為 .so,gcc/g++在編譯時(shí)默認(rèn)使用動(dòng)態(tài)庫(kù)。無論靜態(tài)庫(kù),還是動(dòng)態(tài)庫(kù),都是由 .o文件創(chuàng)建的。

動(dòng)態(tài)庫(kù)的編譯

下面通過一個(gè)例子來介紹如何生成一個(gè)動(dòng)態(tài)庫(kù)。建一個(gè)頭文件:dynamic.h三個(gè).cpp文件:dynamic_a.cpp、dynamic_b.cpp, dynamic_c.cpp我們將這幾個(gè)文件編譯成一個(gè)動(dòng)態(tài)庫(kù):libdynamic.so。

dynamic.h

#ifndef __DYNAMIC_H_ #define __DYNAMIC_H_ #include  void dynamic_a(); void dynamic_b(); void dynamic_c(); #endif 

dynamic_a.cpp

#include"dynamic.h" void dynamic_a() { cout<<"this is in dynamic_a "<<endl;
}

dynamic_b.cpp

#include"dynamic.h" void dynamic_b() { cout<<"this is in dynamic_b "<<endl;
}

dynamic_c.cpp

#include"dynamic.h" void dynamic_c() { cout<<"this is in dynamic_c "<<endl;
}

將這幾個(gè)文件編譯成動(dòng)態(tài)庫(kù)libdynamic.so。編譯命令如下:

g++ dynamic_a.cpp dynamic_b.cpp dynamic_c.cpp -fPIC -shared -o libdynamic.so

參數(shù)說明:-shared:該選項(xiàng)指定生成動(dòng)態(tài)連接庫(kù)-fPIC:表示編譯為位置獨(dú)立的代碼,不用此選項(xiàng)的話編譯后的代碼是位置相關(guān)的,所以動(dòng)態(tài)載入時(shí)是通過代碼拷貝的方式來滿足不同進(jìn)程的需要,而不能達(dá)到真正代碼段共享的目的。

在上面的部分,我們已經(jīng)生成了一個(gè)libdynamic.so的動(dòng)態(tài)鏈接庫(kù),現(xiàn)在我們用一個(gè)程序來調(diào)用這個(gè)動(dòng)態(tài)鏈接庫(kù)。

main.cpp

#include"dynamic.h" int main() {
  dynamic_c();
  dynamic_c();
  dynamic_c(); return 0;
}

main.cpp與libdynamic.so鏈接成一個(gè)可執(zhí)行文件main,命令如下:

g++ main.cpp -L. -ldynamic -o main

參數(shù)說明:-L:表示要連接的庫(kù)在當(dāng)前目錄中-ldynamic:編譯器查找動(dòng)態(tài)連接庫(kù)時(shí)有隱含的命名規(guī)則,即在給出的名字前面加上lib,后面加上.so來確定庫(kù)的名稱。

測(cè)試可執(zhí)行程序main是否已經(jīng)鏈接的動(dòng)態(tài)庫(kù)libdynamic.so,如果列出了libdynamic.so,那么就說明正常鏈接了??梢詧?zhí)行以下命令:

ldd main

如果運(yùn)行:

./main

出現(xiàn)錯(cuò)誤:

error while loading shared libraries: libdynamic.so: cannot open shared object file: No such file or directory

錯(cuò)誤原因:

ld提示找不到庫(kù)文件,而庫(kù)文件就在當(dāng)前目錄中。

鏈接器ld默認(rèn)的目錄是/lib和/usr/lib,如果放在其他路徑也可以,需要讓ld知道庫(kù)文件在哪里。

解決方法1:

編輯/etc/ld.so.conf文件,在新的一行中加入庫(kù)文件所在目錄;比如筆者應(yīng)添加:/home/neu/code/Dynamic_library

sudo ldconfig

目的是用ldconfig加載,以更新/etc/ld.so.cache文件。

靜態(tài)庫(kù)的編譯

就以以上代碼演示,最好把生成的動(dòng)態(tài)庫(kù)的東西全部刪掉。

編譯靜態(tài)庫(kù)

g++ -c dynamic_a.cpp dynamic_b.cpp dynamic_c.cpp

使用ar命令創(chuàng)建靜態(tài)庫(kù)文件(把目標(biāo)文檔歸檔)

ar cr libstatic.a dynamic_a.o dynamic_b.o dynamic_c.o  //cr標(biāo)志告訴ar將object文件封裝(archive)

參數(shù)說明:

d 從指定的靜態(tài)庫(kù)文件中刪除文件 
  m 把文件移動(dòng)到指定的靜態(tài)庫(kù)文件中 
  p 把靜態(tài)庫(kù)文件中指定的文件輸出到標(biāo)準(zhǔn)輸出 
  q 快速地把文件追加到靜態(tài)庫(kù)文件中 
  r 把文件插入到靜態(tài)庫(kù)文件中 
  t 顯示靜態(tài)庫(kù)文件中文件的列表 
  x 從靜態(tài)庫(kù)文件中提取文件 
  a 把新的目標(biāo)文件(*.o)添加到靜態(tài)庫(kù)文件中現(xiàn)有文件之后

使用nm -s 命令來查看.a文件的內(nèi)容

nm -s libstatic.a

鏈接靜態(tài)庫(kù)

g++ main.cpp -lstatic -L. -static -o main//這里的-static選項(xiàng)是告訴編譯器,hello是靜態(tài)庫(kù)也可以用 //g++ main.cpp -lstatic -L.  -o main  

執(zhí)行以下命令,因?yàn)楣P者還是用的動(dòng)態(tài)庫(kù)的代碼,所以結(jié)果一樣

./main

動(dòng)態(tài)鏈接庫(kù)的優(yōu)點(diǎn)

  • 節(jié)省資源;
  • 可以實(shí)現(xiàn)進(jìn)程間資源共享;
  • 更新、部署、發(fā)布簡(jiǎn)單;
  • 可以控制動(dòng)態(tài)庫(kù)的加載時(shí)間(何時(shí)加載);

關(guān)于第二點(diǎn)我們?cè)撊绾卫斫饽兀窟M(jìn)程間的資源共享就是說,某個(gè)程序的在運(yùn)行中要調(diào)用某個(gè)動(dòng)態(tài)鏈接庫(kù)函數(shù)的時(shí)候,操作系統(tǒng)首先會(huì)查看所有正在運(yùn)行的程序,看在內(nèi)存里是否已有此庫(kù)函數(shù)的拷貝了。如果有,則讓其共享那一個(gè)拷貝,只有沒有才鏈接載入。

這樣的模式雖然會(huì)帶來一些 “動(dòng)態(tài)鏈接” 額外的開銷,卻大大的節(jié)省了系統(tǒng)的內(nèi)存資源。C的標(biāo)準(zhǔn)庫(kù)就是動(dòng)態(tài)鏈接庫(kù),也就是說系統(tǒng)中所有運(yùn)行的程序共享著同一個(gè)C標(biāo)準(zhǔn)庫(kù)的代碼段。

結(jié)語(yǔ)

我們?cè)诰帉懗绦虻臅r(shí)候,可以根據(jù)需求選擇什么時(shí)候或者什么情況下,鏈接載入哪個(gè)動(dòng)態(tài)鏈接庫(kù)函數(shù)。你可以有一個(gè)相當(dāng)大的軟件,但每次運(yùn)行的時(shí)候,由于不同的操作需求,只有一小部分程序被載入內(nèi)存。

所有的函數(shù)本著 “有需求才調(diào)入” 的原則,于是大大節(jié)省了系統(tǒng)資源。比如現(xiàn)在的軟件通常都能打開若干種不同類型的文件,這些讀寫操作通常都用動(dòng)態(tài)鏈接庫(kù)來實(shí)現(xiàn)。

在一次運(yùn)行當(dāng)中,一般只有一種類型的文件將會(huì)被打開。所以直到程序知道文件的類型以后再載入相應(yīng)的讀寫函數(shù),而不是一開始就將所有的讀寫函數(shù)都載入,然后才發(fā)覺在整個(gè)程序中根本沒有用到它們。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉