• <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>

            Prayer

            在一般中尋求卓越
            posts - 1256, comments - 190, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

            Aix上使用庫文件和編寫庫文件

            Posted on 2008-12-31 13:45 Prayer 閱讀(10874) 評論(2)  編輯 收藏 引用 所屬分類: C/C++LINUX/UNIX/AIX
            Aix上使用庫文件和編寫庫文件。
            一直以來,被動態鏈接庫,靜態庫,靜態鏈接,動態鏈接,最近又聽到運行時鏈接弄得一塌糊涂。天下文章一大抄,知道的大家都知道,靜態鏈接是編譯時鏈接,生成的文件大,動態鏈接是運行時鏈接,生成的文件小。不知道的大家都不知道,或者大家都以為自己知道...有時windows,有時linux,有時Aix,有時gcc,有時g++,有時cc,有時xlc,有時.so,有時.a,有時.dll有時.lib有時.o,太多不一致,太多麻煩。
            還有,因為工作的原因,經常在以Aix為工作環境,有的說.so是動態鏈接庫,.a是靜態鏈接庫,但在Aix上咋看咋不像。
            這周末,我花了兩天時間研究Aix上的這些問題,用的是vac的xlc和ccs的ld,不能說現在有多了解,但至少不像以前那么糊涂了。現在做做總結。

            一,鏈接文件和鏈接方式。
            其實沒有將動態鏈接和動態鏈接方式仔細地想一想,是導致我原來混亂的主要原因。之所以想到這個問題,是在工作中要編寫一個庫a,那我要編譯a,然后要寫另一個庫b,b依賴于a,我又要編譯b,在這個過程中,我開始思考,我當初編譯a的時候是用的什么鏈接方式,我現在要用a了,那a又是什么?
            于是我開始區分鏈接文件和鏈接方式,開始了以下實驗
            1,使用庫文件libc.a,靜態鏈接成可執行程序
            hello.c
            C代碼 復制代碼
            1. #include <stdio.h>   
            2. int main() {   
            3.   printf("Hello, world!\n");   
            4. }  

            運行
            # xlc  -o hello.o -c hello.c
            生成目標文件hello.o
            運行
            ld -o hello_s -bstatic hello.o -lc
            想靜態鏈接hello.o和libc.a,并生成可執行文件hello_s。我這里沒有直接使用xlc來生成可執行文件,是想把其中每一步弄清楚,結果求知的代價就是大量的時間和無盡的搜索。-bnso是告訴ld靜態鏈接。(你還可以用xlc的-E和-S參數看hello.c的預處理文件和匯編文件,再用as來編譯匯編文件生成對象文件)
            結果
            ld: 0711-327 WARNING: Entry point not found: __start
            ld: 0711-244 ERROR: No csects or exported symbols have been saved.
            這里說沒有找到__start,這個__start看起來很像系統的一個子歷程。出現這個錯的原因是因為我們沒有在鏈接時加入這樣一個庫/usr/lib/crt0.o,如果你用xlc直接靜態鏈接,那么這個庫應該是xlc自己幫你加的(這個庫好像是線程初始化相關),你可以通過nm命令查看這個目標文件相關的symbol,里面是包含有__start的。于是我們再運行
            ld -o hello_s -bstatic hello.o -lc /usr/lib/crt0.o
            結果報錯說一大堆符號找不到,
            ld: 0711-224 WARNING: Duplicate symbol: .is_posix_tz
            ld: 0711-224 WARNING: Duplicate symbol: .__icuinit
            ld: 0711-345 Use the -bloadmap or -bnoquiet option to obtain more information.
            ld: 0711-317 ERROR: Undefined symbol: __loadx
            ld: 0711-317 ERROR: Undefined symbol: _system_TB_config
            ld: 0711-317 ERROR: Undefined symbol: errno
            ld: 0711-317 ERROR: Undefined symbol: .___bzero
            ld: 0711-317 ERROR: Undefined symbol: smcr_timebase
            ld: 0711-317 ERROR: Undefined symbol: .___memmove
            ld: 0711-317 ERROR: Undefined symbol: .___memset
            ld: 0711-317 ERROR: Undefined symbol: _system_configuration
            ld: 0711-317 ERROR: Undefined symbol: disclaim
            ld: 0711-317 ERROR: Undefined symbol: kwritev
            ld: 0711-317 ERROR: Undefined symbol: kpwritev
            ld: 0711-317 ERROR: Undefined symbol: kpwrite
            ld: 0711-317 ERROR: Undefined symbol: kwrite
            ld: 0711-317 ERROR: Undefined symbol: kopenx
            ...
            ld提示可以用-bloadmap來查看具體的出錯信息,于是我運行
            ld -o hello_s -bstatic hello.o -lc /usr/lib/crt0.o -bloadmap:out.txt
            并查看輸出文件,得到
            ...
            ld: 0711-318 ERROR: Undefined symbols were found.
                    The following symbols are in error:
             Symbol                    Inpndx  TY CL Source-File(Object-File) OR Import-File{Shared-object}
                                          RLD: Address  Section  Rld-type Referencing Symbol
             ----------------------------------------------------------------------------------------------
             __loadx                   [262]   ER DS (/usr/lib/libc.a[shr.o])
                                               0006919c .data    R_POS    [1658]  <__loadx>
             _system_TB_config         [792]   ER UA (/usr/lib/libc.a[shr.o])
                                               000691a8 .data    R_POS    [1664]  <_system_TB_config>
             errno                     [8]     ER UA (/usr/lib/libc.a[shr.o])
                                               00068e3c .data    R_POS    [1226]  
            ...
            這說明是libc.a中的shr.o中的定義的一些符號找不到,于是我們將這個shr.o解出來,運行
            ar -x /usr/lib/libc.a shr.o
            得到shr.o,然后
            ldd shr.o
            得到輸出
            shr.o needs:
                     /unix
                     /usr/lib/libcrypt.a(shr.o)
                     /usr/lib/libc.a(shr.o)
            這個shr.o需要以上三個庫,libc.a我們已經包括了,那么哪里去找/unix這個庫?相比現在所找不到的符號應該都是系統調用吧。查看ld的手冊得知我們需要導入系統調用的符號表/lib/syscalls.exp
            于是我們再運行
            # ld -o hello_s -bstatic hello.o -lc /usr/lib/crt0.o -bI:/lib/syscalls.exp
            結果還是報錯
            # ld -o hello_s -bstatic hello.o -lc /usr/lib/crt0.o -bI:/lib/syscalls.exp
            ld: 0711-224 WARNING: Duplicate symbol: .open
            ld: 0711-224 WARNING: Duplicate symbol: .openx
            ld: 0711-224 WARNING: Duplicate symbol: .is_posix_tz
            ld: 0711-224 WARNING: Duplicate symbol: .__icuinit
            ld: 0711-224 WARNING: Duplicate symbol: .send
            ld: 0711-224 WARNING: Duplicate symbol: .nrecvmsg
            ld: 0711-224 WARNING: Duplicate symbol: .nrecvfrom
            ld: 0711-224 WARNING: Duplicate symbol: .recvmsg
            ld: 0711-224 WARNING: Duplicate symbol: .recvfrom
            ld: 0711-224 WARNING: Duplicate symbol: .recv
            ld: 0711-224 WARNING: Duplicate symbol: .nsendmsg
            ld: 0711-224 WARNING: Duplicate symbol: .sendmsg
            ld: 0711-224 WARNING: Duplicate symbol: .sendto
            ld: 0711-224 WARNING: Duplicate symbol: .naccept
            ld: 0711-224 WARNING: Duplicate symbol: .accept
            ld: 0711-224 WARNING: Duplicate symbol: .thread_wait
            ld: 0711-345 Use the -bloadmap or -bnoquiet option to obtain more information.
            ld: 0711-317 ERROR: Undefined symbol: encrypted_pw_passlen
            ld: 0711-317 ERROR: Undefined symbol: crypt_r
            ld: 0711-317 ERROR: Undefined symbol: max_history_size
            ld: 0711-317 ERROR: Undefined symbol: getpass_auto
            ld: 0711-317 ERROR: Undefined symbol: max_pw_passlen

            但現在只有少量符號找不到了,我查看/lib下還有哪些exp,但是沒有發現和加密解密相關,我又查看/lib/syscalls.exp的內容,發現里面也只是一些符號表,我懷疑是否可以自己創建一個符號表。結果網上的一篇資料證實了我的想法,于是我創建一個名為StaticLinkScript的文件,輸入:
            #!
            encrypted_pw_passlen
            crypt_r
            max_history_size
            getpass_auto
            max_pw_passlen
            接著運行:
            # ld -o hello_s -bstatic hello.o -lc /usr/lib/crt0.o -bI:/lib/syscalls.exp -bI:StaticLinkScript
            雖然有些警告,但是hello_s還是生出來了。運行
            # ./hello_s
            Hello, world!成功出現,然后再運行
            # ls -l
            看到這個文件近3M,僅僅一個printf語句,可以估計這個是靜態鏈接出來的文件了
            -rw-r--r--    1 root     system           78 Nov 30 04:41 StaticLinkScript
            -rw-r--r--    1 root     system         1812 Dec 02 07:52 crt0.syms
            -rw-r--r--    1 root     system           64 Nov 29 09:39 hello.c
            -rw-r--r--    1 root     system         1100 Dec 02 07:28 hello.o
            -rwxr-xr-x    1 root     system      2963741 Dec 02 08:28 hello_s
            -rw-r--r--    1 root     system        36438 Dec 02 08:00 out.txt
            -r-xr-xr-x    1 root     system      5111233 Dec 02 08:03 shr.o
            -rw-r--r--    1 root     system       657423 Nov 30 03:41 shr.syms
            在運行
            ldd hello_s
            結果
            hello_s needs:
                     /unix
            這充分證明hello_s是靜態出鏈接出來的。好了,有了上面的經歷,后面就簡單了

            2,使用庫文件libc.a,動態鏈接成可執行程序
            我們去掉-bstatic選項,運行
            # ld -o hello_d hello.o -lc /usr/lib/crt0.o -bI:/lib/syscalls.exp -bI:StaticLinkScript
            生成可以成功運行的可執行文件hello_d,我們再 運行
            # ldd hello_d
            輸出
            hello_d needs:
                     /usr/lib/libc.a(shr.o)
                     /unix
                     /usr/lib/libcrypt.a(shr.o)
            這說明hello_d是動態鏈接出來的。或者運行
            # ls -l
            得到
            -rwxr-xr-x    1 root     system         4402 Dec 02 08:37 hello_d
            -rwxr-xr-x    1 root     system      2963741 Dec 02 08:28 hello_s


            這里我們得到一個結論,Aix上其實沒有動態鏈接庫和靜態鏈接庫的概念,只有共享對象的概念: shared object,即so,拿到一個.so,你可以將它靜態鏈接到某個可執行程序上去,也可將它靜態鏈接到某個可執行程序上去。

            3,關于-bstatic選項和-nso選項
            手冊上說,它只將它之后的共享對象以靜態鏈接的方式鏈接起來,所以,我們來看看以下結果
            # ld -o hello_s -bstatic hello.o -lc /usr/lib/crt0.o -bI:/lib/syscalls.exp -bI:StaticLinkScript
            # ld -o hello_s2 -lc -bstatic hello.o /usr/lib/crt0.o -bI:/lib/syscalls.exp -bI:StaticLinkScript
            # ld -o hello_s3 hello.o -bstatic -lc /usr/lib/crt0.o -bI:/lib/syscalls.exp -bI:StaticLinkScript
            # ld -o hello_s4 -lc -bnso hello.o /usr/lib/crt0.o -bI:/lib/syscalls.exp -bI:StaticLinkScript
            # ls -l
            -rwxr-xr-x    1 root     system         4402 Dec 02 08:37 hello_d
            -rwxr-xr-x    1 root     system      2963741 Dec 02 08:28 hello_s
            -rwxr-xr-x    1 root     system         4402 Dec 02 08:38 hello_s2
            -rwxr-xr-x    1 root     system      2963741 Dec 02 08:39 hello_s3
            -rwxr-xr-x    1 root     system      2963741 Dec 02 09:13 hello_s4

            這驗證了-bstatic并不是讓所有共享對象以靜態方式鏈接。同樣,我們知道了.so和.o文件的區別,.so可以動態或靜態鏈接到結果,而.o好像只能靜態鏈接到結果,或者說.o根本就不是共享文件,不能用上動態鏈接的概念,只能說被鏈接,那么這里的鏈接就只能是將.o文件的靜態鏈接了
            另外,以上例子說明-bnso選項是對全局有效的。

            4,編寫“靜態鏈接庫”,和使用“靜態鏈接庫”
            按照我們第3步的分析,所謂的靜態鏈接庫可以認為就是.o文件,aix上又可以把文件打包成.a文件。難怪有人會說.a就是靜態鏈接庫
            我們先寫源文件mylib.h和mylib.c
            mylib.h
            C代碼 復制代碼
            1. void hello();   
            2. mylib.c   
            3. #include <stdio.h>   
            4. int m1 = 1;   
            5. char m2[10];   
            6. char *m3 = "jjww";   
            7.   
            8. void hello(){   
            9.   int i = 0;   
            10.   char name[10];   
            11.   name[0] = 'l';   
            12.   name[1] = 'i';   
            13.   name[2] = 'u';   
            14.   name[3] = '\0';   
            15.   
            16.   printf("success call from perl to c library: i=%d, name=%s, m3=%s\n", i, name, m3);   
            17. }  

            運行
            # xlc -o mylib.o -c mylib.c
            得到mylib.o,打包成mylib.a,運行
            ar -r mylib.a mylib.o
            好了,所謂的“靜態鏈接庫”就出來了
            編寫應用程序test_lib.c
            C代碼 復制代碼
            1. #include "mylib.h"   
            2. int main() {   
            3.   hello();   
            4. }  

            運行
            # xlc -o test_lib.o -c test_lib.c
            得到對象文件test_lib.o
            運行
            # ld -o test_lib_s test_lib.o mylib.o -bnso /usr/lib/crt0.o -lc -bI:/lib/syscalls.exp -bI:StaticLinkScript
            # ld -o test_lib_s2 test_lib.o mylib.a -bnso /usr/lib/crt0.o -lc -bI:/lib/syscalls.exp -bI:StaticLinkScript
            # ld -o test_lib_d test_lib.o mylib.o /usr/lib/crt0.o -lc -bI:/lib/syscalls.exp -bI:StaticLinkScript
            # ld -o test_lib_d2 test_lib.o mylib.a /usr/lib/crt0.o -lc -bI:/lib/syscalls.exp -bI:StaticLinkScript
            # mv mylib.a libmylib.a
            # ld -o test_lib_s3 test_lib.o -L"." -lmylib /usr/lib/crt0.o -lc -bI:/lib/syscalls.exp -bI:StaticLinkScript
            # ls -l 
            得到
            -rwxr-xr-x    1 root     system         4868 Dec 02 09:22 test_lib_d
            -rwxr-xr-x    1 root     system         4868 Dec 02 09:22 test_lib_d2
            -rwxr-xr-x    1 root     system      2964203 Dec 02 09:19 test_lib_s
            -rwxr-xr-x    1 root     system      2964203 Dec 02 09:19 test_lib_s2
            -rwxr-xr-x    1 root     system         4870 Dec 02 09:28 test_lib_s3
            前兩個語句我是靜態鏈接成可執行程序,接下來的兩個采用動態鏈接,最后一個,我仿照libc.a生成了一個libmylib.a,想動態鏈接mylib.a,但是發現test_lib_s3比test_lib_d和test_lib_d2略大,而且
            # ldd test_lib_s3
            得到
            test_lib_s3 needs:
                     /usr/lib/libc.a(shr.o)
                     /unix
                     /usr/lib/libcrypt.a(shr.o)
            依賴列表中沒有/libmylib.a,可以說明/libmylib.a還是被靜態鏈接的,就和其他的test_lib.o一樣

            5,編寫共享對象.so,和使用.so
            # xlc -o libmylib.so  -qmkshrobj mylib.c
            # xlc -o libmylib2.so -qmkshrobj -c mylib.c
            生成共享對象libmylib.so,注意前者沒有-c而后者有,libmylib2.so被生成為一般的oject文件,雖然其后綴是.so,比如
            # ldd libmylib.so
            輸出
            libmylib.so needs:
                     /usr/lib/libc.a(shr.o)
                     /unix
                     /usr/lib/libcrypt.a(shr.o)
            # ldd libmylib2.so
            輸出
            libmylib2.so needs:
            除了大小和mylib.o一樣外,libmylib2.so同樣不依賴任何庫
            運行
            # ld -o test_lib_ss  -lc libmylib.so test_lib.o -bnso /usr/lib/crt0.o -bI:/lib/syscalls.exp -bI:StaticLinkScript
            # ld -o test_lib_dd  -lc libmylib.so test_lib.o /usr/lib/crt0.o -bI:/lib/syscalls.exp -bI:StaticLinkScript
            # ld -o test_lib_dd2 -lc -L"." libmylib.so test_lib.o /usr/lib/crt0.o -bI:/lib/syscalls.exp -bI:StaticLinkScript
            # ldd test_lib_dd
            test_lib_dd needs:
                     /usr/lib/libc.a(shr.o)
            Cannot find libmylib.so
                     /unix
                     /usr/lib/libcrypt.a(shr.o)
            # ldd test_lib_dd2
            test_lib_dd2 needs:
                     /usr/lib/libc.a(shr.o)
                     ./libmylib.so
                     /unix
                     /usr/lib/libcrypt.a(shr.o)
            test_lib_dd雖然成功生成,但是文件有問題,從ldd test_lib_dd2的結果看出,/libmylib.so是被動態鏈接了

            參考資料
            ld手冊
            xlc手冊
            http://linux.chinaitlab.com/c/769617_2.html
            http://faq.csdn.net/read/201458.html
            http://post.doit.wisc.edu/library/aix51/usr/share/man/info/en_US/a_doc_lib/libs/basetrf1/crypt.htm
            http://blog.163.com/cn_prince/blog/static/638790120078289170781/
            http://blog.solrex.cn/articles/the-true-story-of-hello-world.html

            Feedback

            # re: Aix上使用庫文件和編寫庫文件[未登錄]  回復  更多評論   

            2015-10-27 21:50 by 東東
            很好的講解,學習了,感謝分享

            # re: Aix上使用庫文件和編寫庫文件  回復  更多評論   

            2015-12-01 15:00 by 藍藍
            真的很不錯,學習到很多
            久久国产乱子伦精品免费午夜| 国产精品久久久久久久久软件| 大香伊人久久精品一区二区| 婷婷国产天堂久久综合五月| 免费久久人人爽人人爽av| 国内精品久久久久影院亚洲| 久久亚洲AV成人无码国产| 久久国产精品99久久久久久老狼| 久久精品亚洲福利| 97久久精品人妻人人搡人人玩| 精品国产婷婷久久久| 国产亚洲美女精品久久久2020| 久久精品国产亚洲AV嫖农村妇女| 精品综合久久久久久88小说 | 久久精品国产影库免费看| 热久久国产欧美一区二区精品| 亚洲中文精品久久久久久不卡| 久久精品免费大片国产大片| 亚洲精品乱码久久久久久蜜桃不卡| 大香网伊人久久综合网2020| 亚洲AV无码久久精品成人| 久久强奷乱码老熟女| 亚洲午夜久久久精品影院 | 久久久久99这里有精品10| 99麻豆久久久国产精品免费| 伊人久久大香线焦AV综合影院 | 久久国产成人亚洲精品影院| 国产精品一区二区久久不卡| 蜜臀av性久久久久蜜臀aⅴ麻豆| 久久激情亚洲精品无码?V| 99热热久久这里只有精品68| 无码专区久久综合久中文字幕| 狠狠色丁香久久婷婷综合蜜芽五月| 久久国产成人| 亚洲国产成人久久一区久久| 久久久久国产一级毛片高清板| 精品熟女少妇aⅴ免费久久| 狠狠色伊人久久精品综合网| 国产免费久久精品丫丫| 久久午夜综合久久| 亚洲伊人久久成综合人影院 |