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

Linux 下靜態(tài)鏈接和動態(tài)鏈接的原理及應(yīng)用

系統(tǒng) Linux
我們知道一個.c 文件經(jīng)過編譯、鏈接最終可以形成一個可執(zhí)行文件。

我們知道一個.c 文件經(jīng)過編譯、鏈接最終可以形成一個可執(zhí)行文件。

鏈接原理

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

這就要涉及到鏈接器。

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

鏈接的主要作用有2個:

符號解析:將目標文件內(nèi)的引用符號和該符號的定義聯(lián)系起來。

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

目標文件

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

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

符號解析

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

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

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

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

重定位

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

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

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

程序庫

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

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

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

靜態(tài)庫

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

靜態(tài)庫的創(chuàng)建

本文以四則運算來創(chuàng)建一個靜態(tài)庫,該靜態(tài)庫中包含四個函數(shù):加、減、乘、除。

// 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 命令創(chuàng)建一個靜態(tài)庫,或者將目標文件加入到一個已經(jīng)存在的靜態(tài)庫中。其使用方法如下:

ar rcs 靜態(tài)庫名 目標文件1 目標文件2 ... 目標文件n

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

使用生成的 static_lib.o 目標文件創(chuàng)建一個靜態(tài)庫 static_lib.a

# ar rcs static_lib.a static_lib.o
查看生成的靜態(tài)庫文件
# ls
static_lib.a static_lib.c static_lib.o

靜態(tài)庫的使用

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

//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);

編寫應(yīng)用程序

//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

動態(tài)庫

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

創(chuàng)建動態(tài)庫

我們依然使用以四則運算來創(chuàng)建一個動態(tài)庫,該動態(tài)庫中包含四個函數(shù):加、減、乘、除。

// 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 創(chuàng)建一個動態(tài)庫。由于動態(tài)庫可以被多個進程共享加載,所以需要生成位置無關(guān)的目標文件。因此需要使用 gcc 編譯器的 -fPIC 選項,該選項用于生成位置無關(guān)的代碼。除了使用 -fPIC 選項,還需要使用 -shared 選項,該選項將位置無關(guān)的代碼制作為動態(tài)庫。

創(chuàng)建動態(tài)庫的方法如下:

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

動態(tài)庫的使用

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

//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);

編寫一個應(yīng)用程序使用動態(tài)庫

//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
責任編輯:華軒 來源: 今日頭條
相關(guān)推薦

2017-01-15 15:27:51

Linux軟連接和硬鏈接

2019-11-01 11:06:02

Linux操作系統(tǒng)Windows

2022-07-12 13:23:59

靜態(tài)鏈接庫可執(zhí)行文件C 目標文件

2022-06-08 09:56:46

靜態(tài)鏈接Linux命令

2011-08-24 10:53:41

LinuxLua靜態(tài)

2012-05-04 08:24:14

LinuxUnix

2012-05-08 14:48:23

LinuxUnix動態(tài)鏈接庫

2020-06-01 19:00:42

Linux軟鏈接硬鏈接

2009-07-07 20:57:20

LinuxUnix動態(tài)鏈接庫

2022-02-28 09:44:09

Linux硬鏈接軟鏈接

2023-11-15 08:27:46

Linux系統(tǒng)

2022-03-21 07:56:25

動態(tài)鏈接Linux操作系統(tǒng)

2009-12-23 16:28:13

Linux GCC

2024-10-30 09:50:51

WebGo語言

2024-06-06 08:53:13

動態(tài)鏈接庫共享庫

2022-10-21 08:18:54

Linuxln 命令

2022-07-10 21:20:11

C語言Linux

2024-04-26 00:31:24

Java動態(tài)鏈接

2018-11-09 10:30:05

Linux硬鏈接軟鏈接

2018-11-09 10:10:09

Linux硬鏈接軟鏈接
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 日韩免费高清视频 | 欧美日韩中文字幕在线 | 欧美成年网站 | 亚洲黄色网址视频 | 欧美精品久久久久久久久老牛影院 | 精品一二三区在线观看 | 在线观看av网站永久 | 99精品一区二区 | 国产精品久久网 | 丝袜美腿一区二区三区 | 亚洲第一av网站 | 国产精品久久久久一区二区三区 | 日韩影院在线 | 色av一区二区三区 | 久久精品—区二区三区 | 日韩三 | 欧美日韩中文字幕在线播放 | 伊人久久精品一区二区三区 | 国产大片黄色 | 韩国电影久久 | 久久97精品 | 日韩视频在线观看中文字幕 | 91精品国产综合久久婷婷香蕉 | 中文字幕欧美一区 | 国产精品一区二区精品 | 在线观看中文视频 | 日韩超碰在线 | 成人一区av偷拍 | 国产欧美性成人精品午夜 | 成人特区| 羞羞视频一区二区 | 91亚洲国产成人精品一区二三 | 日韩一区二区三区在线观看 | 精品视频在线一区 | av一级毛片 | 久久免费小视频 | 三级免费毛片 | 欧美一级片在线看 | 国产 欧美 日韩 一区 | 精品国产一区二区在线 | 91精品国产综合久久久久久 |