在使用redis寫c
**的時候遇到的問題,安裝
redis
時make install
可以看到:
mkdir -p/usr/local/include/hiredis /usr/local/lib
cp -a hiredis.h async.h read.h sds.h adapters/usr/local/include/hiredis
cp -a libhiredis.so/usr/local/lib/libhiredis.so.0.13
cd /usr/local/lib &&ln -sflibhiredis.so.0.13 libhiredis.so
cp -a libhiredis.a/usr/local/lib
把redis
的標頭檔案放進了
/usr/local/include/hiredis
,把動態庫
libhiredis.so
和靜態庫
libhiredis.a
都放進了
/usr/local/lib
於是我就在我的
makefile
裡面寫:
gcc main.c -i/usr/local/include-l/usr/local/lib -lhiredis -o main
ok,
gcc通過生成可執行檔案
main
,但是一執行
main
報錯:
error while loading shared libraries:
libhiredis.so.0.13: cannot open sharedobject file: no such file or directory
於是產生了兩個疑問:
1. usr/local/lib
裡面libhiredis.so
和靜態庫
libhiredis.a
都有,為什麼用的是
.so而不是.a?
gcc編譯鏈結時寫法都是
-l庫所在路徑
-l庫名,是否有寫法可以區分指明要鏈結動態庫還是靜態庫?
2. 我在makefile
裡面不是已經指明
so的位置,並且相應位置確實有
libhiredis.so.0.13
,為什麼執行的時候還是找不到?
針對第乙個問題,查了資料之後發現: ld
在鏈結的時候如果路徑下相同庫名的靜態庫和動態庫都有,那麼會優先使用動態鏈結庫,動態鏈結庫不存在才會使用靜態鏈結庫;
如果指明要使用靜態鏈結庫,那麼需要在編譯命令中加入
-static
引數;
gcc main.c -i/usr/local/include-l/usr/local/lib -lhiredis -static -o main
後來又做了測試發現,
-static
是乙個全域性引數,並不是只對乙個鏈結生效,對所有的鏈結都生效。也就是一旦寫上之後所有庫都只會去找靜態庫,就不能指定某些庫鏈靜態庫,而其它庫鏈動態庫;
針對第二個問題其實是很顯然的,
"link time"
(鏈結時)和
"runtime"
(執行時),兩個基本概念要弄清楚,不能混在一起。
-l選項屬於鏈結時,編譯出來的可執行檔案不知道
-l選項後面的值,當然找不到對應的
so。而
-rpath,ld_library_path
都屬於執行時
查資料之後發現執行的時候查詢動態庫路徑順序如下:
1. 可執行檔案中自帶的編譯時寫入的rpath、runpath
2. ld_library_path 指定的地方
3. ldconfig 指定的地方:根據/etc/ld.so.cache查詢
4. /lib
5. /usr/lib
所以相對應的解決辦法有:
1. 使用rpath把so的路徑指明並記錄到二進位制檔案中
gcc main.c -i/usr/local/include -l/usr/local/lib -lhiredis –o main -wl,--rpath=/usr/local/lib
重新編譯再執行發現無報錯了 關於
rpath
、runpath
的詳細相關作用方法見
2. 把libredis.so所在路徑加入到ld_library_path環境變數中
export ld_library_path= /usr/local/lib:$ld_library_path
3. 使用ldconfig修改/etc/ld.so.cache
ldconfig
命令的用途主要是在預設搜尋目錄
/lib
和/usr/lib
以及動態庫配置檔案
/etc/ld
.so.conf
內所列的目錄下,搜尋出可共享的動態鏈結庫(格式如
lib*.so*),
進而建立出動態裝入程式
(ld.so)
所需的連線和快取檔案(一般預設為
/etc/ld.so.cache
),此檔案儲存已排好序的動態鏈結庫名字列表
ldconfig
通常在系統啟動時執行,而當使用者安裝了乙個新的動態鏈結庫時,就需要手工執行這個命令。
由於我們是新安裝了
redis
/etc/ld.so.conf
下面加一行
/usr/local/lib
/usr/local/mysql/lib
(需要root
許可權),儲存過後
ldconfig
一下(需要
root
許可權)
4. 把新安裝的so拷到/lib或/usr/lib下
ld 動態鏈結庫配置
一 ldconfig ldconfig是乙個動態鏈結庫管理命令,為了讓動態鏈結庫為系統所共享,還需執行動態鏈結庫的管理命令 ldconfig。ldconfig 命令的用途,主要是在預設搜尋目錄 lib和 usr lib 以及動態庫配置檔案 etc ld.so.conf內所列的目錄下,搜尋出可共享的動...
動態鏈結庫 靜態鏈結庫
包含標頭檔案和庫 idir 指定編譯查詢標頭檔案的目錄,常用於查詢第三方的庫的標頭檔案,例 gcc test.c i.inc o test。ldir 指定鏈結時查詢lib的目錄,常用於查詢第三方庫。llibrary 指定額外鏈結的lib庫 巨集定義 dmacro 以字串 1 預設值 定義 macro...
靜態鏈結庫 動態鏈結庫
庫是寫好的現有的,成熟的,可以復用的 現實中每個程式都要依賴很多基礎的底層庫,不可能每個人的 都從零開始,因此庫的存在意義非同尋常。本質上來說庫是一種可執行 的二進位制形式,可以被作業系統載入記憶體執行。庫有兩種 靜態庫 a lib 和動態庫 so dll windows上對應的是.lib dll ...