天天看點

linux動态連結庫的加載順序:

linux動态連結庫的加載順序:

它有5個地方會查找,

1. 編譯時指定的run path

2. LD_LIBRARY_PATH 指定的地方

3. ldconfig 指定的地方

4. /lib

5. /usr/lib

下面是測試執行個體,驗證上面5句話。 (注: 用strace 會更好的看到加載順序!!! --hjjdebug)

------------------------------------------------------------

1. 編寫5個so源檔案和1個測試檔案

------------------------------------------------------------

[email protected]:~/MyTest/temp$ cat pos1.c
#include <stdio.h>

void tellpos()
{
    printf("I am pos1\n");
}
[email protected]:~/MyTest/temp$ cat pos2.c
#include <stdio.h>

void tellpos()
{
    printf("I am pos2\n");
}
[email protected]:~/MyTest/temp$ cat pos3.c
#include <stdio.h>

void tellpos()
{
    printf("I am pos3\n");
}
[email protected]:~/MyTest/temp$ cat pos4.c
#include <stdio.h>

void tellpos()
{
    printf("I am pos4\n");
}
[email protected]:~/MyTest/temp$ cat pos5.c
#include <stdio.h>

void tellpos()
{
    printf("I am pos5\n");
}
[email protected]:~/MyTest/temp$ cat main.c
#include <stdio.h>
void tellpos();
int main(int argc, char *argv)
{
	tellpos();
	return 0;
}
           

2. 生成5個so檔案并放到5個地方,生成test 測試檔案

$ cat Makefile
CC=gcc
CFLAG=-fPIC -c
LDFLAG=-shared
all: fivepos test
fivepos
	-mkdir pos1 pos2 pos3
	$(CC) $(CFLAG) -o pos.o pos1.c
	$(CC) $(LDFLAG) pos.o -o libpos.so
	mv libpos.so pos1
	$(CC) $(CFLAG) -o pos.o pos2.c
	$(CC) $(LDFLAG) pos.o -o libpos.so
	mv libpos.so pos2
	$(CC) $(CFLAG) -o pos.o pos3.c
	$(CC) $(LDFLAG) pos.o -o libpos.so
	mv libpos.so pos3
	$(CC) $(CFLAG) -o pos.o pos4.c
	$(CC) $(LDFLAG) pos.o -o libpos.so
	sudo mv libpos.so /lib
	$(CC) $(CFLAG) -o pos.o pos5.c
	$(CC) $(LDFLAG) pos.o -o libpos.so
	sudo mv libpos.so /usr/lib
test: main.c
	gcc -o test main.c -L pos1 -lpos -Wl,-rpath,pos1
# -L pos1 是說連接配接時到 pos1 目錄去找
# -Wl,-rpath,pos1 是說運作時到pos1目錄去找 
           

3. 其它說明:

    pos1 通過readelf -d test 可以看到(RPATH) Library rpath: [pos1]

    pos2 需要用LD_LIBRARY_PATH 說明。此例為: export LD_LIBRARY_PATH=./pos2

    pos3 需要在/etc/ld.so.conf 中指明,此例為:/home/hjj/MyTest/temp/pos3

         然後ldconfig 生成緩存使設定生效。

    pos4 系統目錄/lib

    pos5 系統目錄/usr/lib

------------------------------------------------------------

4. 用ldd 檢查 和用 ./test 直接測試及結果

------------------------------------------------------------

那個64為位址是動态位址,每次ldd 都會變的。

ldd test

    libpos.so => pos1/libpos.so (0x00007f93f4204000)

./test

I am pos1

rm pos1/libpos.so  // 第一個地方删除掉該so, 它會從剩下的4個地方繼續選擇

ldd test

    libpos.so => ./pos2/libpos.so (0x00007f580053d000)

./test

I am pos2

rm pos2/libpos.so //它會從剩下的3個地方繼續選擇

$ ldd test

    libpos.so => /home/hjj/MyTest/temp/pos3/libpos.so (0x00007efef7dbf000)

$ ./test

I am pos3

rm pos3/libpos.so //它會從剩下的2個地方繼續選擇

ldd test

    libpos.so => /lib/libpos.so (0x00007f70d60ce000)

./test

I am pos4

sudo rm /lib/libpos.so //它會從剩下的1個地方繼續選擇

ldd test

    libpos.so => /usr/lib/libpos.so (0x00007f3849e1e000)

./test

I am pos5

sudo rm /usr/lib/libpos.so

ldd test

libpos.so => not found

./test

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

我們用strace ./test 來跟蹤系統調用,非常清晰的看到了動态庫的加載過程。(這就不貼文字了). 看到連結器經過了很多的努力後,

最後給出找不到動态庫的結論。

本貼示範了如何生成動态庫so檔案及如何使用動态庫。 給出了一種比較笨的直接了當的方法,也給出了聰明的strace方法。

繼續閱讀