• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            tqsheng

            go.....
            隨筆 - 366, 文章 - 18, 評論 - 101, 引用 - 0
            數據加載中……

            linux下so動態庫一些不為人知的秘密(上) (2012-08-14 22:48)



            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的路徑方面一些不為人知的小秘密

             

            posted on 2013-01-04 16:57 tqsheng 閱讀(278) 評論(0)  編輯 收藏 引用

            久久成人18免费网站| 丁香五月综合久久激情| 久久中文字幕一区二区| av色综合久久天堂av色综合在| 国产毛片久久久久久国产毛片| 久久精品国产69国产精品亚洲| www.久久热.com| 久久久久一区二区三区| 久久最新精品国产| 狠狠精品干练久久久无码中文字幕| 99久久综合狠狠综合久久| 国产成人久久精品麻豆一区| 国产精品美女久久久久AV福利| 久久久久久久久久免免费精品| 久久久精品国产Sm最大网站| 久久性精品| 久久久久久国产a免费观看黄色大片 | 国产精品久久久久久久久软件| 久久影院久久香蕉国产线看观看| 人人狠狠综合久久亚洲| 色婷婷综合久久久久中文字幕 | 97视频久久久| 99久久久精品| 国产免费久久精品99久久| 亚洲AV伊人久久青青草原| 国产亚洲美女精品久久久2020| 精品久久久久久久久午夜福利| 88久久精品无码一区二区毛片| 久久精品人妻一区二区三区| 亚洲午夜精品久久久久久浪潮 | 77777亚洲午夜久久多喷| 97久久超碰成人精品网站| 久久久91人妻无码精品蜜桃HD| 热99RE久久精品这里都是精品免费 | 日韩精品久久久久久| 亚洲国产精品无码久久九九 | 日本一区精品久久久久影院| 亚洲第一永久AV网站久久精品男人的天堂AV| 亚洲精品无码专区久久同性男| .精品久久久麻豆国产精品| 久久激情亚洲精品无码?V|