linux載入庫
⑴ 如何讓linux載入當前目錄的動態庫
linux 載入當前目錄的動態庫的方法是:設置合適的環境變數LD_LIBRARY_PATH。
設置方法有以下三種:
1、臨時修改,log out之後就失效
在terminal中執行:export LD_LIBRARY_PATH=./
2、讓當前帳號以後都優先載入當前目錄的動態庫
修改~/.bash_profile在文件末尾加上兩行: LD_LIBRARY_PATH=./ 和 export LD_LIBRARY_PATH
3、讓所有帳號從此都優先載入當前目錄的動態庫
修改/etc/profile在文件末尾加上兩行: LD_LIBRARY_PATH=./ 和 export LD_LIBRARY_PATH
⑵ Linux下C/C++動態庫在運行時是怎樣載入進來的
在linux上,你在ps中說的那種"將動態庫作為一個參數傳到程序里"的使用方式,是通過dlopen函數將.so載入到當前進程中,並且通過ld.so將.so"鏈接"進當前進程。這個"鏈接"過程包括:查找未定義符號在當前進程中的地址、分配數據/代碼/bss段內存(數據初始化全局變數、代碼段重定位)、執行constructor函數等。之後,可以使用dlsym在已知符號名的情況下通過符號名查找符號對應的地址。這個符號可以是一個全局變數、全局函數等。在你說的C++中,重載的函數也可以理解為全局函數,會有一個屬性為weak的符號。該符號的符號名如果不做修改,默認按照System V的C++ API命名規范命名(以保證linux下不同編譯器編譯出來的.so和.o可以通用)。但如果使用extern "C"修飾之後,變成C的函數名,則無名稱修飾,便於使用。
作者:yin jie
鏈接:https://www.hu.com/question/29988788/answer/46352593
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請註明出處。
⑶ linux下的動態庫是如何在程序運行時載入
直接上代碼,祈禱排版不要亂掉,一下源碼來自http://lameck.blog.163.com/blog/static/388113742011111591750149/
//test.h
#ifndef_TEST_H_
#define_TEST_H_
typedefint(*TEST_FUN)(void);
#endif
//test.cgcc-ctest.c-otest.o
//gcc-sharedtest.o-olibtest.so
#include<stdio.h>
#include"test.h"
inttest_fun(void)
{
printf("thisisatest! ");
return0;
}
//main.cgccmain.c-omain-ldl
#include<stdio.h>
#include<stdlib.h>
#include<dlfcn.h>
#include"test.h"
intmain()
{
void*handle=NULL;
TEST_FUNp=NULL;
char*error=NULL;
handle=dlopen("./libtest.so",RTLD_LAZY);
if((error=dlerror())!=NULL)
{
printf("%s ",error);
exit(1);
}
p=(TEST_FUN)dlsym(handle,"test_fun");
if((error=dlerror())!=NULL)
{
printf("%s ",error);
dlclose(handle);
exit(1);
}
p();
dlclose(handle);
return0;
}
主要函數
void * dlopen( const char *pathname, intmode);
void* dlsym(void* handle,const char* symbol);
const char *dlerror(void);
int dlclose (void *handle);
這些基本上可以從函數簽名中得到實際功能和使用方法..
除了mode參數,其他的想必能夠通過閱讀源代碼來學習吧
關於dlopen的mode參數有如下幾個常量:
1、解析方式
RTLD_LAZY:在dlopen返回前,對於動態庫中的未定義的符號不執行解析(只對函數引用有效,對於變數引用總是立即解析)。
RTLD_NOW: 需要在dlopen返回前,解析出所有未定義符號,如果解析不出來,在dlopen會返回NULL,錯誤為:: undefined symbol: xxxx.......
2、作用范圍
RTLD_GLOBAL:動態庫中定義的符號可被其後打開的其它庫重定位。
RTLD_LOCAL: 與RTLD_GLOBAL作用相反,動態庫中定義的符號不能被其後打開的其它庫重定位。如果沒有指明是RTLD_GLOBAL還是RTLD_LOCAL,則預設為RTLD_LOCAL。
3、作用方式
RTLD_NODELETE: 在dlclose()期間不卸載庫,並且在以後使用dlopen()重新載入庫時不初始化庫中的靜態變數。這個flag不是POSIX-2001標准。
RTLD_NOLOAD: 不載入庫。可用於測試庫是否已載入(dlopen()返回NULL說明未載入,否則說明已載入),也可用於改變已載入庫的flag,如:先前載入庫的flag為RTLD_LOCAL,用dlopen(RTLD_NOLOAD|RTLD_GLOBAL)後flag將變成RTLD_GLOBAL。這個flag不是POSIX-2001標准。
RTLD_DEEPBIND:在搜索全局符號前先搜索庫內的符號,避免同名符號的沖突。這個flag不是POSIX-2001標准。
⑷ Linux下的靜態庫和動態庫
linux下的靜態庫和動態庫1.製作自己的動態庫和靜態庫linux下動態庫以.so結尾,靜態庫以.a結尾,它們都以lib開頭,比如一個庫名為net,那麼它的全名應該是libnet.so或者libnet.a。我們有兩個文件,hello.c和test.c,下面是兩個文件的內容//hello.c
www.shiwu.com
#include
<stdio.h>void
my_lib_func(){printf(Library
routine
called/r/n);}//test.c#include
<stdio.h>
www.shiwu.com
int
main(){my_lib_func();return
1;}test.c調用了hello.c的方法,我們把hello.c封裝成庫文件。無論是靜態庫還是動態庫,都是由.o文件組成,我們先把gcc
-c
hello.c生成.o文件製作靜態庫ar
crv
libmyhello.a
hello.o,ar是生成靜態庫的命令,libmyhello.a是我的靜態庫名。下一步就是在我的程序中使用靜態庫
可以看到已經有了Library
routine
called的結果,說明調用成功了。下面我們刪除libmyhello.a,看看程序是否還是運行正常
我們發現程序依然運行正常,說明靜態庫已經連接進入我們的程序中製作動態庫
www.shiwu.com
我們看見動態庫libmyhello.so已經生成,下面繼續使用
找不到庫文件,這個時候我們把so文件拷貝到/usr/lib下面
運行成功2.動態庫和靜態庫同時存在的調用規則我們可以發現,不論是動態庫還是靜態庫,程序編譯連接的時候都是加的參數-l,那麼當他們同時存在的時候,程序會選擇動態庫還是靜態庫呢。我們做個嘗試。
我們同時存在libmyhello.a和libmyhello.so,我們發現運行的時候,出現找不到動態庫的錯誤,由此,我們可以得出結論,同時存在動態庫和靜態庫的時候,gcc會優先選擇動態庫作者
梨樹陽光
⑸ Linux下載入靜態鏈接庫
dll文件,貌似是windows下的動態鏈接庫,屬於pe文件。linux下怎麼可能載入那種東西呢。
⑹ 初步接觸linux,請問gdb調試start後載入動態庫符號時間很長,怎麼解決,可以不載入指定庫符號嗎
方法一、在/etc/ld.so.conf文件中添加路徑,vi /etc/ld.so.conf
添加下邊內容
123
include ld.so.conf.d/*.conf /usr/cluster/.share/lib
方法二、在終端輸入:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/cluster/.share/lib
方法三、修改/etc/profile文件
123
export MPI_HOME=/usr/cluster export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MPI_HOME/.share/lib
在終端執行source /etc/profile 使配置文件生效
程序運行時載入動態庫失敗的解決方法
錯誤提示如下:
error while loading shared libraries: libjson.so.0: cannot open shared object file: No such file or directory
原因一般有兩個,一個是操作系統中沒有包含該共享庫(lib*.so.* 文件)或者共享庫版本不對。解決辦法就是重新下載安裝。
另外一個原因就是已經安裝了該共享庫,但是執行需要調用該共享庫的程序的時候,程序按照默認共享庫路徑找不到該共享庫文件。解決方法如下:
如果共享庫文件安裝到了 /lib 或 /usr/lib 目錄下,那麼執行一下 ldconfig 命令。
ldconfig命令的用途, 主要是在默認搜尋目錄(b和/usrb)以及動態庫配置文件/etc/ld.so.conf內所列的目錄下, 搜索出可共享的動態鏈接庫(格式如lib*.so*), 進而創建出動態裝入程序(ld.so)所需的連接和緩存文件. 緩存文件默認為/etc/ld.so.cache, 此文件保存已排好序的動態鏈接庫名字列表.
如果共享庫文件安裝到了 /usr/local/lib (一般開源的共享庫都會安裝到該目錄下)或者其它非 /lib 或 /usr/lib 目錄下,那麼在執行 ldconfig 命令前,還要把新的共享庫目錄加入到共享庫配置文件 /etc/ld.so.conf 中,如下:
1234
# cat /etc/ld.so.confinclude ld.so.conf.d/*.conf# echo "/usr/local/lib" >> /etc/ld.so.conf# ldconfig
或者在 /etc/ld.so.conf.d/ 目錄下新建任何以 .conf 為後綴的文件,在該文件中加入庫文件所在的目錄。然後執行 ldconfig 更新 /etc/ld.so.cache 文件。
如果共享庫文件安裝到了其他非 /lib 或 /usr/lib 目錄下,但是又不想在 /etc/ld.so.conf 文件中加共享庫路徑(或者是沒有許可權加路徑)。那可以 export 一個全局變數 LD_LIBRARY_PATH,然後運行程序的時候就會去找個目錄中找共享庫。
LD_LIBRARY_PATH的意思是告訴loader在哪些目錄中可以找到共享庫. 可以設置多個搜索目錄, 這些目錄之間用冒號分隔開. 比如安裝了一個mysql到/usr/local/mysql目錄下, 其中有一大堆庫文件在/usr/local/mysql/lib下面, 則可以在.bashrc或.bash_profile或shell里加入以下語句即可:
export LD_LIBRARY_PATH=/usr/local/mysql/lib:$LD_LIBRARY_PATH
一般來講這只是一種臨時的解決方案, 在沒有許可權或臨時需要的時候使用.
如果程序需要的庫文件比系統目前存在的庫文件版本低,可以做一個鏈接。比如:
12345
error while loading shared libraries: libncurses.so.4: cannot open sharedobject file: No such file or directoryls /usr/lib/libncu*/usr/lib/libncurses.a /usr/lib/libncurses.so.5/usr/lib/libncurses.so /usr/lib/libncurses.so.5.3
可見雖然沒有libncurses.so.4,但有libncurses.so.5,是可以向下兼容的
建一個鏈接就好了
1
ln -s /usr/lib/libncurses.so.5.3 /usr/lib/libncurses.so.4
⑺ 查看linux當前載入庫文件的命令
ldd
<可執行文件名>
查看可執行文件鏈接了哪些
系統動態鏈接庫
nm
<可執行文件名>
查看可執行文件裡面有哪些符號
strip
<可執行文件名>
去除符號表可以給可執行文件瘦身
如果我們想從可執行程序裡面提取出來一點什麼文本信息的話,還可以用strings命令
strings
<可執行文件名>
Linux操作系統上面的動態共享庫大致分為三類:
1、操作系統級別的共享庫和基礎的系統工具庫
比方說libc.so,
libz.so,
libpthread.so等等,這些系統庫會被放在/lib和/usr/lib目錄下面,如果是64位操作系統,還會有/lib64和/usr
/lib64目錄。如果操作系統帶有圖形界面,那麼還會有/usr/X11R6/lib目錄,如果是64位操作系統,還有/usr/X11R6
/lib64目錄。此外還可能有其他特定Linux版本的系統庫目錄。
這些系統庫文件的完整和版本的正確,確保了Linux上面各種程序能夠正常的運行。
2、應用程序級別的系統共享庫
並非操作系統自帶,但是可能被很多應用程序所共享的庫,一般會被放在/usr/local/lib和/usr/local/lib64這兩個目錄下面。很多你自行編譯安裝的程序都會在編譯的時候自動把/usr/local/lib加入gcc的-L參數,而在運行的時候自動到/usr/local
/lib下面去尋找共享庫。
以上兩類的動態共享庫,應用程序會自動尋找到他們,並不需要你額外的設置和擔心。這是為什麼呢?因為以上這些目錄默認就被加入到動態鏈接程序的搜索路徑裡面了。Linux的系統共享庫搜索路徑定義在/etc/ld.so.conf這個配置文件裡面。這個文件的內容格式大致如下:
/usr/X11R6/lib64
/usr/X11R6/lib
/usr/local/lib
/lib64
/lib
/usr/lib64
/usr/lib
/usr/local/lib64
/usr/local/ImageMagick/lib
假設我們自己編譯安裝的ImageMagick圖形庫在/usr/local/ImageMagick目錄下面,並且希望其他應用程序都可以使用
ImageMagick的動態共享庫,那麼我們只需要把/usr/local/ImageMagick/lib目錄加入/etc/ld.so.conf文件裡面,然後執行:ldconfig
命令即可。
ldcofig將搜索以上所有的目錄,為共享庫建立一個緩存文件/etc/ld.so.cache。為了確認ldconfig已經搜索到ImageMagick的庫,我們可以用上面介紹的strings命令從ld.so.cache裡面抽取文本信息來檢查一下:
strings
/etc/ld.so.cache
|
grep
ImageMagick
輸出結果為:
/usr/local/ImageMagick/lib/libWand.so.10
/usr/local/ImageMagick/lib/libWand.so
/usr/local/ImageMagick/lib/libMagick.so.10
/usr/local/ImageMagick/lib/libMagick.so
/usr/local/ImageMagick/lib/libMagick++.so.10
/usr/local/ImageMagick/lib/libMagick++.so
已經成功了!
3、應用程序獨享的動態共享庫
有很多共享庫只被特定的應用程序使用,那麼就沒有必要加入系統庫路徑,以免應用程序的共享庫之間發生版本沖突。因此Linux還可以通過設置環境變數LD_LIBRARY_PATH來臨時指定應用程序的共享庫搜索路徑,就像我們上面舉的那個例子一樣,我們可以在應用程序的啟動腳本裡面預先設置
LD_LIBRARY_PATH,指定本應用程序附加的共享庫搜索路徑,從而讓應用程序找到它。
⑻ 如何讓linux載入當前目錄的動態庫
讓linux載入當前目錄的動態庫,設置方法有以下三種:
1、臨時修改,log out之後就失效
在terminal中執行:
export LD_LIBRARY_PATH=./
2、讓當前帳號以後都優先載入當前目錄的動態庫
修改~/.bash_profile 在文件末尾加上兩行:
LD_LIBRARY_PATH=./ 和 export LD_LIBRARY_PATH
3、讓所有帳號從此都優先載入當前目錄的動態庫
修改/etc/profile 在文件末尾加上兩行:
LD_LIBRARY_PATH=./ 和 export LD_LIBRARY_PATH
⑼ linux下C/C++動態庫在運行時是怎樣載入進來的
在linux上,你在ps中說的那種"將動態庫作為一個參數傳到程序里"的使用方式,是通過dlopen函數將.so載入到當前進程中,並且通過ld.so將.so"鏈接"進當前進程。這個"鏈接"過程包括:查找未定義符號在當前進程中的地址、分配數據/代碼/bss段內存(數據初始化全局變數、代碼段重定位)、執行constructor函數等。之後,可以使用dlsym在已知符號名的情況下通過符號名查找符號對應的地址。這個符號可以是一個全局變數、全局函數等。在你說的C++中,重載的函數也可以理解為全局函數,會有一個屬性為weak的符號。該符號的符號名如果不做修改,默認按照System V的C++ API命名規范命名(以保證linux下不同編譯器編譯出來的.so和.o可以通用)。但如果使用extern "C"修飾之後,變成C的函數名,則無名稱修飾,便於使用。
它怎樣實例化我實現的繼承類?
實例化的方式和正常鏈接一樣。例如你在之類Derived中重載了基類Base中函數virtual void foo();那麼你需要在你的.so中導出一個可以new Derived()的函數,並且返回結果為Base *,這樣別人可以在沒有Derived定義的情況下獲得運行時類型為Derived的對象。此時別人雖然只有Base *的類型,但是仍然可以和正常鏈接一樣通過虛表查virtual void foo()的地址,從而調用你定義的foo()。
此外,如果你定義了繼承類的全局變數,在載入.so的時候該全局變數會自動初始化,你也可以將這個初始化的類通過指向Base *的指針傳出去。
如果有大神能解釋一下windows下動態庫和靜態庫的原理,小弟感激不盡!
和Linux差不多,不過在實現細節上有些出入。例如windows鏈接時要直接鏈接.dll需要通過鏈接生成這個.dll時生成的.lib,而Linux上直接鏈接.so即可。不過運行時鏈接無需這個.lib。靜態庫都是目標文件的壓縮包。都是ELF格式。至於共享內存之類的,僅僅取決於section的屬性。
⑽ Linux下執行程序無法載入庫文件有方法解決嗎
程序安裝的目的是為了把執行程序放到執行路徑下面,把配置文件放到程序可讀取的位置,把需要的鏈接庫放到可找到的位置,配置一些需要預先設置的參數等等。如果一個程序這些都不需要,那麼直接把可執行程序放到該在的目錄就可以了。