欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Linux動(dòng)靜態(tài)庫(kù)的制作與使用

 更新時(shí)間:2024年05月15日 10:07:11   作者:春人.  
這篇文章主要介紹了Linux動(dòng)靜態(tài)庫(kù)的制作與使用,文中通過(guò)代碼示例和圖文結(jié)合的方式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或共組哦有一定的幫助,需要的朋友可以參考下

一、靜態(tài)庫(kù)

對(duì)于我們自己寫的一份源代碼,別人如果想使用,可以有以下兩種做法:第一種就是將我們的源代碼直接給別人拷貝一份,但是如果你覺(jué)得自己的代碼寫的非常厲害,不想讓別人知道,或者別人嫌拷貝太麻煩了,那么就需要采用第二種做法;第二種做法就是,將我們自己寫的源代嘛想辦法打包成庫(kù),然后將這個(gè)庫(kù)和對(duì)應(yīng)的頭文件提供給使用者。注意,頭文件是必不可少的,頭文件就相當(dāng)于該庫(kù)中方法的使用說(shuō)明書,如果不提供頭文件,別人大概率是不知道該庫(kù)是如何使用的。

1.1 靜態(tài)庫(kù)的制作

// 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;
}
// mul.h
#pragma once

int mul(int x, int y);
// mul.c
#include "mul.h"

int mul(int x, int y)
{
    return x * y;
}
// div.h
#pragma once

extern int myerrno; // 聲明一個(gè)可以被其它源文件使用的變量

int div(int x, int y);
// div.c
#include "div.h"

int myerrno = 0; // 定義

int div(int x, int y)
{
    if(y == 0) 
    {
        myerrno = -1;
        return myerrno;
    }
    return x / y;
}

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

靜態(tài)庫(kù)的生成指令:

在這里插入圖片描述

靜態(tài)庫(kù)本質(zhì)上就是對(duì) .o 文件進(jìn)行打包,所以首先要將 .c 文件編譯成 .o 文件,然后進(jìn)行打包。ar 是 gnu 歸檔工具,可以使用它來(lái)生成一個(gè)靜態(tài)庫(kù),它執(zhí)行的工作就是把一個(gè)或者多個(gè) .o 文件打包,生成一個(gè) .a 庫(kù)文件。-rc 表示 replace and creat,.a 庫(kù)文件中如果有待打包的 .o 文件就替換,沒(méi)有就創(chuàng)建。

靜態(tài)庫(kù)生成示意圖:

在這里插入圖片描述

1.3 靜態(tài)庫(kù)的發(fā)布

發(fā)布庫(kù):

在這里插入圖片描述

在這里插入圖片描述

發(fā)布庫(kù)就是把 lib 目錄拷貝給別人。

1.4 靜態(tài)庫(kù)的使用

首先創(chuàng)建一個(gè) test 目錄,先講上面發(fā)布的 lib 目錄拷貝到 test 目錄中,然后在 test 目錄中創(chuàng)建一個(gè) main.c 進(jìn)行測(cè)試。目錄結(jié)構(gòu)如下圖所示:

在這里插入圖片描述

// main.c
#include "add.h"
#include "sub.h"
#include "mul.h"
#include "div.h"
#include <stdio.h>

int main()
{
    printf("1 + 2 = %d\n", add(1, 2));
    printf("1 - 2 = %d\n", sub(1, 2));
    printf("1 * 2 = %d\n", mul(1, 2));
    printf("1 / 2 = %d\n", div(1, 2));
    return 0;
}

在這里插入圖片描述

編譯 main.c 時(shí)報(bào)錯(cuò),說(shuō)找不到對(duì)應(yīng)的頭文件。此時(shí)就需要再來(lái)認(rèn)識(shí)一下包含頭文件的兩種方式了。在使用庫(kù)中的頭時(shí),一般用 <> 來(lái)包含頭文件,<> 表示到系統(tǒng)指定目錄下去查找頭文件。在使用自己寫的頭文件時(shí),一般使用 "",表示在當(dāng)前源文件的統(tǒng)計(jì)目錄下查找頭文件,找打了就用,沒(méi)找到再去系統(tǒng)指定目錄下進(jìn)行查找,所以對(duì)于庫(kù)提供的頭文件我們也可以使用 "" 進(jìn)行包含。但是上面代碼中我們使用的就是 "",并且 add.h 就在 lib/include 目錄下,lib 目錄和 main.c 同處 test 目錄下,為什么會(huì)報(bào)錯(cuò)呢?因?yàn)橛?"" 包含的頭文件,會(huì)告訴編譯器在 main.c 的同級(jí)目錄下進(jìn)行查找,也就是在 test 目錄下進(jìn)行查找,并不會(huì)深入到 test 中的 lib 目錄去查找。

在這里插入圖片描述

解決上面報(bào)錯(cuò)的方法有三種。第一種,將我們發(fā)布的 lib 庫(kù)中的頭文件拷貝到系統(tǒng)的指定路徑下;第二種,在代碼中補(bǔ)全路徑,如 #include "/lib/include/add.h";第三種,在執(zhí)行 gcc 指令編譯的時(shí)候加上 -I 選項(xiàng),指定編譯器搜索頭文件的路徑。

第三種解決方案示意圖:

在這里插入圖片描述

此時(shí)編譯仍然沒(méi)有成功,但是沒(méi)有報(bào)頭文件找不到的錯(cuò)誤了?,F(xiàn)在是鏈接出錯(cuò),可以編譯形成 .o 文件,如下圖所示:

在這里插入圖片描述

鏈接報(bào)錯(cuò)還是因?yàn)?gcc 在進(jìn)行編譯鏈接的時(shí)候,只會(huì)去默認(rèn)路徑下查找打包形成的庫(kù)文件,不會(huì)去我們的 lib/mymathlib 目錄下查找,這樣就導(dǎo)致 gcc 編譯器找不到我們打包的庫(kù) libmymath.a ,最終鏈接時(shí)就會(huì)報(bào)錯(cuò)。

在這里插入圖片描述

解決鏈接有兩種方法。方法一:將我們的庫(kù)拷貝到系統(tǒng)的指定路徑下,并不能完全解決,還需要指定庫(kù)的名稱,下面會(huì)講;方法二:在使用 gcc 的時(shí)候添加對(duì)應(yīng)的選項(xiàng)。方法二示意圖,如下所示:

在這里插入圖片描述

其中 -L 選項(xiàng)指定了庫(kù)的搜索路徑,-l 選項(xiàng)指定了待搜索的庫(kù)的名稱。 為什么在搜索頭文件的時(shí)候僅需指定路徑呢?因?yàn)樵诖a中已經(jīng)寫了頭文件的具體名稱,所以僅需指定頭文件的路徑即可。而一個(gè)路徑下可以有多個(gè)庫(kù),如果只指定路勁,編譯器還是不知道該去鏈接哪個(gè)庫(kù),因此還要在后面使用 -l 選項(xiàng)指定待鏈接的庫(kù)的具體名稱,注意:去掉前綴 lib 和 后綴 .a 才是一個(gè)庫(kù)的名稱,建議 -l 后面緊跟庫(kù)的名稱。一般在使用第三方庫(kù)的時(shí)候,可能不需要帶 -I 或者 -L,但是 -l 指定庫(kù)的名稱是一定需要到,因?yàn)?gcc 默認(rèn)只能找到系統(tǒng)調(diào)用和語(yǔ)言層面的庫(kù)。

小Tips:在動(dòng)態(tài)庫(kù)和靜態(tài)庫(kù)都有的情況下,gcc 默認(rèn)鏈接動(dòng)態(tài)庫(kù),如果系統(tǒng)中只提供靜態(tài)庫(kù),gcc 則只能對(duì)該庫(kù)進(jìn)行靜態(tài)鏈接。如果有需要,gcc 可以鏈接多個(gè)庫(kù)。

1.5 靜態(tài)庫(kù)的安裝

在這里插入圖片描述

庫(kù)的安裝本質(zhì)上就是把頭文件和庫(kù)文件拷貝到系統(tǒng)的特定目錄下。還可以通過(guò)在指定目錄下創(chuàng)建軟鏈接的方式,如下圖所示:

在這里插入圖片描述

小Tips:此時(shí)包含頭文件前面應(yīng)該加上軟鏈接的名字,如:#include <myinc/add.h> 這種形式。

二、動(dòng)態(tài)庫(kù)

2.1 動(dòng)態(tài)庫(kù)的制作

// myprintf.h
#pragma once

#include <stdio.h>

void Print();
// myprintf.c
#include "myprintf.h"

void Print()
{
    printf("Hello Linux\n");
}
// mylog.h
#pragma once

#include <stdio.h>

void Log(const char* info);
// mylog.c
#include "mylog.h"

void Log(const char* info)
{
    printf("log: %s\n", info);
}

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

在這里插入圖片描述

小Tips:在編譯生成 .o 文件的時(shí)候,要加上 -fPIC 選項(xiàng),該選項(xiàng)表示產(chǎn)生位置無(wú)關(guān)碼(position independent code)。將 .o 文件打包生成動(dòng)態(tài)庫(kù),繼續(xù)使用 gcc,需要帶 -shared 選項(xiàng),表示生成共享庫(kù)格式。其次需要注意動(dòng)態(tài)庫(kù)的命名規(guī)則是 libxxx.so。動(dòng)態(tài)庫(kù)是可執(zhí)行程序的一種,將來(lái)是需要被加載到內(nèi)存的,因此它帶了 x 選項(xiàng),而靜態(tài)庫(kù)的使用本質(zhì)是把靜態(tài)庫(kù)中的二進(jìn)制代碼拷貝一份去使用,靜態(tài)庫(kù)是不需要被加載到內(nèi)存的,因此靜態(tài)庫(kù)沒(méi)有可執(zhí)行權(quán)限。

2.3 動(dòng)態(tài)庫(kù)的發(fā)布

dy-lib=libmymethod.so
static-lib=libmymath.a
.PHONY:all
all:$(dy-lib) $(static-lib)

$(static-lib):add.o sub.o mul.o div.o
		ar -rc $@ add.o sub.o mul.o div.o

$(dy-lib):myprintf.o mylog.o
		gcc -shared -o $@ $^

myprintf.o:myprintf.c
		gcc -fPIC -c $^
mylog.o:mylog.c
		gcc -fPIC -c $^
add.o:add.c
		gcc -c $^
sub.0:sub.c
		gcc -c $^
mul.o:mul.c
		gcc -c $^
div.o:div.c
		gcc -c $^
.PHONY:clean
clean:
		rm -rf *.o *.a mylib *.so
.PHONY:output
output:
		mkdir -p mylib/include
		mkdir -p mylib/lib
		cp *.h mylib/include
		cp *.a mylib/lib
		cp *.so mylib/lib

在這里插入圖片描述

小Tips:上面不是單純的發(fā)布動(dòng)態(tài)庫(kù),而是將動(dòng)靜態(tài)庫(kù)同時(shí)發(fā)布。

2.4 動(dòng)態(tài)庫(kù)的使用

#include "myprintf.h"
#include "mylog.h"
#include <stdio.h>

int main()
{
    Print();
    Log("Hello log function!");
    return 0;
}

在這里插入圖片描述

上圖中按照靜態(tài)庫(kù)的使用方法去使用動(dòng)態(tài)庫(kù),可以成功生成可執(zhí)行文件,但是可執(zhí)行文件在運(yùn)行的時(shí)候出錯(cuò)了。

在這里插入圖片描述

在使用 ldd 查看可執(zhí)行程序運(yùn)行所需的共享庫(kù)時(shí)發(fā)現(xiàn),libmymethod.so 后面指向 not found。為什么會(huì)這樣呢?我們?cè)谑褂?gcc 進(jìn)行編譯的時(shí)候,不是已經(jīng)通過(guò) -L-l 選項(xiàng)告訴編譯器動(dòng)態(tài)庫(kù)所在的路徑和名字,為什么還是找不到呢?原因正如前面所述,我們僅僅是告訴了編譯器所需的動(dòng)態(tài)庫(kù)在哪里,而可執(zhí)行程序運(yùn)行靠的是加載器,上面的 not found 表示加載器不知道動(dòng)態(tài)庫(kù)在哪里。這也從側(cè)面印證了靜態(tài)庫(kù)是不會(huì)加載到內(nèi)存中的,所以使用靜態(tài)庫(kù)只需要告訴編譯器靜態(tài)庫(kù)在哪里即可。

解決該問(wèn)題的方法有四種。第一種,將庫(kù)文件拷貝到系統(tǒng)默認(rèn)的庫(kù)路徑(/lib64、/usr/lib64);第二種,在系統(tǒng)默認(rèn)的庫(kù)路徑(/lib64、/usr/lib64)下建立軟鏈接;第三種,將自己庫(kù)所在的路徑,添加到系統(tǒng)的環(huán)境變量 LD_LIBRARY_PATH 中,該環(huán)境變量就是專門用來(lái)搜索動(dòng)態(tài)庫(kù)的;第四種,如果想讓我們的庫(kù)和系統(tǒng)、語(yǔ)言自帶的庫(kù)一樣,在程序運(yùn)行的時(shí)候可以自動(dòng)被找到,那我們可以在 /etc/ld.so.conf.d 路徑下添加一個(gè) .conf 結(jié)尾的配置文件,該配置文件里面的內(nèi)容就是我們自己動(dòng)態(tài)庫(kù)所在的路徑。添加完后執(zhí)行 ldconfig 指令,將所有的配置文件重現(xiàn)加載一下,然后程序就能夠正常運(yùn)行啦。

在這里插入圖片描述

在這里插入圖片描述

小Tips:這樣添加,當(dāng)系統(tǒng)重啟后新添加的境變量就沒(méi)有了,如果想讓系統(tǒng)啟動(dòng)時(shí)自動(dòng)添加該路徑到 LD_LIBRARY_PATH 環(huán)境變量中,可以通過(guò)修改 ~/.bash_profile 中的配置去實(shí)現(xiàn),具體如下圖所示:

在這里插入圖片描述

在這里插入圖片描述

小Tips:加載器是不需要知道庫(kù)的名字的,只需要知道庫(kù)的路徑即可。

2.5 動(dòng)態(tài)庫(kù)是如何被加載和共享的?

動(dòng)態(tài)庫(kù)在進(jìn)程運(yùn)行的時(shí)候是需要被加載到內(nèi)存的,常見(jiàn)的動(dòng)態(tài)庫(kù)被所有的可執(zhí)行程序(動(dòng)態(tài)鏈接的),都要使用,因此,動(dòng)態(tài)庫(kù)在系統(tǒng)中加載之后,會(huì)被所有進(jìn)程共享。

在這里插入圖片描述

首先我們需要知道,一個(gè)進(jìn)程可以鏈接多個(gè)動(dòng)態(tài)庫(kù),同理,當(dāng)系統(tǒng)中存在多個(gè)進(jìn)程的時(shí)候,那么此時(shí)系統(tǒng)中一定是存在多個(gè)動(dòng)態(tài)庫(kù)的。操作系統(tǒng)一定會(huì)通過(guò)“先描述,再組織”的方式將系統(tǒng)中所有的動(dòng)態(tài)庫(kù)管理起來(lái)。所以對(duì)操作系統(tǒng)而言,所有庫(kù)的加載情況,它非常清楚。A.exe 在編譯鏈接的時(shí)候采用的是動(dòng)態(tài)庫(kù),A 進(jìn)程在運(yùn)行的時(shí)候,CPU 按照從上往下的順序執(zhí)行代碼,遇到了一個(gè)庫(kù)函數(shù),假設(shè)就為 printf,此時(shí)操作系統(tǒng)發(fā)現(xiàn) printf 所在的動(dòng)態(tài)庫(kù)并沒(méi)有被加載到內(nèi)存中,因此就會(huì)將這個(gè)動(dòng)態(tài)庫(kù)加載到內(nèi)存,因?yàn)閯?dòng)態(tài)庫(kù)也是文件,也有 inode,所以這本質(zhì)上就是文件的加載,將動(dòng)態(tài)庫(kù)加載到內(nèi)存之后,操作系統(tǒng)會(huì)在 A 進(jìn)程的頁(yè)表上建立該動(dòng)態(tài)庫(kù)與 A 進(jìn)程地址空間中共享區(qū)的映射關(guān)系,然后 CPU 就又代碼段跳轉(zhuǎn)到共享區(qū)去執(zhí)行動(dòng)態(tài)庫(kù)中關(guān)于 printf 的代碼,執(zhí)行完后跳轉(zhuǎn)會(huì)代碼段繼續(xù)執(zhí)行后續(xù)代碼。與此同時(shí),B.exe 經(jīng)過(guò)編譯鏈接(用動(dòng)態(tài)庫(kù)),然后被加載到內(nèi)存,成為 B 進(jìn)程,CPU 在執(zhí)行 B 進(jìn)程代碼的時(shí)候,也遇到了 printf 函數(shù),此時(shí)因?yàn)樵?A 進(jìn)程執(zhí)行的時(shí)候,就把 printf 所在的動(dòng)態(tài)庫(kù)加載到了內(nèi)存,所以此時(shí)操作系統(tǒng)并不會(huì)再去把這個(gè)動(dòng)態(tài)庫(kù)加載一遍,而是直接在 B 進(jìn)程的頁(yè)表中建立映射關(guān)系。此時(shí)一個(gè)動(dòng)態(tài)庫(kù)被加載到內(nèi)存中,就同時(shí)被兩個(gè)進(jìn)程所使用,因此動(dòng)態(tài)庫(kù)也被叫做共享庫(kù)。

一個(gè)問(wèn)題:現(xiàn)在我們知道了動(dòng)態(tài)庫(kù)是可以被多個(gè)進(jìn)程共享的。那動(dòng)態(tài)庫(kù)中的全局變量例如 errno 該怎么辦?我們知道,errno 是 C 語(yǔ)言為我們提供的一個(gè)錯(cuò)誤碼,一般在調(diào)用庫(kù)函數(shù)失敗的時(shí)候,該錯(cuò)誤碼會(huì)被設(shè)置,那動(dòng)態(tài)庫(kù)是被共享的,豈不意味著 errno 也可能是被多個(gè)進(jìn)程共享的,那在 A 進(jìn)程中執(zhí)行庫(kù)函數(shù)失敗,假設(shè) errno 被設(shè)置成 1,在 B 進(jìn)程中 errno 也是 1 嘛?這顯然是不合理的。實(shí)際上,當(dāng)要修改 errno 的時(shí)候,操作系統(tǒng)會(huì)通過(guò)引用計(jì)數(shù)去判斷該動(dòng)態(tài)庫(kù)是否被多個(gè)進(jìn)程共享,如果該庫(kù)被多個(gè)進(jìn)程共享,操作系統(tǒng)會(huì)發(fā)生寫時(shí)拷貝。

三、再來(lái)認(rèn)識(shí)地址

3.1 邏輯地址的引入

一個(gè) .c 源文件在被編譯成為 .exe 可執(zhí)行程序的時(shí)候,會(huì)加上地址??梢赃@樣來(lái)理解,一個(gè) .c 源文件首先會(huì)編譯成為匯編文件,將我們的 C 語(yǔ)言轉(zhuǎn)化成一條條匯編指令,接著會(huì)把匯編指令轉(zhuǎn)化成機(jī)器碼,對(duì)應(yīng)的匯編文件和機(jī)器碼文件其實(shí)都已經(jīng)加上了地址,最終 .exe 中也是包含地址的。.exe 文件本質(zhì)上就是由各種段構(gòu)成的,現(xiàn)如今的 .exe 文件中的編址都采用平坦模式,即 .exe 文件已經(jīng)按照程序地址空間的格式進(jìn)行分段編址。

3.2 CPU 是如何知道指令位置的

上面說(shuō)過(guò),可執(zhí)行程序內(nèi)部是有邏輯地址的,在可執(zhí)行程序加載到內(nèi)存之后,每一條指令還會(huì)有自己對(duì)應(yīng)的物理地址,因?yàn)槲锢韮?nèi)存它本身就是有地址的,無(wú)論可執(zhí)行程序是否加載到內(nèi)存中。此時(shí)可執(zhí)行程序已經(jīng)被加載到了內(nèi)存,CPU 是如何知道該可執(zhí)行程序的第一條指令在哪兒的呢?在編譯形成可執(zhí)行程序的時(shí)候,除了形成代碼段、數(shù)據(jù)段、.bss 段外,還會(huì)形成一個(gè)文件頭,這里面就存儲(chǔ)了可執(zhí)行程序的入口地址,這個(gè)地址是邏輯地址(虛擬地址)。在 CPU 中有一個(gè)寄存器,一般管它叫做 PC 指針,它里面存儲(chǔ)的就是接下來(lái)要執(zhí)行指令的地址。實(shí)際上,最初并不急著把可執(zhí)行程序全部加載到內(nèi)存,只需要將可執(zhí)行文件的頭部加載到內(nèi)存即可,CPU 通過(guò)頭部獲取到可執(zhí)行程序的入口地址,然后拿著該地址去查頁(yè)表,發(fā)現(xiàn)并沒(méi)有建立內(nèi)存映射,此時(shí)操作系統(tǒng)會(huì)發(fā)生缺頁(yè)中斷,將對(duì)應(yīng)的程序加載到內(nèi)存,接下來(lái)就好辦了,CPU 通過(guò)內(nèi)置的指令集,先天就知道每條指令的長(zhǎng)度,然后他會(huì)按順序往后執(zhí)行,遇到函數(shù)調(diào)用指令,或者一些跳轉(zhuǎn)指令,也是根據(jù)虛擬地址去頁(yè)表中查找映射關(guān)系,發(fā)生缺頁(yè)中斷。因此可以得出一結(jié)論,CPU 是通過(guò)虛擬地址轉(zhuǎn)物理地址去執(zhí)行可執(zhí)行程序中的指令,訪問(wèn)可執(zhí)行程序中的變量。

3.3 一個(gè)庫(kù)函數(shù)是如何被找到并且執(zhí)行的

結(jié)合上面兩點(diǎn),可以得出,可執(zhí)行程序內(nèi)部有邏輯地址,CPU 是通過(guò)虛擬地址轉(zhuǎn)物理地址去執(zhí)行指令的。那一個(gè)可執(zhí)行程序是如何加載并使用動(dòng)態(tài)庫(kù)的呢?以程序中調(diào)用 printf 函數(shù)為例,按照上面兩小節(jié)的說(shuō)法,在可執(zhí)行程序中,printf 函數(shù)有一個(gè)固定的邏輯地址,假設(shè)為 0x11223344,而 CPU 是通過(guò)虛擬地址查找物理地址去執(zhí)行指令,即通過(guò) 0x11223344 這個(gè)虛擬地址去映射找到物理地址,然后執(zhí)行 printf 函數(shù),那是否意味著,在程序地址空間角度,動(dòng)態(tài)庫(kù)需要被加載到動(dòng)態(tài)區(qū)的固定位置,這樣才能保證 printf 函數(shù)的地址是 0x11223344。如果按照上面兩小節(jié)說(shuō)的,對(duì)于一個(gè)進(jìn)程來(lái)說(shuō),動(dòng)態(tài)庫(kù)是必須加載到固定的位置,但是這幾乎是不可能的,因?yàn)橐粋€(gè)可執(zhí)行程序可能同時(shí)使用多個(gè)庫(kù),每個(gè)庫(kù)的大小不一,并且每個(gè)庫(kù)中都獨(dú)立編址,可能該進(jìn)程還使用了 B 庫(kù)中的某個(gè)函數(shù),該函數(shù)在 B 庫(kù)中為編址也是 0x11223344。所以很難做到將一個(gè)動(dòng)態(tài)庫(kù)加載到固定位置。因此我們需要想辦法讓庫(kù)可以在虛擬內(nèi)存中共享區(qū)的任意位置進(jìn)行加載,實(shí)現(xiàn)方法是,在動(dòng)態(tài)庫(kù)內(nèi)部,不采用絕對(duì)編址,而是采用相對(duì)編址,對(duì)于動(dòng)態(tài)庫(kù)中的函數(shù)只需要知道其在庫(kù)中的偏移量即可0x11223344 就不再表示 printf 的絕對(duì)地址,而是它相對(duì)于這個(gè)庫(kù)起始位置的偏移量,此時(shí)就可以實(shí)現(xiàn)把庫(kù)加載到虛擬內(nèi)存共享區(qū)的任意位置。之后,操作系統(tǒng)只需要記住每一個(gè)庫(kù)在虛擬內(nèi)存中的起始地址即可,當(dāng)要執(zhí)行某個(gè)庫(kù)函數(shù)的時(shí)候,只需要用該函數(shù)所在庫(kù)的起始地址加上該函數(shù)的相對(duì)地址(也就是偏移量),就可以知道該函數(shù)在程序地址空間中的虛擬地址,然后再拿著這個(gè)虛擬地址去查頁(yè)表,找到該函數(shù)在物理內(nèi)存中的地址,然后執(zhí)行庫(kù)函數(shù)。-fPIC 選項(xiàng),就是讓編譯器在形成動(dòng)態(tài)庫(kù)文件的時(shí)候,直接用偏移量對(duì)庫(kù)中的函數(shù)進(jìn)行編址。靜態(tài)庫(kù)是直接拷貝到可執(zhí)行程序中的,無(wú)需加載到物理內(nèi)存中,因此靜態(tài)庫(kù)中的函數(shù)就被當(dāng)做了我們自己寫的函數(shù)一樣,直接采用絕對(duì)編址。

四、結(jié)語(yǔ)

以上就是Linux動(dòng)靜態(tài)庫(kù)的制作與使用的詳細(xì)內(nèi)容,更多關(guān)于Linux動(dòng)靜態(tài)庫(kù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 一步步教你如何編寫Shell腳本

    一步步教你如何編寫Shell腳本

    這篇文章主要介紹了關(guān)于如何編寫Shell腳本的相關(guān)資料,文中介紹的非常詳細(xì),對(duì)大家具有一定的參考價(jià)值,需要的朋友下面跟著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-04-04
  • 關(guān)于Apache shiro實(shí)現(xiàn)一個(gè)賬戶同一時(shí)刻只有一個(gè)人登錄(shiro 單點(diǎn)登錄)

    關(guān)于Apache shiro實(shí)現(xiàn)一個(gè)賬戶同一時(shí)刻只有一個(gè)人登錄(shiro 單點(diǎn)登錄)

    今天和同事在一起探討shiro如何實(shí)現(xiàn)一個(gè)賬戶同一時(shí)刻只有一session存在的問(wèn)題,下面小編把核心代碼分享到腳本之家平臺(tái),需要的朋友參考下
    2017-09-09
  • linux 清理內(nèi)存命令詳細(xì)介紹

    linux 清理內(nèi)存命令詳細(xì)介紹

    這篇文章主要介紹了linux 清理內(nèi)存命令詳細(xì)介紹的相關(guān)資料,這里對(duì)Linux 清理內(nèi)存進(jìn)行了詳解及查看內(nèi)存條命令,需要的朋友可以參考下
    2016-11-11
  • apache虛擬主機(jī)中設(shè)置泛域名解析的方法

    apache虛擬主機(jī)中設(shè)置泛域名解析的方法

    apache虛擬主機(jī)中設(shè)置泛域名解析,主要是用到ServerAlias 的配置,供大家學(xué)習(xí)參考
    2013-02-02
  • Centos7.4服務(wù)器安裝apache及安裝過(guò)程出現(xiàn)的問(wèn)題解決方法

    Centos7.4服務(wù)器安裝apache及安裝過(guò)程出現(xiàn)的問(wèn)題解決方法

    這篇文章主要介紹了Centos7.4服務(wù)器安裝apache及安裝過(guò)程出現(xiàn)的問(wèn)題解決方法,結(jié)合實(shí)例形式分析了Centos7.4服務(wù)器安裝apache相關(guān)命令、配置操作及端口占用等常見(jiàn)問(wèn)題解決方法,需要的朋友可以參考下
    2019-03-03
  • 如何為CentOS 7配置靜態(tài)IP地址的兩種方法

    如何為CentOS 7配置靜態(tài)IP地址的兩種方法

    本篇文章主要介紹了如何為CentOS 7配置靜態(tài)IP地址的幾種方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-02-02
  • LNMP服務(wù)器環(huán)境配置 (linux+nginx+mysql+php)

    LNMP服務(wù)器環(huán)境配置 (linux+nginx+mysql+php)

    在高并發(fā)連接的情況下,Nginx是Apache服務(wù)器不錯(cuò)的替代品。Nginx同時(shí)也可以作為7層負(fù)載均衡服務(wù)器來(lái)使用。Nginx 0.8.46 + PHP 5.2.14 (FastCGI) 可以承受3萬(wàn)以上的并發(fā)連接數(shù),相當(dāng)于同等環(huán)境下Apache的10倍
    2014-07-07
  • Linux命令 sort、uniq、tr工具詳解

    Linux命令 sort、uniq、tr工具詳解

    這篇文章主要介紹了Linux命令 sort、uniq、tr工具詳解,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • linux環(huán)境openssl、openssh升級(jí)流程

    linux環(huán)境openssl、openssh升級(jí)流程

    該文章詳細(xì)介紹了在Ubuntu 22.04系統(tǒng)上升級(jí)OpenSSL和OpenSSH的方法,首先,升級(jí)OpenSSL的步驟包括下載最新版本、安裝編譯環(huán)境、備份和安裝、驗(yàn)證等,然后,升級(jí)OpenSSH的步驟包括下載最新版本、安裝相關(guān)依賴、解壓和編譯安裝、查看版本、備份替換文件、重啟服務(wù)等
    2025-03-03
  • Apache 文件上傳與文件下載案例詳解

    Apache 文件上傳與文件下載案例詳解

    寫一個(gè)Apache文件上傳與文件下載的案例以供今后學(xué)習(xí),非常不錯(cuò),具有參考借鑒價(jià)值,需要的的朋友參考下吧
    2017-07-07

最新評(píng)論