linux指定動態運行庫的位置


  動態運行庫在windows、linux下均廣泛使用。windows下通常為dll文件,linux下為so文件。不過,對於部署程序,這兩個系統查找依賴的運行庫文件時卻不一樣。對於windows而言,優先查找當前目錄下,然后再到系統庫文件C:\windows\system32(記不太清楚,好像是這個位置)下查找。這個特性極大的方便了程序的部署,程序員只需要把相關的dll打包就OK,這也讓很多程序可以制作成綠色版。而在linux下,默認只到/lib、/usr/lib和/usr/local/lib查找,找不到程序將無法啟動。

  對於windows的方式,好處顯而易見,就是方便部署。缺點也有,安全性不高。想想有那么多dll是通用的,我隨便寫個同名的扔到程序當前目錄下,不就把程序劫持了么。不過,這個缺點在日常應用中顯得不是很重要。大部分人下軟件安裝時根本不會注意軟件安裝了什么文件,只要殺毒軟件不報就OK。而相對於程序員而言,這種部署也極大的方便了調試。我不太方便去改/usr/lib里的東西。

  要想linux下的程序在當前目錄下查找動態運行庫文件,如果是固定路徑,則可以通過修改系統變量的方式,如LD_LIBRARY_PATH,LD_PRELOAD。而要實現程序copy到任何地方,都在當前目錄下查找,則在編譯程序時需要指定rpath。先編譯一個動態運行庫文件:

root@debian:/home/xzc/cpp/libtest# cat say.cpp
#include <iostream>
#include "say.h"

void CSay::say_yes()
{
    std::cout << "yes yes yes" << std::endl;
}

root@debian:/home/xzc/cpp/libtest# cat say.h

class CSay
{
public:
    void say_yes();
};

root@debian:/home/xzc/cpp/libtest# g++ -fPIC -shared say.cpp -o libsay.so

然后再寫一個程序:

root@debian:/home/xzc/cpp/libtest# cat main.cpp
#include <iostream>

#include "say.h"

int main()
{
    CSay s;
    s.say_yes();
}

root@debian:/home/xzc/cpp/libtest# g++ main.cpp -lsay -L . -o main.o
root@debian:/home/xzc/cpp/libtest# ./main.o 
./main.o: error while loading shared libraries: libsay.so: cannot open shared object file: No such file or directory

可見這個程序沒有找到當前路徑下的libsay.so文件。下面我們在編譯時指定rpath:

root@debian:/home/xzc/cpp/libtest# g++ main.cpp -lsay -L . -Wl,--rpath=. -o main.o
root@debian:/home/xzc/cpp/libtest# ./main.o 
yes yes yes
root@debian:/home/xzc/cpp/libtest# readelf -d main.o 

Dynamic section at offset 0x860 contains 26 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [libsay.so]
 0x00000001 (NEEDED)                     Shared library: [libstdc++.so.6]
 0x00000001 (NEEDED)                     Shared library: [libm.so.6]
 0x00000001 (NEEDED)                     Shared library: [libgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 0x0000000f (RPATH)                      Library rpath: [.]
 0x0000000c (INIT)                       0x8048508
 0x0000000d (FINI)                       0x804878c
 0x00000004 (HASH)                       0x804818c
 0x6ffffef5 (GNU_HASH)                   0x80481dc
 0x00000005 (STRTAB)                     0x8048310
 0x00000006 (SYMTAB)                     0x8048220
 0x0000000a (STRSZ)                      312 (bytes)
 0x0000000b (SYMENT)                     16 (bytes)
 0x00000015 (DEBUG)                      0x0
 0x00000003 (PLTGOT)                     0x804995c
 0x00000002 (PLTRELSZ)                   56 (bytes)
 0x00000014 (PLTREL)                     REL
 0x00000017 (JMPREL)                     0x80484d0
 0x00000011 (REL)                        0x80484c8
 0x00000012 (RELSZ)                      8 (bytes)
 0x00000013 (RELENT)                     8 (bytes)
 0x6ffffffe (VERNEED)                    0x8048468
 0x6fffffff (VERNEEDNUM)                 2
 0x6ffffff0 (VERSYM)                     0x8048448
 0x00000000 (NULL)                       0x0

可見程序已運行成功。readelf也可以看到其中的rpath為當前目錄,如果沒有指定,則在系統默認中找。現在,這個程序也可以隨意copy到其他地方運行了,只要你連libsay.so一同拷貝。


免責聲明!

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



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