<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    linux下so動態庫一些不為人知的秘密(上)

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

     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:

      呵呵,辦法很簡單省事吧,本文主要講so依賴的一些問題,下一篇將介紹so的路徑方面一些不為人知的小秘密RFID設備管理軟件

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全