【C】 20_連接過程簡介

  • 問題:工程中的每一個 C 語言源文件被編譯後產生目標文件,這些目標文件如何生成最終的可執行程序呢?

連接器的意義

  • 連接器的主要做用是把各個模塊之間互相引用的部分處理好,使得各個模塊之間可以正確的銜接。

clipboard.png

模塊連接

靜態連接

  • 由連接器在連接時將庫的內容直接加入到可執行文件中

clipboard.png

Linux 下靜態庫的建立和使用

  • 編譯靜態庫源碼: gcc-c lib.c -o lib.o
  • 生成靜態庫文件: ar -q lib.a lib.o
  • 使用靜態庫編譯: gcc main.c lib.a -o main.out

編程實驗: 靜態連接示例

test.c
#include <stdio.h>

extern char* name();
extern int add(int a, int b);

int main()
{
    printf("Name" %s\n", name());
    printf("Result: %d\n", add(2, 3));
    
    return 0;
}
slib.c
char* name()
{
    return "Static Lib";
}

int add(int a, int b)
{
    return a + b;
}
輸出:
Name Static Lib
Result: 5

gcc -c slib.c -o slib.o
ar -q slib.a -o slib.o
gcc test.c slib.a -o test.out

動態連接

  • 可執行程序在運行時才動態加載庫進行連接
  • 庫的內容不會進入可執行程序當中

clipboard.png

stubx : 告訴編譯器動態庫中可以使用的內容編程

Linux 下動態庫的建立和使用

  • 編譯動態庫源碼: gcc -shared dlib.c -o dlib.so
  • 使用動態庫編譯: gcc main.c -ldl -o main.out
  • 關鍵系統調用函數

    • dlopen: 打開動態庫文件
    • dlsym: 查找動態庫中的函數並返回調用地址
    • dlclose: 關閉動態庫文件

編程實驗: 動態連接示例

test.c
#include <stdio.h>
#include <dlfcn.h>

extern char* name();
extern int add(int a, int b);

int main()
{
    void* pdlib = dlopen("./dlib.so", RTLD_LAZY);
    
    char* (*pname)();
    int (*padd)(int, int);
    
    if( pdlib != NULL )
    {
        pname = dlsym(pdlib, "name");
        padd  = dlsym(pdlib, "add");
        
        if( (pname != NULL) && (padd != NULL) )
        {
            printf("Name %s\n", pname());
            printf("Result: %d\n", padd(2, 3));
        }
        
        dlclose(pdlib);
    }
    else
    {
        printf("Cannot open lib ... \n");
    }

    return 0;
}
dlib.c
char* name()
{
    return "Static Lib";
}

int add(int a, int b)
{
    return a + b;
}
輸出:
Name Static Lib
Result: 5

gcc -shared dlib.c -o dlib.so
gcc test.c -ldl -o test.out

小結

  • 連接是指將目標文件最終連接爲可執行文件
  • 根據連接方式的不一樣,連接過程能夠分爲:spa

    • 靜態連接: 將目標文件直接連接進入可執行程序
    • 動態連接: 在程序啓動後才動態加載運行

以上內容參考狄泰軟件學院系列課程,請你們保護原創!code

相關文章
相關標籤/搜索