linux動態庫加載的秘密


摘自http://gotowqj.iteye.com/blog/1926734

摘自http://www.360doc.com/content/14/0313/13/12747488_360246417.shtml

 

linux 下有動態庫和靜態庫,動態庫以.so為擴展名,靜態庫以.a為擴展名。二者都使用廣泛。本文主要講動態庫方面知識。

   
   基本上每一個linux 程序都至少會有一個動態庫,查看某個程序使用了那些動態庫,使用 ldd命令查看 
  1. # ldd /bin/ls
  2. linux-vdso.so.1 => (0x00007fff597ff000)
  3. libselinux.so.1 => /lib64/libselinux.so.1 (0x00000036c2e00000)
  4. librt.so.1 => /lib64/librt.so.1 (0x00000036c2200000)
  5. libcap.so.2 => /lib64/libcap.so.2 (0x00000036c4a00000)
  6. libacl.so.1 => /lib64/libacl.so.1 (0x00000036d0600000)
  7. libc.so.6 => /lib64/libc.so.6 (0x00000036c1200000)
  8. libdl.so.2 => /lib64/libdl.so.2 (0x00000036c1600000)
  9. /lib64/ld-linux-x86-64.so.2 (0x00000036c0e00000)
  10. libpthread.so.0 => /lib64/libpthread.so.0 (0x00000036c1a00000)
  11. libattr.so.1 => /lib64/libattr.so.1 (0x00000036cf600000)

   這么多so,是的。使用ldd顯示的so,並不是所有so都是需要使用的,下面舉個例子

main.cpp
  1. #include <stdio.h>
  2. #include <iostream>
  3. #include <string>
  4. using namespace std;
  5. int main ()
  6. {
  7.    cout << "test" << endl;
  8.    return 0;
  9. }
   使用缺省參數編譯結果
  1. # g++ -o demo main.cpp
  2. # ldd demo
  3.     linux-vdso.so.1 => (0x00007fffcd1ff000)
  4.         libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007f4d02f69000)
  5.         libm.so.6 => /lib64/libm.so.6 (0x00000036c1e00000)
  6.         libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00000036c7e00000)
  7.         libc.so.6 => /lib64/libc.so.6 (0x00000036c1200000)
  8.         /lib64/ld-linux-x86-64.so.2 (0x00000036c0e00000)
   如果我鏈接一些so,但是程序並不用到這些so,又是什么情況呢,下面我加入鏈接壓縮庫,數學庫,線程庫
  1. # g++ -o demo -lz -lm -lrt main.cpp
  2. # ldd demo
  3.         linux-vdso.so.1 => (0x00007fff0f7fc000)
  4.         libz.so.1 => /lib64/libz.so.1 (0x00000036c2600000)
  5.         librt.so.1 => /lib64/librt.so.1 (0x00000036c2200000)
  6.         libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007ff6ab70d000)
  7.         libm.so.6 => /lib64/libm.so.6 (0x00000036c1e00000)
  8.         libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00000036c7e00000)
  9.         libc.so.6 => /lib64/libc.so.6 (0x00000036c1200000)
  10.         libpthread.so.0 => /lib64/libpthread.so.0 (0x00000036c1a00000)
  11.         /lib64/ld-linux-x86-64.so.2 (0x00000036c0e00000)

  看看,雖然沒有用到,但是一樣有鏈接進來,那看看程序啟動時候有沒有去加載它們呢

  1. # strace ./demo
  2.     execve("./demo", ["./demo"], [/* 30 vars */]) = 0
  3.     ... = 0
  4.     open("/lib64/libz.so.1", O_RDONLY) = 3
  5.     ...
  6.     close(3) = 0
  7.     open("/lib64/librt.so.1", O_RDONLY) = 3
  8.     ...
  9.     close(3) = 0
  10.     open("/usr/lib64/libstdc++.so.6", O_RDONLY) = 3
  11.     ...
  12.     close(3) = 0
  13.     open("/lib64/libm.so.6", O_RDONLY) = 3
  14.     ...
  15.     close(3) = 0
  16.     open("/lib64/libgcc_s.so.1", O_RDONLY) = 3
  17.     ...
  18.     close(3) = 0
  19.     open("/lib64/libc.so.6", O_RDONLY) = 3
  20.     ...
  21.     close(3) = 0
  22.     open("/lib64/libpthread.so.0", O_RDONLY) = 3
  23.     ...
  24.     close(3) = 0
  25.     ...
  看,有加載,所以必定會影響進程啟動速度,所以我們最后不要把無用的so編譯進來,這里會有什么影響呢?
   大家知不知道linux從程序(program或對象)變成進程(process或進程),要經過哪些步驟呢,這里如果詳細的說,估計要另開一篇文章。簡單的說分三步:
    1、fork進程,在內核創建進程相關內核項,加載進程可執行文件;
    2、查找依賴的so,一一加載映射虛擬地址
    3、初始化程序變量。
  可以看到,第二步中dll依賴越多,進程啟動越慢,並且發布程序的時候,這些鏈接但沒有使用的so,同樣要一起跟着發布,否則進程啟動時候,會失敗,找不到對應的so。所以我們不能像上面那樣,把一些毫無意義的so鏈接進來,浪費資源。但是開發人員寫makefile 一般有沒有那么細心,圖省事方便,那么有什么好的辦法呢。繼續看下去,下面會給你解決方法。
  先 使用 ldd -u demo 查看不需要鏈接的so,看下面,一面了然,無用的so全部暴露出來了吧
  1. # ldd -u demo
  2. Unused direct dependencies:
  3.         /lib64/libz.so.1
  4.         /lib64/librt.so.1
  5.         /lib64/libm.so.6
  6.         /lib64/libgcc_s.so.1
  使用 -Wl,--as-needed 編譯選項
  1. # g++ -Wl,--as-needed -o demo -lz -lm -lrt main.cpp
  2. # ldd demo
  3.         linux-vdso.so.1 => (0x00007fffebfff000)
  4.         libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007ff665c05000)
  5.         libc.so.6 => /lib64/libc.so.6 (0x00000036c1200000)
  6.         libm.so.6 => /lib64/libm.so.6 (0x00000036c1e00000)
  7.         /lib64/ld-linux-x86-64.so.2 (0x00000036c0e00000)
  8.         libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00000036c7e00000)
  9. # ldd -u demo
  10. Unused direct dependencies:

 

 

我們知道linux鏈接so有兩種途徑:顯示和隱式。所謂顯示就是程序主動調用dlopen打開相關so;這里需要補充的是,如果使用顯示鏈接,上篇文章討論的那些問題都不存在。首先,dlopen的so使用ldd是查看不到的。其次,使用dlopen打開的so並不是在進程啟動時候加載映射的,而是當進程運行到調用dlopen代碼地方才加載該so,也就是說,如果每個進程顯示鏈接a.so;但是如果發布該程序時候忘記附帶發布該a.so,程序仍然能夠正常啟動,甚至如果運行邏輯沒有觸發運行到調用dlopen函數代碼地方。該程序還能正常運行,即使沒有a.so.

 

  既然顯示加載這么多優點,那么為什么實際生產中很少碼農使用它呢, 主要原因還是起使用不是很方便,需要開發人員多寫不少代碼。所以不被大多數碼農使用,還有一個重要原因應該是能提前發現錯誤,在部署的時候就能發現缺少哪些so,而不是等到實際上限運行的時候才發現缺東少西。

 

  下面舉個工作中最常碰到的問題,來引申出本篇內容吧。

寫一個最簡單的so, tmp.cpp

1.    int test()

2.    {

3.      return 20;

4.    }

  編譯=>鏈接=》運行, 下面main.cpp 內容請參見上一篇文章。

[stevenrao]$ g++ -fPIC -c tmp.cpp

[stevenrao]$ g++ -shared -o libtmp.so tmp.o

[stevenrao]$ mv libtmp.so /tmp/

[stevenrao]$ g++ -o demo -L/tmp -ltmp main.cpp

[stevenrao]$ ./demo

./demo: error while loading shared libraries: libtmp.so: cannot open shared object file: No such file or directory

 

 


 

 

[stevenrao]$ g++ -fPIC -c tmp.cpp

[stevenrao]$ g++ -shared -o libtmp.so tmp.o

[stevenrao]$ mv libtmp.so /tmp/

[stevenrao]$ g++ -o demo -L/tmp -ltmp main.cpp

[stevenrao]$ ./demo

./demo: error while loading shared libraries: libtmp.so: cannot open shared object file: No such file or directory

[stevenrao]$ ldd demo

linux-vdso.so.1 => (0x00007fff7fdc1000)

        libtmp.so => not found

 

[stevenrao]$ ldd demo

linux-vdso.so.1 =>  (0x00007fff7fdc1000)

        libtmp.so => not found

   這個錯誤是最常見的錯誤了。運行程序的時候找不到依賴的so。一般人使用方法是修改LD_LIBRARY_PATH這個環境變量

   export LD_LIBRARY_PATH=/tmp

[stevenrao]$ ./demo

test

   這樣就OK了, 不過這樣export 只對當前shell有效,當另開一個shell時候,又要重新設置。可以把export LD_LIBRARY_PATH=/tmp 語句寫到 ~/.bashrc中,這樣就對當前用戶有效了,寫到/etc/bashrc中就對所有用戶有效了。

   前面鏈接時候使用 -L/tmp/ -ltmp 是一種設置相對路徑方法,還有一種絕對路徑鏈接方法。

[stevenrao]$ g++ -o demo  /tmp/libtmp.so main.cpp

[stevenrao]$ ./demo

  test

[stevenrao]$ ldd demo

        linux-vdso.so.1 =>  (0x00007fff083ff000)

        /tmp/libtmp.so (0x00007f53ed30f000) 

絕對路徑雖然申請設置環境變量步驟,但是缺陷也是致命的,這個so必須放在絕對路徑下,不能放到其他地方,這樣給部署帶來很大麻煩。所以應該禁止使用絕對路徑鏈接so。

   

   搜索路徑分兩種,一種是鏈接時候的搜索路徑,一種是運行時期的搜索路徑。像前面提到的 -L/tmp/ 是屬於鏈接時期的搜索路徑,即給ld程序提供的編譯鏈接時候尋找動態庫路徑;而 LD_LIBRARY_PATH則既屬於鏈接期搜索路徑,又屬於運行時期的搜索路徑。

   

   這里需要介紹鏈-rpath鏈接選項,它是指定運行時候都使用的搜索路徑。聰明的同學馬上就想到,運行時搜索路徑,那它記錄在哪兒呢。也像. LD_LIBRARY_PATH那樣,每部署一台機器就需要配一下嗎。呵呵,不需要..,因為它已經被硬編碼到可執行文件內部了。看看下面演示

[stevenrao] $ g++ -o demo -L /tmp/ -ltmp main.cpp

[stevenrao] $ ./demo

./demo: error while loading shared libraries: libtmp.so: cannot open shared object file: No such file or directory

[stevenrao] $ g++ -o demo -Wl,-rpath /tmp/ -L/tmp/ -ltmp main.cpp

[stevenrao] $ ./demo

test

[stevenrao] $ readelf -d demo

Dynamic section at offset 0xc58 contains 26 entries:

  Tag        Type                         Name/Value

 0x0000000000000001 (NEEDED)             Shared library: [libtmp.so]

 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]

 0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]

 0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]

 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

 0x000000000000000f (RPATH)              Library rpath: [/tmp/]

 0x000000000000001d (RUNPATH)            Library runpath: [/tmp/]

   看看是吧,編譯到elf文件內部了,路徑和程序深深的耦合到一起

繼續上一篇《 linux下so動態庫一些不為人知的秘密(中) 》介紹so搜索路徑,還有一個類似於-path,叫LD_RUN_PATH環境變量, 它也是把路徑編譯進可執行文件內,不同的是它只設置RPATH。

 [stevenrao]  g++ -o demo -L /tmp/  -ltmp main.cpp
 [stevenrao]  readelf -d demo
 Dynamic section at offset 0xb98 contains 25 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libtmp.so]
 ....
 0x000000000000000f  (RPATH)              Library rpath: [/tmp/]
 
  另外還可以通過配置 /etc/ld.so.conf,在其中加入一行
  /tmp/
  這個配置項也是只對運行期有效,並且是全局用戶都生效,需要root權限修改,修改完后需要使用命令 ldconfig 將 /etc/ld.so.conf 加載到 ld.so.cache中,避免重啟系統就可以立即生效。
  除了前面介紹的那些搜索路徑外,還有缺省搜索路徑/usr/lib/ /lib/ 目錄,可以通過 -z nodefaultlib編譯選項禁止搜索缺省路徑。
  [stevenrao] $  g++ -o demo -z nodefaultlib  -L/tmp -ltmp main.cpp
  [stevenrao] $   ./demo
   ./demo: error while loading shared libraries: libstdc++.so.6: cannot open shared object file
 
  這么多搜索路徑,他們有個先后順序如下
  1、RUMPATH 優先級最高
  2、RPATH   其次
  3、LD_LIBRARY_PATH
  4、/etc/ld.so.cache
  5、/usr/lib/ /lib/
 
  查看一個程序搜索其各個動態庫另一個簡單的辦法是使用 LD_DEBUG這個環境變量;
  [stevenrao] $  export LD_DEBUG=libs
  [stevenrao] $  ./demo
 
 
 
 
 

鏈接動態庫

如何程序在連接時使用了共享庫,就必須在運行的時候能夠找到共享庫的位置。linux的可執行程序在執行的時候默認是先搜索/lib和/usr/lib這兩個目錄,然后按照/etc/ld.so.conf里面的配置搜索絕對路徑。同時,Linux也提供了環境變量LDLIBRARYPATH供用戶選擇使用,用戶可以通過設定它來查找除默認路徑之外的其他路徑,如查找/work/lib路徑,你可以在/etc/rc.d/rc.local或其他系統啟動后即可執行到的腳本添加如下語句:LDLIBRARYPATH =/work/lib:$(LDLIBRARYPATH)。並且LDLIBRARYPATH路徑優先於系統默認路徑之前查找(詳細參考《使用LDLIBRARYPATH》)。

不過LDLIBRARYPATH的設定作用是全局的,過多的使用可能會影響到其他應用程序的運行,所以多用在調試。(LDLIBRARYPATH的缺陷和使用准則,可以參考《Why LDLIBRARYPATH is bad》 )。通常情況下推薦還是使用gcc的-R或-rpath選項來在編譯時就指定庫的查找路徑,並且該庫的路徑信息保存在可執行文件中,運行時它會直接到該路徑查找庫,避免了使用LDLIBRARYPATH環境變量查找。

鏈接選項和路徑

現代連接器在處理動態庫時將鏈接時路徑(Link-time path)和運行時路徑(Run-time path)分開,用戶可以通過-L指定連接時庫的路徑,通過-R(或-rpath)指定程序運行時庫的路徑,大大提高了庫應用的靈活性。比如我們做嵌入式移植時#arm-linux-gcc $(CFLAGS) –o target –L/work/lib/zlib/ -llibz-1.2.3 (work/lib/zlib下是交叉編譯好的zlib庫),將target編譯好后我們只要把zlib庫拷貝到開發板的系統默認路徑下即可。或者通過-rpath(或-R )、LDLIBRARYPATH指定查找路徑。

鏈接器ld的選項有 -L,-rpath 和 -rpath-link,看了下 man ld,大致是這個意思:

-L: “鏈接”的時候,去找的目錄,也就是所有的 -lFOO 選項里的庫,都會先從 -L 指定的目錄去找,然后是默認的地方。編譯時的-L選項並不影響環境變量LDLIBRARYPATH,-L只是指定了程序編譯連接時庫的路徑,並不影響程序執行時庫的路徑,系統還是會到默認路徑下查找該程序所需要的庫,如果找不到,還是會報錯,類似cannot open shared object file。

-rpath-link:這個也是用於“鏈接”的時候的,例如你顯示指定的需要 FOO.so,但是 FOO.so 本身是需要 BAR.so 的,后者你並沒有指定,而是 FOO.so 引用到它,這個時候,會先從 -rpath-link 給的路徑里找。

-rpath: “運行”的時候,去找的目錄。運行的時候,要找 .so 文件,會從這個選項里指定的地方去找。對於交叉編譯,交叉編譯鏈接器需已經配置 --with-sysroot 選項才能起作用。也就是說,-rpath指定的路徑會被記錄在生成的可執行程序中,用於運行時查找需要加載的動態庫。-rpath-link 則只用於鏈接時查找。

鏈接搜索順序

直接man ld。The linker uses the following search paths to locate required shared libraries:

       1.  Any directories specified by -rpath-link options.
       2.  Any directories specified by -rpath options.  The difference between -rpath and -rpath-link is that directories specified by -rpath options are included in the executable and used at runtime, whereas the -rpath-link option is only effective at link time. Searching -rpath in this way is only supported by native linkers and cross linkers which have been configured with the --with-sysroot option.
       3.  On an ELF system, for native linkers, if the -rpath and -rpath-link options were not used, search the contents of the environment variable "LD_RUN_PATH".
       4.  On SunOS, if the -rpath option was not used, search any directories specified using -L options.
       5.  For a native linker, the search the contents of the environment variable "LD_LIBRARY_PATH".
       6.  For a native ELF linker, the directories in "DT_RUNPATH" or "DT_RPATH" of a shared library are searched for shared libraries needed by it. The "DT_RPATH" entries are ignored if "DT_RUNPATH" entries exist.
       7.  The default directories, normally /lib and /usr/lib.
       8.  For a native linker on an ELF system, if the file /etc/ld.so.conf exists, the list of directories found in that file.
       If the required shared library is not found, the linker will issue a warning and continue with the link.

gcc和鏈接選項的使用

在gcc中使用ld鏈接選項時,需要在選項前面加上前綴-Wl(是字母l,不是1,我曾多次弄錯),以區別不是編譯器的選項。 if the linker is being invoked indirectly, via a compiler driver (e.g. gcc) then all the linker command line options should be prefixed by -Wl, (or whatever is appropriate for the particular compiler driver) like this:

1 gcc -Wl,--start-group foo.o bar.o -Wl,--end-group

This is important, because otherwise the compiler driver program may silently drop the linker options, resulting in a bad link.

用例子說話

 

二進制

對應源碼

有一個程序

a.out

main.c

需要加載插件A

libA.so

liba.c

A需要另一個動態庫

libB.so

libB1.c 或 libB2.c

本文的關注點就是:到底是哪一個libB.so被加載

目錄結構:

/home/debao/ttt/a.out /home/debao/ttt/libA.so /home/debao/ttt/libB.so /usr/lib/libB.so

具體源碼

  • main.c ==> ./a.out

 

#include <stdio.h>
#include <dlfcn.h>
typedef int (*funcA)(int, int);
int main()
{
    void * plugin = dlopen("./libA.so", RTLD_LAZY);
    funcA f = (funcA)dlsym(plugin, "funcA");
    printf("main: %d\n", f(3,4));
    return 0;
}
  • liba.c ==> ./libA.so

 

#include <stdio.h>
int funcB(int, int);
int funcA(int a, int b)
{
    printf("hello from funcA\n");
    return funcB(a, b);
}
  • libb1.c ==> ./libB.so

 

#include <stdio.h>
int funcB(int a, int b)
{
    printf("Hello from funcB 1\n");
    return a*b;
}  
  • libb2.c ==> /usr/lib/libB.so

 

#include <stdio.h>
int funcB(int a, int b)
{
    printf("Hello from funcB 2\n");
    return a*b;
}  

編譯庫文件

  • 編譯動態庫libB.so

 

$ gcc -shared -fPIC libb2.c -o libB2.so
$ sudo mv libB2.so /usr/lib/libB.so
$ gcc -shared -fPIC libb.c -o libB.so
  • 編譯動態庫libA.so

 

$ gcc -shared -fPIC liba.c -o libA.so -L. -lB

順便看看該elf文件的頭部信息:

$ readelf libA.so -d

Dynamic section at offset 0xf20 contains 21 entries:
  Tag        Type      Name/Value
 0x00000001 (NEEDED)   Shared library: [libB.so]
 0x00000001 (NEEDED)   Shared library: [libc.so.6]
...

恩,只有庫的文件名信息,而沒有路徑信息。

編譯程序

  • 第一次編譯運行(什么路徑都不加)

 

$ gcc main.c -ldl
$ ./a.out 
hello from funcA
Hello from funcB 2
main: 12

程序:dlopen從當前目錄找到libA.so,然后卻在/usr/lib/中找到libB.so(沒有使用當前目錄的libB.so,這是我們需要的么?)

  • 第二次編譯運行(使用DT_RPATH)

 

$ gcc main.c -ldl  -Wl,--rpath=.
$ ./a.out 
hello from funcA
Hello from funcB 1
main: 12

恩,使用當前目錄的libB.so,很理想的東西

  • 可是,由於DT_RPATH無法被環境變量LD_LIBRARY_PATH覆蓋,不是不建議被使用,而是建議使用DT_RUNPATH么?

  • 第三次編譯運行(使用DT_RUNPATH)

 

$ gcc main.c -ldl -Wl,--rpath=.,--enable-new-dtags 
$ ./a.out 
hello from funcA
Hello from funcB 2
main: 12

問題重新出現,使用的系統路徑中的libB.so 而不是當前目錄下的。

程序頭部信息

通過下列命令可以查看:

$ readelf -d a.out

為了完整起見,列出前面3次編譯的程序的信息:

  • 沒有rpath和runpath

 

Dynamic section at offset 0xf20 contains 21 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [libdl.so.2]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 0x0000000c (INIT)                       0x8048360
...
  • 包含rpath

 

Dynamic section at offset 0xf18 contains 22 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [libdl.so.2]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 0x0000000f (RPATH)                      Library rpath: [.]
 0x0000000c (INIT)                       0x8048360
....
  • 包含rpath和runpath

 

Dynamic section at offset 0xf10 contains 23 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [libdl.so.2]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 0x0000000f (RPATH)                      Library rpath: [.]
 0x0000001d (RUNPATH)                    Library runpath: [.]

原因

RPATH and RUNPATH給出這個問題的答案:

 

Unless loading object has RUNPATH:
    RPATH of the loading object,
        then the RPATH of its loader (unless it has a RUNPATH), ...,
        until the end of the chain, which is either the executable
        or an object loaded by dlopen
    Unless executable has RUNPATH:
        RPATH of the executable
LD_LIBRARY_PATH
RUNPATH of the loading object
ld.so.cache
default dirs

用它解釋第一個程序:

  • libA.so 沒有RUNPATH,故而
    • 使用其RPATH (沒有)
    • 遞歸查找其loader直到鏈條的頂端(可執行程序或被dlopen打開的對象)的RPATH或者遇RUNPATH退出 (沒有命中)
    • 可執行程序沒有RUNPATH,故而
      • 使用其RPATH (沒有)
  • 環境變量LD_LIBRARY_PATH,(沒有)
  • libA.so 的RUNPATH (沒有)
  • ld.so.cache (沒有命中)
  • 默認路徑/usr/lib (命中)

用它解釋第二個程序:

  • libA.so 沒有RUNPATH,故而
    • 使用其RPATH (沒有)
    • 遞歸查找其loader直到鏈條的頂端(可執行程序或被dlopen打開的對象)的RPATH或者遇RUNPATH退出 (沒有命中)
    • 可執行程序沒有RUNPATH,故而
      • 使用其RPATH (命中)

用它解釋第三個程序:

  • libA.so 沒有RUNPATH,故而
    • 使用其RPATH (沒有)
    • 遞歸查找其loader直到鏈條的頂端(可執行程序或被dlopen打開的對象)的RPATH或者遇RUNPATH退出 (沒有命中)
    • 可執行程序有RUNPATH,(繼續前行)
  • 環境變量LD_LIBRARY_PATH,(沒有)
  • libA.so 的RUNPATH (沒有)
  • ld.so.cache (沒有命中)
  • 默認路徑/usr/lib (命中)

有意思的就是這個程序了,可執行程序的RUNPATH是一個重要的判斷條件,卻並不被做為這兒搜索路徑!!

結束

本文是在kubuntu 11.10下編寫測試的。為了盡可能簡單,例子也都是認為制造的。而且我們看到,在使用RPATH的時候是正常的,RUNPATH一般來說,被推薦使用,但這兒它卻不能正常工作。

所以,當使用RUNPATH時,我們需要明白:某些情況下可能需要設置環境變量 LD_LIBRARY_PATH

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM