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

            Error

            C++博客 首頁 新隨筆 聯(lián)系 聚合 管理
              217 Posts :: 61 Stories :: 32 Comments :: 0 Trackbacks

            第一反應(yīng)是:居然沒有對應(yīng)的.so 和.a,dll搜索path居然是編譯階段就定好了。

            好吧,都是可以控制的


            靜態(tài)庫:

             對函數(shù)庫的鏈接是放在編譯時期(compile time)完成的。所有相關(guān)的對象文件(object file)與牽涉到的函數(shù)庫(library)被鏈接合成一個可執(zhí)行文件(executable file),即將動態(tài)庫內(nèi)容拷貝到自己需要的程序中,所以程序在運行時,與函數(shù)庫再無瓜葛,所以這些函數(shù)庫被成為靜態(tài)庫(static libaray),通常文件名為“libxxx.a”的形式。
             
                   在linux環(huán)境中, 使用ar命令創(chuàng)建靜態(tài)庫文件.如下是命令的選項: 
                      d -----從指定的靜態(tài)庫文件中刪除文件 
                      m -----把文件移動到指定的靜態(tài)庫文件中 
                      p -----把靜態(tài)庫文件中指定的文件輸出到標準輸出 
                      q -----快速地把文件追加到靜態(tài)庫文件中 
                      r -----把文件插入到靜態(tài)庫文件中 
                      t -----顯示靜態(tài)庫文件中文件的列表 
                      x -----從靜態(tài)庫文件中提取文件 
                      還有多個修飾符修改以上基本選項,詳細請man ar 以下列出三個: 
                      a -----把新的目標文件(*.o)添加到靜態(tài)庫文件中現(xiàn)有文件之后 
                      b -----***************************************之前 
                      v -----使用詳細模式       ar 命令的命令行格式如下:       ar [-]{dmpqrtx}[abcfilNoPsSuvV] [membername] [count] archive files...      eg:         ar -crs hello.a hello.c
            動態(tài)庫 :
             庫函數(shù)的鏈接載入推遲到程序運行的時期(runtime)。這就是如雷貫耳的動態(tài)鏈接庫(dynamic link library)技術(shù)。
            動態(tài)鏈接庫的特點與優(yōu)勢:
             1. 可以實現(xiàn)進程之間的資源共享。
             某個程序的在運行中要調(diào)用某個動態(tài)鏈接庫函數(shù)的時候,操作系統(tǒng)首先會查看所有正在運行的程序,看在內(nèi)存里是否已有此庫函數(shù)的拷貝了。如果有,則讓其共享那一個拷貝;只有沒有才鏈接載入。這樣的模式雖然會帶來一些“動態(tài)鏈接”額外的開銷,卻大大的節(jié)省了系統(tǒng)的內(nèi)存資源。C的標準庫就是動態(tài)鏈接庫,也就是說系統(tǒng)中所有運行的程序共享著同一個C標準庫的代碼段。
             2. 將一些程序升級變得簡單。用戶只需要升級動態(tài)鏈接庫,而無需重新編譯鏈接其他原有的代碼就可以完成整個程序的升級
             3. 甚至可以真正做到鏈接載入完全由程序員在程序代碼中控制。
                所有的函數(shù)本著“有需求才調(diào)入”的原則,于是大大節(jié)省了系統(tǒng)資源。

            動態(tài)鏈接庫的創(chuàng)建

             由于動態(tài)鏈接庫函數(shù)的共享特性,它們不會被拷貝到可執(zhí)行文件中。在編譯的時候,編譯器只會做一些函數(shù)名之類的檢查。在程序運行的時候,被調(diào)用的動態(tài)鏈接庫函數(shù)被安置在內(nèi)存的某個地方,所有調(diào)用它的程序?qū)⒅赶蜻@個代碼段。因此,這些代碼必須實用相對地址,而不是絕對地址。在編譯的時候,我們需要告訴編譯器,這些對象文件是用來做動態(tài)鏈接庫的,所以要用地址不無關(guān)代碼(Position Independent Code (PIC))。

            對gcc編譯器,只需添加上 -fPIC 標簽,如: 
            1.創(chuàng)建共享庫 
                 gcc -fPIC -c error.c                
                 gcc -fPIC -c errorlog.c
                 gcc -shared -o libapue.so error.o errorlog.o 
            這樣就創(chuàng)建了共享庫! 
            注意到最后一行,-shared 標簽告訴編譯器這是要建立動態(tài)鏈接庫。這與靜態(tài)鏈接庫的建立很不一樣,后者用的是 ar 命令。也注意到,動態(tài)鏈接庫的名字形式為 “libxxx.so” 后綴名為 “.so”

            2.編譯共享庫 
               
             使用動態(tài)鏈接庫,首先需要在編譯期間讓編譯器檢查一些語法與定義。

             這與靜態(tài)庫的實用基本一樣,用的是 -Lpath 和 -lxxx 標簽。如:

             gcc file1.o file2.o -Lpath -lxxx -o program.exe

             編譯器會先在path文件夾下搜索libxxx.so文件,如果沒有找到,繼續(xù)搜索libxxx.a(靜態(tài)庫)。

             在程序運行期間,也需要告訴系統(tǒng)去哪里找你的動態(tài)鏈接庫文件。在UNIX下是通過定義名為 LD_LIBRARY_PATH 的環(huán)境變量 來實現(xiàn)的。只需將path賦值給此變量即可。csh 命令為:

             setenv LD_LIBRARY_PATH your/full/path/to/dll

             一切安排妥當(dāng)后,你可以用 ldd 命令檢查是否連接正常。

             ldd program.exe

             

            如何才能讓動態(tài)加載器發(fā)現(xiàn)庫文件呢?有兩種方法可以解決: 
                 LD_LIBRARY_PATH 環(huán)境變量  
                 /etc/ld.so.conf文件 
                1.環(huán)境變量 
                   export LD_LIBRARY_PATH="dir$LD_LIBRARY_PATH" 
                2.修改/etc/ld.so.conf文件.位于/etc/ld.so.conf 
            一般應(yīng)用程序的庫文件不與系統(tǒng)庫文件放在同一個目錄下,一般把應(yīng)用程序的共享庫文件放在/usr/local/lib下,新建一個屬于自己的目錄apue,然后把剛才libapue.so復(fù)制過去就行了
            同時在/etc/ld.so.conf中新增一行: 
            /usr/local/lib/apue

            實例分析:
            1、動態(tài)庫的編譯

            下面通過一個例子來介紹如何生成一個動態(tài)庫。這里有一個頭文件:so_test.h,三個.c文件:test_a.c、test_b.c、test_c.c,我們將這幾個文件編譯成一個動態(tài)庫:libtest.so。

            so_test.h:

            #include 
            #include

            void test_a();
            void test_b();
            void test_c();


            test_a.c:

            #include "so_test.h"
            void test_a()
            {
             printf("this is in test_a.../n");
            }


            test_b.c:
            #include "so_test.h"
            void test_b()
            {
             printf("this is in test_b.../n");
            }

            test_a.c:

            #include "so_test.h"
            void test_c()
            {
             printf("this is in test_c.../n");
            }

            將這幾個文件編譯成一個動態(tài)庫:libtest.so
            $ gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so

            2、動態(tài)庫的鏈接

            在1、中,我們已經(jīng)成功生成了一個自己的動態(tài)鏈接庫libtest.so,下面我們通過一個程序來調(diào)用這個庫里的函數(shù)。程序的源文件為:test.c。

            test.c:

            #include "so_test.h"
            int main()
            {
            test_a();
            test_b();
            test_c();
            return 0;

            }

            l 將test.c與動態(tài)庫libtest.so鏈接生成執(zhí)行文件test:

            $ gcc test.c -L. -ltest -o test

            l 測試是否動態(tài)連接,如果列出libtest.so,那么應(yīng)該是連接正常了

            $ ldd test

            l 執(zhí)行test,可以看到它是如何調(diào)用動態(tài)庫中的函數(shù)的。
            3、編譯參數(shù)解析
            最主要的是GCC命令行的一個選項:
            -shared 該選項指定生成動態(tài)連接庫(讓連接器生成T類型的導(dǎo)出符號表,有時候也生成弱連接W類型的導(dǎo)出符號),不用該標志外部程序無法連接。相當(dāng)于一個可執(zhí)行文件

            l -fPIC:表示編譯為位置獨立的代碼,不用此選項的話編譯后的代碼是位置相關(guān)的所以動態(tài)載入時是通過代碼拷貝的方式來滿足不同進程的需要,而不能達到真正代碼段共享的目的。

            l -L.:表示要連接的庫在當(dāng)前目錄中

            l -ltest:編譯器查找動態(tài)連接庫時有隱含的命名規(guī)則,即在給出的名字前面加上lib,后面加上.so來確定庫的名稱

            l LD_LIBRARY_PATH:這個環(huán)境變量指示動態(tài)連接器可以裝載動態(tài)庫的路徑。

            l 當(dāng)然如果有root權(quán)限的話,可以修改/etc/ld.so.conf文件,然后調(diào)用 /sbin/ldconfig來達到同樣的目的,不過如果沒有root權(quán)限,那么只能采用輸出LD_LIBRARY_PATH的方法了。
            4、注意

            調(diào)用動態(tài)庫的時候有幾個問題會經(jīng)常碰到,有時,明明已經(jīng)將庫的頭文件所在目錄 通過 “-I” include進來了,庫所在文件通過 “-L”參數(shù)引導(dǎo),并指定了“-l”的庫名,但通過ldd命令察看時,就是死活找不到你指定鏈接的so文件,這時你要作的就是通過修改 LD_LIBRARY_PATH或者/etc/ld.so.conf文件來指定動態(tài)庫的目錄。通常這樣做就可以解決庫無法鏈接的問題了。

              3: 如果出現(xiàn)下列錯誤
                      ./test: error while loading shared libraries: libtest.so: cannot open   shared object file: No such file or directory
                  解決方法:
                   1: export LD_LIBRARY_PATH=DIR:$LD_LIBRARY_PATH 
                   2: 修改文件/etc/ld.so.config文件,在末行加上你的庫文件目錄,最后,ldconfig刷新ld.so.cache文件即可。可以用strings命令查看ld.so.cache是否刷新:strings /etc/ld.so.cache | grep print
                 
            4:   ldd命令查看動態(tài)連接庫
                        
                        linux-gate.so.1 =>  (0xb7f0e000)
                        libprint.so => not found
                        libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7d82000)
                        /lib/ld-linux.so.2 (0xb7ef4000)
            5 : nm查看程序中有那些符號
                  
            049f18 d _DYNAMIC
            08049ff4 d _GLOBAL_OFFSET_TABLE_
            080485cc R _IO_stdin_used
                     w _Jv_RegisterClasses
            08049f08 d __CTOR_END__
            08049f04 d __CTOR_LIST__
            08049f10 D __DTOR_END__
            08049f0c d __DTOR_LIST__
            080485ec r __FRAME_END__
            08049f14 d __JCR_END__
            08049f14 d __JCR_LIST__
            0804a018 A __bss_start
            0804a010 D __data_start
            08048580 t __do_global_ctors_aux
            08048450 t __do_global_dtors_aux

            6: strip取出程序中符號
            7: strings查看可執(zhí)行文件中的文本信息

            posted on 2014-01-14 19:29 Enic 閱讀(421) 評論(0)  編輯 收藏 引用

            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            香蕉99久久国产综合精品宅男自 | 亚洲一区中文字幕久久| 合区精品久久久中文字幕一区 | 久久精品中文字幕一区| 久久久青草青青国产亚洲免观| 久久久久久免费一区二区三区| 久久不见久久见免费视频7| 色妞色综合久久夜夜| 伊人久久大香线蕉精品不卡| 久久无码人妻精品一区二区三区 | 2021最新久久久视精品爱| 天天影视色香欲综合久久| 香蕉久久夜色精品国产尤物| 天天做夜夜做久久做狠狠| 精品视频久久久久| 久久综合久久鬼色| 久久综合鬼色88久久精品综合自在自线噜噜| 国产精品久久久99| 久久久黄片| 久久精品人妻中文系列| 午夜精品久久久久久久| 久久亚洲精品国产精品| 国内精品久久久久| 久久婷婷人人澡人人| 亚洲女久久久噜噜噜熟女| 久久偷看各类wc女厕嘘嘘| 国产精品久久久久久一区二区三区| 国产亚洲欧美成人久久片| 亚州日韩精品专区久久久| 伊人久久大香线蕉综合影院首页| 久久久精品人妻一区二区三区蜜桃 | 大蕉久久伊人中文字幕| 亚洲国产综合久久天堂 | 国产精自产拍久久久久久蜜| 久久精品国产一区二区电影| 免费精品久久天干天干| 嫩草影院久久99| 久久久久亚洲av成人网人人软件| 久久国产精品久久精品国产| 伊人久久大香线蕉综合5g| 久久无码av三级|