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

當(dāng)前位置:首頁 > 公眾號精選 > 程序喵大人
[導(dǎo)讀]大家平時使用Linux系統(tǒng)過程中可能都見過文件系統(tǒng)里有好多帶版本號的共享庫,如下: 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

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

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


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

以"libname.so.x.y.z"來說:

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

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

  • y為次版本號,表示庫的增量升級,相對于舊版本只是增加了一些新的接口,并保持原有的接口符號不變,完全兼容舊版本的庫,即一個依賴于舊版本號的程序可以直接鏈接新版本庫來正常運行。

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

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

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

如下代碼:

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

在gcc中通過“-Wl,-soname”參數(shù)告訴鏈接器,用于指定共享庫的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;}

編譯鏈接運行:

$ 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

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

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

再次運行發(fā)現(xiàn)還是沒有運行成功,為什么呢?因為程序運行時不知道去哪里找這個動態(tài)鏈接庫,所以需要指定一下查找?guī)斓穆窂剑?br>

$ LD_LIBRARY_PATH=. ./tttfunc 1

運行成功。

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

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

一般有三個:

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

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

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

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

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

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

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

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

為什么要extern C?

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

參考資料

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


c++11新特性,所有知識點都在這了!

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

JNI編程如何巧妙獲取JNIEnv

Linux 為什么要動態(tài)鏈接?與靜態(tài)鏈接的區(qū)別是什么?

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

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

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

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

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

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