成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Linux 下靜態鏈接和動態鏈接的原理及應用

系統 Linux
我們知道一個.c 文件經過編譯、鏈接最終可以形成一個可執行文件。

我們知道一個.c 文件經過編譯、鏈接最終可以形成一個可執行文件。

鏈接原理

當我們的程序包含多個文件時,那么這些文件是怎么形成一個目標文件的呢?

這就要涉及到鏈接器。

鏈接器的作用就是將多個目標文件鏈接成一個完整、可加載、可執行的目標文件。其輸入是一組可以重定位的目標文件。

鏈接的主要作用有2個:

符號解析:將目標文件內的引用符號和該符號的定義聯系起來。

將符號定義與存儲器的位置聯系起來,修改對這些符號的引用。

目標文件

典型的目標文件有3種形式

  • 可重定位目標文件:這種目標文件后綴通常為.o,這種文件包含已經轉換成機器指令的二進制代碼和數據,但是這種文件還不能直接執行,因為這些指令和數據中往往還引用其他模塊(目標文件)中的符號,這些其他模塊的符號對于本模塊來講還都是未知的,因此這些符號的解析需要鏈接器對這些模塊進行連接,這種操作也稱為“重定位”。
  • 可執行目標文件:這種文件同樣包含二進制代碼和數據,區別就是這些文件已經經過鏈接,因此這些文件是可以直接執行的。
  • 共享目標文件:這是一種特殊類型的可重定位的目標文件,可以在需要它的程序運行過程或者加載時,動態的加載到內存中運行。這種文件的后綴通常為“.so”, 共享目標文件又稱為“動態庫”文件或者“共享庫”文件。

符號解析

符號解析是鏈接的主要任務之一。只有在正確的解析了符號之后才能更改引用符號的位置,從而完成重定位,生成一個可以被機器直接加載執行的的可執行目標文件。每個可重定位目標文件都有一個符號表。在這個符號表中存儲符號。這些符號分為3類:

本模塊中引用其他模塊所定義的全局符號。

本模塊中定義的全局符號。

本模塊中定義和引用的局部符號。

重定位

在符號解析結束后,每個符號的定義位置及大小都是已知的了。重定位操作只需要將這些符號鏈接起來。在該步驟中,鏈接器需要將所有參與鏈接的目標文件合并,并且為每一個符號分配存儲內容的運行時地址。

重定位分為2個步驟進行:

  • 重定位段:該步將所有目標文件中同類型的段合并,生成一個大段。比如,將所有參與鏈接的目標文件的數據段合并,生成一個大的數據段。合并之后,程序中的指令和變量就擁有一個統一并且唯一的運行時地址了。
  • 重定位符號引用:由于目標文件中相同的段已經合并,因此程序中對符號的引用位置就都作廢了。這時鏈接器需要修改這些引用符號的地址,使其指向正確的運行時地址。

程序庫

所謂“程序庫”就是包含了一些通用函數的數據和二進制可執行機器碼的文件。這些文件是目標文件的一種,其不能單獨執行。但是若與其他的可執行程序結合起來就可以執行了。

從鏈接方式上區別,程序庫可分為靜態庫和動態庫(共享庫)兩種:

  • 靜態庫:是在可執行程序運行前就已經加入到執行代碼中,成為執行程序的一部分來執行的。
  • 動態庫:是在執行程序啟動時加載到執行程序中,可以被多個執行程序共享使用。

靜態庫

靜態庫是一些目標代碼的集合。Linux下靜態目標文件一般以.a作為目標文件的后綴。在Linux環境下使用ar命令來創建一個靜態庫。靜態庫的優點就是在生成時已經編譯成可重定位的目標文件,節省了編譯時間,并且在編譯時把代碼復制到可執行代碼段中,這樣可執行程序就可以單獨直接運行,但是缺點也是顯而易見的,就是可執行文件可能會變得很臃腫。

靜態庫的創建

本文以四則運算來創建一個靜態庫,該靜態庫中包含四個函數:加、減、乘、除。

// static_lib.c
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int mul(int a, int b)
{
return a * b;
}
int div(int a, int b)
{
return a / b;
}

生成一個可重定位的目標文件。

# gcc -c static_lib.c

在Linux下使用 ar 命令創建一個靜態庫,或者將目標文件加入到一個已經存在的靜態庫中。其使用方法如下:

ar rcs 靜態庫名 目標文件1 目標文件2 ... 目標文件n

該命令表示將目標文件1~n加入到指定的靜態庫中。若該靜態庫不存在,則創建靜態庫文件,并將庫文件的擴展名命名為.a, 其中rcs這三個參數分別表示:把列表中的目標文件加入到靜態庫中(r);若指定的靜態庫不存在,則創建該庫文件(c);更新靜態庫文件的索引,使之包含新加入的目標文件的內容(s)。

使用生成的 static_lib.o 目標文件創建一個靜態庫 static_lib.a

# ar rcs static_lib.a static_lib.o
查看生成的靜態庫文件
# ls
static_lib.a static_lib.c static_lib.o

靜態庫的使用

創建的靜態庫需要鏈接到應用程序中才能使用,為了方便引用,我們創建一個頭文件,使用時把該頭文件包含到應用程序中。

//static_lib.h
extern int add(int a, int b);
extern int sub(int a, int b);
extern int mul(int a, int b);
extern int div(int a, int b);

編寫應用程序

//test.c#include <stdio.h>
#include "static_lib.h"
int main()
{
int a = 8, b = 4;
printf("the add : %d\n", add(a, b));
printf("the sub : %d\n", sub(a, b));
printf("the mul : %d\n", mul(a, b));
printf("the div : %d\n", div(a, b));
}

編譯

# gcc test.c -o test -L. static_lib.a
或者
#gcc test.c -o test ./static_lib.a運行
# ./test
the add :12
the sub :4
the mul :32
the div :2

動態庫

動態庫又稱為共享庫或者動態鏈接庫。在 Linux 環境下為 so 文件。動態庫是在程序運行時加載的。當一個應用程序裝載了一個動態庫后,其他應用程序仍可以裝載同一個動態庫。這個被多個進程同時使用的動態庫在內存中只有一個副本,因此動態庫易于程序模塊的更新,更新庫并不影響應用程序使用舊的、非向后兼容的版本。

創建動態庫

我們依然使用以四則運算來創建一個動態庫,該動態庫中包含四個函數:加、減、乘、除。

// share_lib.c
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int mul(int a, int b)
{
return a * b;
}
int div(int a, int b)
{
return a / b;
}

Linux 下使用 gcc 創建一個動態庫。由于動態庫可以被多個進程共享加載,所以需要生成位置無關的目標文件。因此需要使用 gcc 編譯器的 -fPIC 選項,該選項用于生成位置無關的代碼。除了使用 -fPIC 選項,還需要使用 -shared 選項,該選項將位置無關的代碼制作為動態庫。

創建動態庫的方法如下:

# gcc -shared -fPIC -o share_lib.so share_lib.c
# ls
share_lib.so share_lib.c

動態庫的使用

為了使應用程序可以正確的引用該庫中的全局符號,需要制作一個包含該動態庫文件中的全局符號聲明的頭文件。

//share_lib.h
extern int add(int a, int b);
extern int sub(int a, int b);
extern int mul(int a, int b);
extern int div(int a, int b);

編寫一個應用程序使用動態庫

//main.c#include <stdio.h>
#include "share_lib.h"
int main()
{
int a = 8, b = 4;
printf("the add : %d\n", add(a, b));
printf("the sub : %d\n", sub(a, b));
printf("the mul : %d\n", mul(a, b));
printf("the div : %d\n", div(a, b));
}

運行

# gcc main.c ./share_lib.so -o main
# ./main
the add :12
the sub :4
the mul :32
the div :2
責任編輯:華軒 來源: 今日頭條
相關推薦

2017-01-15 15:27:51

Linux軟連接和硬鏈接

2019-11-01 11:06:02

Linux操作系統Windows

2022-07-12 13:23:59

靜態鏈接庫可執行文件C 目標文件

2022-06-08 09:56:46

靜態鏈接Linux命令

2011-08-24 10:53:41

LinuxLua靜態

2012-05-04 08:24:14

LinuxUnix

2012-05-08 14:48:23

LinuxUnix動態鏈接庫

2020-06-01 19:00:42

Linux軟鏈接硬鏈接

2009-07-07 20:57:20

LinuxUnix動態鏈接庫

2022-02-28 09:44:09

Linux硬鏈接軟鏈接

2023-11-15 08:27:46

Linux系統

2022-03-21 07:56:25

動態鏈接Linux操作系統

2009-12-23 16:28:13

Linux GCC

2024-10-30 09:50:51

WebGo語言

2024-06-06 08:53:13

動態鏈接庫共享庫

2022-10-21 08:18:54

Linuxln 命令

2022-07-10 21:20:11

C語言Linux

2024-04-26 00:31:24

Java動態鏈接

2018-11-09 10:30:05

Linux硬鏈接軟鏈接

2018-11-09 10:10:09

Linux硬鏈接軟鏈接
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲国产精品久久 | 日韩在线观看网站 | 美日韩免费视频 | 一级毛片黄片 | 久久r免费视频 | 毛片免费视频 | 成人羞羞国产免费视频 | 久久久精 | 亚洲一区二区三区免费在线 | 国产精品一区二区免费 | av网站免费| 激情在线视频 | 国产成人网 | 亚洲a在线视频 | www.操.com| 日本不卡一区二区三区 | 成年免费大片黄在线观看岛国 | 成人午夜精品 | 国产在线一区二区 | 国产精品99久久久久久www | 91久久综合| 波多野结衣一区二区三区 | 免费国产黄网站在线观看视频 | 亚洲美女网站 | 国产 欧美 日韩 一区 | 中文字幕 国产精品 | 夜夜草 | 欧美在线一区二区三区 | 国产高清久久 | 成人深夜福利 | 国产精品一区二区不卡 | 999热精品 | 在线国产视频 | 久久精品国产一区 | 久久精品日产第一区二区三区 | 中文字幕日韩欧美 | 欧美激情精品久久久久久 | 日韩一区二区在线观看视频 | 亚洲天堂av一区 | 在线观看免费av网 | 不卡一区二区三区四区 |