Linux動態(tài)庫與靜態(tài)庫-創(chuàng)新互聯(lián)

Linux動態(tài)庫與靜態(tài)庫

十載的平橋網(wǎng)站建設經(jīng)驗,針對設計、前端、開發(fā)、售后、文案、推廣等六對一服務,響應快,48小時及時工作處理。成都全網(wǎng)營銷的優(yōu)勢是能夠根據(jù)用戶設備顯示端的尺寸不同,自動調整平橋建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設計,從而大程度地提升瀏覽體驗。創(chuàng)新互聯(lián)公司從事“平橋網(wǎng)站設計”,“平橋網(wǎng)站推廣”以來,每個客戶項目都認真落實執(zhí)行。文章目錄
  • Linux動態(tài)庫與靜態(tài)庫
    • 1.庫的概念、種類與使用
    • 2.鏈接簡述
      • 2.1 鏈接過程理解
      • 2.2 靜態(tài)鏈接與動態(tài)鏈接概念
      • 2.3 靜態(tài)鏈接與動態(tài)鏈接的例子
    • 3.動態(tài)庫與靜態(tài)庫的生成方法
      • 3.1 靜態(tài)庫的生成
      • 3.2 靜態(tài)庫的打包
      • 3.2 靜態(tài)庫的使用
      • 3.3 動態(tài)庫的生成
      • 3.4 動態(tài)庫的打包
      • 3.5 動態(tài)庫的使用

1.庫的概念、種類與使用

庫的概念:一組.o文件的集合,或者說.obj文件(windows下)的集合,也就是鏈接生成可執(zhí)行文件時用到的文件

請?zhí)砑訄D片描述

在我的理解里,庫就是別人寫的代碼,比如庫函數(shù),第三方庫,包括之后會用到的網(wǎng)絡庫,這些都是別人寫的,我們只是拿過來使用而已

那為什么我們要使用別人的代碼呢?

因為:為了開發(fā)效率和代碼的健壯性

那我們要如何使用別人的庫?

  • 借助庫、開源代碼、和網(wǎng)絡。下面我們主要了解庫的使用
  • 如果別人要用我們的功能,我們又不想給源碼,就可以把源碼打包成一個庫給對方用

庫的種類:

鏈接分為動態(tài)鏈接和靜態(tài)鏈接,庫分為動態(tài)庫和靜態(tài)庫。靜態(tài)鏈接是一個過程,這個過程中用到的庫就是靜態(tài)庫,動態(tài)鏈接同理

使用三方庫時的鏈接過程:
請?zhí)砑訄D片描述


2.鏈接簡述 2.1 鏈接過程理解

鏈接過程簡單概括為地址和空間分配,符號解析和代碼重定位

符號指的是變量,函數(shù)名等,符號解析則是將符號的定義和符號的引用建立聯(lián)系

重定位我簡單理解為可以準確的運行我們的程序,比如一個函數(shù),我們可以精準的找到函數(shù)入口的地址并進行運行

符號解析后生成符號表,linux下查看符號表命令:readelf -s 文件名.o

請?zhí)砑訄D片描述

代碼的重定位:我們運行的指令都有其對應的地址,比如我們進入一個函數(shù)就是跳到一個表示函數(shù)入口的地址,代碼變化指令也會跟著變化,地址自然就變化了,比如前面一開始有4條代碼,修改后有5條,那對應的指令和地址可能都要發(fā)生變化,函數(shù)入口就變化了,此時的代碼里重新計算地址的過程就叫做重定位。如果有多個模塊,成千上萬行代碼,修改這個地址的工作就是龐大的,早期還是人工改,現(xiàn)在都交給鏈接器了


2.2 靜態(tài)鏈接與動態(tài)鏈接概念

靜態(tài)鏈接概念:

  • 靜態(tài)鏈接:是指編譯階段把靜態(tài)庫的代碼加入到可執(zhí)行文件中,或者說把用到的函數(shù)的全部鏈接到可執(zhí)行文件中(但是鏈接器是以文件為單位進行操作的,比如要用printf就得鏈接所有包含printf的文件)。這樣生成的可執(zhí)行文件不需要借助外部的庫,生成后可以直接使用,這就是靜態(tài)鏈接。缺點是文件比較大,每次更新都得重新編譯,優(yōu)點是運行較快
  • 簡言之:把需要的代碼和數(shù)據(jù)從庫全拷貝到當前代碼

動態(tài)鏈接概念:

  • 動態(tài)鏈接:是什么時候要用到庫里的東西就什么時候去找,存的也只是索引和相關的部分信息,所以占用空間不大。好處是占用空間小,所有的程序可以共用同一個庫,更新也比較方便,缺點就是比較慢。如果我們有及時上百個進程都用了同一個庫,那相比靜態(tài)鏈接就大大節(jié)省了空間
  • 簡言之:動態(tài)庫可以被多個進程共享,與進程地址空間里的共享區(qū)有關

2.3 靜態(tài)鏈接與動態(tài)鏈接的例子

gcc -o 命令默認動態(tài)鏈接,加上-static選項就表示靜態(tài)鏈接,可通過file命令查看鏈接屬性

#includeint main()
{int a=1;
  printf("%d\n",a);
  return 0;
}

請?zhí)砑訄D片描述

ldd命令,查看程序或者庫文件所依賴的共享庫,即打印動態(tài)鏈接依賴的庫列表

下圖中:libc.so.6,把lib和so去掉,中間剩下的c就是庫名,.so就表示動態(tài)庫,.a表示靜態(tài)庫,.6是主版本號

請?zhí)砑訄D片描述

對于靜態(tài)鏈接與動態(tài)鏈接的總結:

  1. 靜態(tài)鏈接會拷貝代碼和數(shù)據(jù),再將其鏈接進可執(zhí)行文件,因為鏈接器的操作單元又是文件,所以靜態(tài)的鏈接的文件一般都較大,優(yōu)點是快(不用去庫里找東西自然快),不需要依賴外部(庫丟失了也能跑)。但是不好更新,每次更新都得重新編譯,比如包含了這個庫里的某個函數(shù)的文件就全得更新
  2. 動態(tài)鏈接就是啥時候要就啥時候找,鏈接器看到動態(tài)鏈接的符號也會去找,只不過不分配地址,重定位的操作等到了程序裝載時才做。但因為是通過索引去找,所以多個進程可以共享一個庫(庫丟失就跑不了了),一些場景下可以大大節(jié)省空間資源,更新時也方便,只用編譯相對應的模塊

3.動態(tài)庫與靜態(tài)庫的生成方法

下面的動靜態(tài)庫生成剖析通過下面四個函數(shù)來驗證:

add.h

#pragma once 
int add(int x,int y);

add.c

#include"add.h"
int add(int x,int y)
{return x+y;
}

sub.h

#pragma once 
int sub(int x,int y);

sub.c

#include"sub.h"
int sub(int x,int y)
{return x-y;
}

3.1 靜態(tài)庫的生成

下面以一個例子說明生成靜態(tài)庫的操作,我們利用ar工具把兩個C文件打包成一個靜態(tài)庫。靜態(tài)庫里放.o文件,可以做到不暴露源碼,再建一個目錄放頭文件,告訴使用者里面有哪些方法可以用
請?zhí)砑訄D片描述


3.2 靜態(tài)庫的打包

靜態(tài)庫的打包過程:

關于ar命令的補充:

ar命令是gnu的歸檔工具,常用于將目標文件打包為靜態(tài)庫,下面我們使用ar命令的-r選項和-c選項進行打包

  • -r(replace):若靜態(tài)庫文件當中的目標文件有更新,則用新的目標文件替換舊的目標文件
  • -c(create):建立靜態(tài)庫文件
  • -t:列出靜態(tài)庫中的文件
  • -v(verbose):顯示詳細的信息

打包流程:

  1. 第一步:讓所有源文件生成對應的目標文件,即gcc -c add.c -o add.o等操作
  2. 第二步:使用ar命令將所有目標文件打包為靜態(tài)庫,即ar -rc …等操作
  3. 第三步:將頭文件和生成的靜態(tài)庫組織起來,即cp add.h sub.h …等操作
  4. 第四步(可有可無):編寫Makefile后,只需一個make就能生成所有源文件對應的目標文件進而生成靜態(tài)庫

請?zhí)砑訄D片描述

生成的靜態(tài)庫名為libmymath.a.1,后面的1表示版本號,建議我們自己打包庫的時候去掉版本號,不然后面使用的時候會顯示找不到庫…(也不知道為啥會找不到,網(wǎng)上查閱資料后發(fā)現(xiàn)靜態(tài)庫一般都把版本號寫在文件里,再通過strings+文件里添加字符串version來標識文件是哪個版本,也有利用命令行參數(shù)來打印版本號的)


3.2 靜態(tài)庫的使用
gcc -o main main.c  -I ./include -L ./lib -lmymath -static
//-I指定去哪找頭文件,-L指定去哪找?guī)煳募?l+庫名表示去找哪個庫
//因為默認路徑的緣故,gcc編譯C代碼都不用加-I -L -l等選項

請?zhí)砑訄D片描述


3.3 動態(tài)庫的生成

多個進程可以共享一個多態(tài)庫,如下圖:

請?zhí)砑訄D片描述

動態(tài)庫上面提到是要的時候再去找,所以多個進程用動態(tài)庫時用的都是同一份代碼,合理的節(jié)省了資源

請?zhí)砑訄D片描述

-fPIC作用于編譯時期,產(chǎn)生與位置無關的代碼,編譯后的代碼用的是相對地址

用相對地址的原因共享庫加載進內存的位置是不確定的,如果不加-fPIC選項,可能生成帶有絕對位置的代碼,那鏈接器鏈接時可能就需要去重新定位各個符號的位置,那共享庫的代碼可能就發(fā)生了變化,我們的程序此時就要去維護這段發(fā)生了變化的代碼,維護進行的操作就是拷貝一份,那動態(tài)鏈接的作用就不大了(動態(tài)鏈接本來是要用的時候直接用庫里的,現(xiàn)在我程序自身要維護一份更改后的代碼,顯然是不合理的),所以與位置無關的代碼其實就是使用了相對地址的代碼,這么做與elf文件的格式有關(借助了elf文件里面的“段”)。可以簡單理解為規(guī)定了一根線,關于地址的坐標都是相對于這根線的,不管我程序加載到內存的哪個位置,只要通過計算這根線到當前位置的距離就可以獲取到(算出)正確的位置。真正清晰的理解需要了解elf文件的格式,編譯原理、鏈接器的相關知識

請?zhí)砑訄D片描述


3.4 動態(tài)庫的打包

動態(tài)庫的打包相對于靜態(tài)庫來說有一點點差別,但大致相同,我們還是利用上面的四個文件進行打包演示:

動態(tài)庫的打包流程:

第一步:讓所有源文件生成對應的目標文件

  • 此時用源文件生成目標文件時需要攜帶-fPIC選項

  • -fPIC(position independent code):產(chǎn)生位置無關碼

請?zhí)砑訄D片描述

說明一下:

  • -fPIC作用于編譯階段,告訴編譯器產(chǎn)生與位置無關的代碼,此時產(chǎn)生的代碼中沒有絕對地址,全部都使用相對地址,從而代碼可以被加載器加載到內存的任意位置都可以正確的執(zhí)行。這正是共享庫所要求的,共享庫被加載時,在內存的位置不是固定的
  • 如果不加-fPIC選項,則加載.so文件的代碼段時,代碼段引用的數(shù)據(jù)對象需要重定位,重定位會修改代碼段的內容,這就造成每個使用這個.so文件代碼段的進程在內核里都會生成這個.so文件代碼段的拷貝,并且每個拷貝都不一樣,取決于這個.so文件代碼段和數(shù)據(jù)段內存映射的位置
  • 不加-fPIC編譯出來的.so是要在加載時根據(jù)加載到的位置再次重定位的,因為它里面的代碼BBS位置無關代碼。如果該.so文件被多個應用程序共同使用,那么它們必須每個程序維護一份.so的代碼副本(因為.so被每個程序加載的位置都不同,顯然這些重定位后的代碼也不同,當然不能共享)
  • 我們總是用-fPIC來生成.so,但從來不用-fPIC來生成.a。但是.so一樣可以不用-fPIC選項進行編譯,只是這樣的.so必須要在加載到用戶程序的地址空間時重定向所有表目

第二步:使用-shared選項將所有目標文件打包為動態(tài)庫

  • 與生成靜態(tài)庫不同的是,生成動態(tài)庫時我們不必使用ar命令,我們只需使用gcc的-shared選項即可
gcc -shared -o libcal.so add.o sub.o

請?zhí)砑訄D片描述


第三步:將頭文件和生成的動態(tài)庫組織起來

  • 與生成靜態(tài)庫時一樣,為了方便別人使用,在這里我們可以將add.hsub.h這兩個頭文件放到一個名為include的目錄下,將生成的動態(tài)庫文件libcal.so放到一個名為lib的目錄下,然后將這兩個目錄都放到mlib下,此時就可以將mlib給別人使用了

請?zhí)砑訄D片描述


第四步:使用Makefile

  • 當然,生成動態(tài)庫也可以將上述所要執(zhí)行的命令全部寫到Makefile當中,后續(xù)當我們要生成動態(tài)庫以及組織頭文件和庫文件時就可以一步到位了

請?zhí)砑訄D片描述

  • 編寫Makefile后,只需一個make就能生成所有源文件對應的目標文件進而生成動態(tài)庫

請?zhí)砑訄D片描述

  • 一個make output就能將頭文件和動態(tài)庫組織起來

請?zhí)砑訄D片描述


3.5 動態(tài)庫的使用

我們使用下面main.c的代碼作為例子:

//main.c
#include#include"add.h"
#include"sub.h"
int main()
{int a=add(0,1);
  printf("%d\n",a);

  return 0;
}

請?zhí)砑訄D片描述
請?zhí)砑訄D片描述
請?zhí)砑訄D片描述

你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧

網(wǎng)頁標題:Linux動態(tài)庫與靜態(tài)庫-創(chuàng)新互聯(lián)
標題網(wǎng)址:http://muchs.cn/article12/dsgpdc.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供域名注冊、定制開發(fā)、網(wǎng)站收錄、全網(wǎng)營銷推廣、用戶體驗、網(wǎng)站設計

廣告

聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站建設