靜態(tài)庫(kù)、動(dòng)態(tài)庫(kù)編譯原理

編譯過程

預(yù)處理 -> 編譯 -> 匯編 -> 鏈接

預(yù)處理

  1. 完成宏替換、文件引入,去除空行、注釋等。
  2. 針對(duì)預(yù)處理命令進(jìn)行處理,頭文件包含、宏定義擴(kuò)展、條件編譯的選擇等。
# test.c
#include <stdio.h> 
int main(){
    printf("hello world!\n");
    return 0;
}
------------------------------------------------
$ gcc -E test.c -o test.i
  • -E: 讓gcc在預(yù)處理結(jié)束后停止編譯,test.i文件為預(yù)處理后的文件
  • -o: 指定輸出文件

編譯

這里的編譯不是指程序從源文件到二進(jìn)制程序的全部過程,而是指將經(jīng)過預(yù)處理之后的程序轉(zhuǎn)換成特定匯編代碼(assembly code)的過程。

$ gcc -S test.i -o test.s

匯編

將上一步的匯編代碼轉(zhuǎn)換成機(jī)器碼(machine code),這一步產(chǎn)生的文件叫做目標(biāo)文件,是二進(jìn)制格式。

$ gcc -c test.s -o test.o

鏈接

鏈接過程將多個(gè)目標(biāo)文以及所需的庫(kù)文件(.so等)鏈接成最終的可執(zhí)行文件

$ gcc test.o -o test
$ ./test

更詳細(xì)的內(nèi)容可以參考:https://www.cnblogs.com/CarpenterLee/p/5994681.html#top

生成靜態(tài)庫(kù)

  • 首先生成test.o目標(biāo)文件
  • 使用ar命令將test.o打包成libtest.a靜態(tài)庫(kù)
# 首先生成目標(biāo)文件
$ gcc -c test.c -o test.o
# 使用ar命令將目標(biāo)文件打包成靜態(tài)庫(kù)
$ ar rcs libtest.a test.o
# 使用ar t libtest.a 查看靜態(tài)庫(kù)內(nèi)容
$ ar t libtest.a
test.o

生成動(dòng)態(tài)庫(kù)

  • 首先生成test.o目標(biāo)文件。
  • 使用-shared和-fPIC參數(shù)生成動(dòng)態(tài)庫(kù)
# 首先生成目標(biāo)文件
$ gcc -c test.c
# 使用-fPIC和-shared生成動(dòng)態(tài)庫(kù)
$ gcc -shared -fPIC -o libtest.so test.o

例子

tool.h

int find_max(int arr[], int n);

tool.c

#include "tool.h"

int find_max(int arr[], int n){
    int max = arr[0];
    int i;
    for(i = 0; i < n; i++){
        if(arr[i] > max){
            max = arr[i];
        }
    }
    return max;
}

main.c

#include <stdio.h>
#include "tool.h"
int main(){
    int arr[] = {1,3,5,8,2};
    int max = find_max(arr, 5);
    printf(" max = %d\n", max);
    return 0;
}

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

  • 編譯目標(biāo)文件 $ gcc -c tool.c,省略-o默認(rèn)生成同名文件
  • 編譯靜態(tài)庫(kù)文件 ar rcs libtool.a tool.o
  • 編譯可執(zhí)行文件&鏈接靜態(tài)庫(kù) gcc -o main main.c -L. -ltool
    -L: 查詢庫(kù)路徑
    -l: 需要鏈接的庫(kù)
  • 執(zhí)行 ./main

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

$ gcc -shared -fPIC -o libtool.so tool.c
$ gcc -o main -L. -ltool main.c
$ ./main

ps

  • 靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)同名時(shí),系統(tǒng)會(huì)優(yōu)先鏈接動(dòng)態(tài)庫(kù)。
  • 查看文件詳情ls -lh
  • 查看鏈接庫(kù)詳情
    linuxldd main
    macOx 動(dòng)態(tài)庫(kù):otool -L main ,靜態(tài)庫(kù) nm main

靜態(tài)庫(kù)與動(dòng)態(tài)庫(kù)區(qū)別

  • 靜態(tài)庫(kù)在程序編譯時(shí)會(huì)鏈接到目標(biāo)代碼中,程序運(yùn)行時(shí)不在需要靜態(tài)庫(kù),因此體積較大。每次編譯都需要載入靜態(tài)代碼,因此內(nèi)存開銷大。
  • 動(dòng)態(tài)庫(kù)在程序編譯時(shí)不會(huì)被鏈接到目標(biāo)代碼中,而是在程序運(yùn)行時(shí)才被載入,程序運(yùn)行時(shí)需要?jiǎng)討B(tài)庫(kù)存在,因此體積較小。而且系統(tǒng)只需載入一次動(dòng)態(tài)庫(kù),不同程序可以得到內(nèi)存中相同的動(dòng)態(tài)庫(kù)副本,因此內(nèi)存開銷小。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容