www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 程序喵大人
[導(dǎo)讀]大家平時(shí)使用Linux系統(tǒng)過(guò)程中可能都見過(guò)文件系統(tǒng)里有好多帶版本號(hào)的共享庫(kù),如下: lrwxrwxrwx 1 root root 21 Mar 25 18:33 libDeployPkg.so.0 -> libDeployPkg.so.0.0.0-rw-r--r-- 1 root root 31304 Mar 25 18:33 libDeployPkg.so.0.0.0lrwxrwxrwx 1 root

大家平時(shí)使用Linux系統(tǒng)過(guò)程中可能都見過(guò)文件系統(tǒng)里有好多帶版本號(hào)的共享庫(kù),如下:

lrwxrwxrwx 1 root root 21 Mar 25 18:33 libDeployPkg.so.0 -> libDeployPkg.so.0.0.0-rw-r--r-- 1 root root 31304 Mar 25 18:33 libDeployPkg.so.0.0.0lrwxrwxrwx 1 root root 20 Mar 25 18:33 libguestlib.so.0 -> libguestlib.so.0.0.0-rw-r--r-- 1 root root 26752 Mar 25 18:33 libguestlib.so.0.0.0lrwxrwxrwx 1 root root 16 Mar 25 18:33 libhgfs.so.0 -> libhgfs.so.0.0.0-rw-r--r-- 1 root root 167248 Mar 25 18:33 libhgfs.so.0.0.0lrwxrwxrwx 1 root root 18 Mar 25 18:33 libvgauth.so.0 -> libvgauth.so.0.0.0-rw-r--r-- 1 root root 85144 Mar 25 18:33 libvgauth.so.0.0.0lrwxrwxrwx 1 root root 19 Mar 25 18:33 libvmtools.so.0 -> libvmtools.so.0.0.0-rw-r--r-- 1 root root 631480 Mar 25 18:33 libvmtools.so.0.0.0


大家平時(shí)關(guān)注過(guò)這些共享庫(kù)的版本號(hào)是以什么規(guī)則制定的呢?

以"libname.so.x.y.z"來(lái)說(shuō):

  • 最前面使用"lib"前綴,中間是庫(kù)的名字和后綴".so",后面跟著三個(gè)數(shù)字組成版本號(hào)

  • x為主版本號(hào),表示庫(kù)的重大升級(jí),不同主版本號(hào)的庫(kù)之間是不兼容的,依賴于舊版本號(hào)的程序要修改相應(yīng)的代碼來(lái)適應(yīng)新版本的庫(kù),并重新編譯才可以鏈接新版本庫(kù)運(yùn)行。

  • y為次版本號(hào),表示庫(kù)的增量升級(jí),相對(duì)于舊版本只是增加了一些新的接口,并保持原有的接口符號(hào)不變,完全兼容舊版本的庫(kù),即一個(gè)依賴于舊版本號(hào)的程序可以直接鏈接新版本庫(kù)來(lái)正常運(yùn)行。

  • z為發(fā)布版本號(hào),表示庫(kù)的一些錯(cuò)誤修正、性能優(yōu)化等,不會(huì)增加新的接口,只是在舊版本庫(kù)的基礎(chǔ)上做一些優(yōu)化。

如何創(chuàng)建共享庫(kù)?

首先介紹一些SO-NAME,每一個(gè)共享庫(kù)都有一個(gè)SO-NAME,即共享庫(kù)的文件名去掉次版本號(hào)和發(fā)布版本號(hào),比如"libname.so.x.y.z"的SO_NAME就是"libname.so.x"。在Linux系統(tǒng)中,系統(tǒng)會(huì)為每個(gè)共享庫(kù)在所在的目錄中創(chuàng)建一個(gè)與SO-NAME同名并且指向?qū)嶋H共享庫(kù)的軟鏈接。例如"libc.so.1"會(huì)指向"libc.so.1.2.3",當(dāng)目錄中有"libc.so.1.2.4"時(shí),"libc.so.1"這個(gè)軟鏈就會(huì)指向"libc.so.1.2.4",達(dá)到升級(jí)的目的。那系統(tǒng)是如何更新這個(gè)軟鏈的呢,例如我們經(jīng)常使用apt-get install更新程序時(shí),動(dòng)態(tài)鏈接庫(kù)更換了一個(gè)新的版本,那同時(shí)也需要更新一些軟鏈指向的位置,有一個(gè)程序叫l(wèi)dconfig,每次升級(jí)后執(zhí)行一下ldconfig,就會(huì)自動(dòng)遍歷所有的默認(rèn)共享庫(kù)目錄,更新軟鏈。

如下代碼:

// libc.c#include <stdio.h>
void func(int i) { printf("func %d \n", i);}

在gcc中通過(guò)“-Wl,-soname”參數(shù)告訴鏈接器,用于指定共享庫(kù)的SO-NAME。

gcc -fPIC -shared -Wl,-soname,libc.so.1 -o libc.so.1.2.3 lib.c

再看program.c

// program.c#include <stdio.h>
int main() { func(1); return 0;}

編譯鏈接運(yùn)行:

$ gcc -o ttt program.c ./libc.so.1.2.3$ ./ttt./ttt: error while loading shared libraries: libc.so.1: cannot open shared object file: No such file or directory

上面可見,程序并沒有運(yùn)行成功,因?yàn)闆]有創(chuàng)建SO-NAME的相應(yīng)軟鏈

$ ln -s libc.so.1.2.3 libc.so.1再次運(yùn)行$ ./ttt./ttt: error while loading shared libraries: libc.so.1: cannot open shared object file: No such file or directory

再次運(yùn)行發(fā)現(xiàn)還是沒有運(yùn)行成功,為什么呢?因?yàn)槌绦蜻\(yùn)行時(shí)不知道去哪里找這個(gè)動(dòng)態(tài)鏈接庫(kù),所以需要指定一下查找?guī)斓穆窂剑?br>

$ LD_LIBRARY_PATH=. ./tttfunc 1

運(yùn)行成功。

為什么運(yùn)行"LD_LIBRARY_PATH=."后程序就可以運(yùn)行成功了呢?這里介紹下共享庫(kù)的路徑查找相關(guān)知識(shí)點(diǎn)。

共享庫(kù)系統(tǒng)路徑

一般有三個(gè):

  • /lib:主要存放系統(tǒng)最關(guān)鍵和基礎(chǔ)的共享庫(kù),比如動(dòng)態(tài)鏈接器、C語(yǔ)言運(yùn)行庫(kù)、數(shù)學(xué)庫(kù)等,/bin和/sbin下的程序需要的共享庫(kù)和系統(tǒng)啟動(dòng)需要的庫(kù)一般放在這里。

  • /usr/lib:主要存放一些非系統(tǒng)運(yùn)行時(shí)所需要的關(guān)鍵性的共享庫(kù),一般是用戶開發(fā)過(guò)程中用到的共享庫(kù)。

  • /usr/local/lib:一般存放一些非系統(tǒng)所需要的第三方庫(kù),例如裝一個(gè)Python環(huán)境依賴的庫(kù)都可以放在這里。

總結(jié):/lib和/usr/lib存放一些常用成熟的系統(tǒng)本身需要的庫(kù),/usr/local/lib存放一些非系統(tǒng)所需要的第三方庫(kù)。

簡(jiǎn)單講:/lib是內(nèi)核級(jí)的,/usr/lib是系統(tǒng)級(jí)的:/usr/local/lib是用戶級(jí)的。

兩個(gè)在程序運(yùn)行時(shí)與共享庫(kù)搜索路徑相關(guān)的環(huán)境變量:

  • LD_LIBRARY_PATH:通過(guò)此環(huán)境變量,可以臨時(shí)改變某個(gè)程序的共享庫(kù)查找路徑,而不會(huì)影響系統(tǒng)中的其它程序,LD_LIBRARY_PATH默認(rèn)為空,如果某個(gè)進(jìn)程設(shè)置了此環(huán)境變量,動(dòng)態(tài)鏈接器在查找共享庫(kù)時(shí),會(huì)首先查找LD_LIBRARY_PATH的指定目錄,通過(guò)這個(gè)環(huán)境變量可以測(cè)試新的共享庫(kù),因?yàn)殒溄悠麈溄訒r(shí)會(huì)鏈接最先找到的共享庫(kù)。

  • LD_PRELOAD:與LD_LIBRARY_PATH類似,它比LD_LIBRARY_PATH里面的目錄優(yōu)先級(jí)還高,LD_PRELOAD里面指定的共享庫(kù)和目標(biāo)文件中的全局符號(hào)會(huì)覆蓋后面出現(xiàn)的同名全局符號(hào),使得我們可以很方便的改寫標(biāo)準(zhǔn)庫(kù)里的某個(gè)函數(shù)而不影響其它函數(shù),對(duì)于程序調(diào)試和測(cè)試非常有用。

為什么要extern C?

前面已經(jīng)介紹了共享庫(kù)的版本升級(jí)機(jī)制,在C語(yǔ)言中可能升級(jí)比較方便簡(jiǎn)單,不會(huì)遇到太多問(wèn)題,在C++中就比較繁瑣了,因?yàn)镃++為了支持重載和namespace等,編譯出來(lái)的函數(shù)符號(hào)相對(duì)于函數(shù)名字來(lái)說(shuō)有很多前后綴修飾,而且不同廠家的編譯器或者不同版本的編譯器可能符號(hào)修飾規(guī)則都不同,在更新時(shí)可能也會(huì)因?yàn)檫@種原因?qū)е虏患嫒荩院瘮?shù)導(dǎo)出時(shí)需要使用extern C修飾,讓導(dǎo)出函數(shù)的符號(hào)遵守C語(yǔ)言的規(guī)范。

參考資料

《程序員的自我修養(yǎng):鏈接裝載與庫(kù)》
https://blog.csdn.net/weixin_35695879/article/details/90721384


c++11新特性,所有知識(shí)點(diǎn)都在這了!

你的c++團(tuán)隊(duì)還在禁用異常處理嗎?

JNI編程如何巧妙獲取JNIEnv

Linux 為什么要?jiǎng)討B(tài)鏈接?與靜態(tài)鏈接的區(qū)別是什么?

內(nèi)存對(duì)齊之格式修訂版

c++11新特性之智能指針

gcc a.c 究竟經(jīng)歷了什么?

談?wù)劤绦蜴溄蛹胺侄文切┦?/span>

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉
關(guān)閉