Linux下動態庫的顯性調用(dlopen)和隱性調用區別
在linux環境下編程,我們如果想要使用第三方的庫,基本上有以下幾種方式:
1、將第三方庫的源碼合并到我們的工程項目代碼中,一起編譯。
2、將第三方庫編譯成靜態庫(xxx.a),我們在使用時,在Makefile中引用該靜態庫。
3、將第三方庫編譯成動態庫(xxx.so), 我們在使用時,隱性調用該動態庫,具體表現為需要 在程序中包含動態庫的 頭文件,同時需要在/usr/lib路徑下,存放動態庫文件,以便程序調用。
4、將第三方庫編譯成動態庫(xxx.so), 我們在使用時,顯性調用該動態庫,在程序中,不需要包含動態庫的頭文件,使用 dlopen、dlsym等接口函數調用該動態庫。
在上述四種方式中:
第 1 和 2 種,本質上是一樣的,使用靜態庫,編譯時,會將靜態庫的內容合并到工程代碼中,唯一區別的是當我們拿不到第三方庫的源碼時,可以直接使用靜態庫,相當于使用一個黑盒子,靜態庫提供接口。
第 3 和 4 種方式,我們常用的是第3種方式,也就是隱性調用,但是顯性調用一種程序插件的概念,隨用隨加載,不用不加載。
顯性調用和隱性調用區別
名稱使用方式動態庫文件內存其他隱性調用引用動態庫頭文件需要提前拷貝到/usr/lib/目錄,否則程序無法執行程序開始執行,不管是否用到動態庫功能,都會將動態庫讀到內存中不會額外調用插件庫顯性調用不需要引用動態庫頭文件,但是需要引用不一定,如果程序不會執行到動態庫功能,則不需要拷貝,即便使用,也可以使用絕對路徑來使用,不需要拷貝到/usr/lib/目錄下只有程序執行到dlopen時,才會將動態庫讀入內存會額外調用linux插件庫,來支持顯性調用
在使用dlopen時,編譯時候要加入 -ldl (指定dl庫),若dl庫有問題,那么在運行時調用dlopen時會出現段錯誤。因此要保證dl庫沒問題。
開發時遇到一個問題,本地需要編寫一個so庫給應用程序提供接口,在應用程序中使用dlopen來打開so庫,但是運行時調用dlopen時出現段錯誤。
原因是應用程序編譯時引用應用程序中lib下的dl庫,該庫有問題導致運行時出現段錯誤。解決方式就是把應用程序中lib下的dl庫給替換掉。
小結
顯性調用更多的是體現在“插件”的思想,使用起來更加靈活,比如大的工程項目中,同樣一套代碼,提供不一樣的功能時,為了節省內存、磁盤容量,可以按需加載。在使用方式上,顯性調用相比隱性調用,略復雜,需要增加額外的轉換代碼,而隱性調用,只需要包含動態庫頭文件,在代碼中,直接調用API即可。在生產程序中,如果對內存或磁盤、啟動速度沒有嚴苛的要求,盡量使用隱形調用,方便程序編寫和維護。