• <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>
            asm, c, c++ are my all
            -- Core In Computer
            posts - 139,  comments - 123,  trackbacks - 0

            /********************************************\
            |????歡迎轉載, 但請保留作者姓名和原文鏈接, 祝您進步并共勉!???? |
            \********************************************/


            Linux靜態、共享和動態庫之編程

            作者: Jerry Cat
            時間: 2006/04/21
            鏈接: http://www.shnenglu.com/jerysun0818/archive/2006/04/22/6065.html

            一.庫的分類
            ??? 有兩種說法, 如果熟悉WIN平臺下的DLL, 相信不難理解:

            ??? 庫可以有三種使用的形式:靜態、共享和動態.靜態庫的代碼在編譯時就已連接到開發人員開發的應用程序中, 而共享庫只是在程序開始運行時才載入, 在編譯時, 只是簡單地指定需要使用的庫函數.動態庫則是共享庫的另一種變化形式.動態庫也是在程序運行時載入, 但與共享庫不同的是, 使用的庫函數不是在程序運行開始, 而是在程序中的語句需要使用該函數時才載入.動態庫可以在程序運行期間釋放動態庫所占用的內存, 騰出空間供其它程序使用.由于共享庫和動態庫并沒有在程序中包括庫函數的內容, 只是包含了對庫函數的引用, 因此代碼的規模比較小.

            ??? Linux下的庫文件分為共享庫和靜態庫兩大類, 它們兩者的差別僅在程序執行時所需的代碼是在運行時動態加載的, 還是在編譯時靜態加載的.區分庫類型最好的方法是看它們的文件后綴, 通常共享庫以.so(Shared Object的縮寫)結尾, 靜態鏈接庫通常以.a結尾(Archive的縮寫).在終端缺省情況下, 共享庫通常為綠色, 而靜態庫為黑色.

            ???? 已經開發的大多數庫都采取共享庫的方式.ELF格式的可執行文件使得共享庫能夠比較容易地實現, 當然使用舊的a.out模式也可以實現庫的共享.Linux系統中目前可執行文件的標準格式為ELF格式.

              .a的是為了支持較老的a.out格式的可執行文件的
              .so的是支持elf格式的可執行文件的庫.

             ? .a是靜態庫文件, 可以用ar 命令生成.
              .so是動態庫文件, 編譯時加上指定的選項即可生成, 具體選項看相應的系統文檔了.

            二.庫的命名規則
            ??? GNU庫的使用必須遵守Library GNU Public License(LGPL許可協議).該協議與GNU許可協議略有不同, 開發人員可以免費使用GNU庫進行軟件開發, 但必須保證向用戶提供所用的庫函數的源代碼.

              系統中可用的庫都存放在/usr/lib和/lib目錄中.庫文件名由前綴lib和庫名以及后綴組成.根據庫的類型不同, 后綴名也不一樣.共享庫的后綴名由.so和版本號組成, 靜態庫的后綴名為.a.采用舊的a.out格式的共享庫的后綴名為.sa.
              libname.so.major.minor
              libname.a

              這里的name可以是任何字符串, 用來唯一標識某個庫.該字符串可以是一個單字、幾個字符、甚至一個字母.數學共享庫的庫名為libm.so.5, 這里的標識字符為m, 版本號為5.libm.a則是靜態數學庫.X-Windows庫名為libX11.so.6, 這里使用X11作為庫的標識, 版本號為6.

            三.庫操作命令

            ?? Linux庫操作可以使用命令完成, 目前常用的命令是ldd和ldconfig.

            ?? 1.ldd
            ?ldd是Library Dependency Display縮寫, 它的作用是顯示一個可執行程序必須使用的共享庫.

            ?$ ldd /usr/bin/mesg
            ?libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7eaf000)
            ?/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0xb7feb000)

            ?? 2.ldconfig
            ?庫安裝到系統以后, 為了讓動態鏈接庫為系統所認識及共享, 就需要運行ldconfig.ldconfig命令的用途, 主要是在默認搜尋目錄(/lib和/usr/lib)以及動態庫配置文件/etc/ld.so.conf內所列的目錄下, 搜索出可共享的動態鏈接庫(格式如lib*.so*), 進而創建出動態裝入程序(ld.so)所需的連接和緩存文件.緩存文件默認為/etc/ld.so.cache, 此文件保存已排好序的動態鏈接庫名字列表, ldconfig通常在系統啟動時運行, 而當用戶安裝了一個新的動態鏈接庫時,就需要手工運行這個命令.

            ???? (1)命令格式
            ?ldconfig [選項] [libs]

            ???? (2)主要選項
            ?-v或--verbose ldconfig將顯示正在掃描的目錄、搜索到的動態鏈接庫, 以及它所創建的連接的名字.

            ?-f CONF 指定動態鏈接庫的配置文件為CONF, 系統默認為/etc/ld.so.conf.

            ?-C CACHE 指定生成的緩存文件為CACHE, 系統默認的是/etc/ld.so.cache,文件存放已排好序的可共享的動態鏈接庫的列表.

            ?-p或--print-cache 讓ldconfig打印出當前緩存文件所保存的所有共享庫的名字.

            ?-r ROOT 改變應用程序的根目錄為ROOT.

            ?-n ldconfig僅掃描命令行指定的目錄, 不掃描默認目錄(/lib、/usr/lib),也不掃描配置文件/etc/ld.so.conf所列的目錄.

            ?運行沒有選項的ldconfig命令時, 用于更新高速緩沖文件.這個命令主要用于高速緩沖DNS服務器(Caching DNS Server).高速緩沖DNS服務器的原理是提供查詢的歷史記錄, 并且利用這些記錄來提高查詢的效率.

            ?當某個查詢是第一次被發送到高速緩沖DNS服務器時, 高速緩沖DNS服務器就將此查詢的整個過程記錄下來, 在一定的時期內用它來回答所有相同的查詢, 從而減少整個DNS系統的負擔并且提高查詢速度.

            四.庫的升級

            ?Linux系統軟件更新很快, 新的核心幾乎每幾個星期就公布一次, 其它軟件的更新也是非常頻繁.多數情況下, 盲目跟隨潮流的升級并不必要, 如果確實需要新版本的特性時再升級.換句話說, 不要為了升級而升級.Linux系統中多數軟件都是用共享庫來編譯的, 其中包含了在不同程序之間共享的公用子例程.

            在運行某個程序時, 如果看到如下信息:“Incompatible library version.”則表明需要將該庫升級到程序所需要的版本.庫是向下兼容的, 也就是說, 用老版本庫編譯的程序可以在新安裝的版本庫上運行, 反之則不行.

            Linux庫函數的升級是一項重要的工作, 往往與其它軟件包的升級有一定關聯作用, 所以操作前一定要備份文件.下面看一下如何把Glibc 2.2.4.13升級至2.3.2版本, 其過程如下:

            ? 1.下載.gz壓縮文件并解壓

            在GUN C網站下載的四個.gz壓縮文件, 解壓至一臨時目錄中:
            cd /usr/caolinux
            tar xzvf glibc-2.3.2.tar.gz
            cd glibc-2.3.2
            tar xzvf ../glibc-linuxthreads-2.3.2.tar.gz
            tar xzvf ../glibc-crypt-2.3.2.tar.gz
            tar xzvf ../glibc-localedata-2.3.2.tar.gz

            ? 2.建立庫函數的安裝目錄
            mkdir /usr/higlibc
            cd /usr/higlibc

            ?? 3.建立編譯目錄
            mkdir cao
            cd cao
            ./configure --enable-add-ons=linuxthreads,crypt,localedata -prefix=/usr/higlibc

            ? 4.編譯與安裝
            make
            make check
            make install

            ? 5.改變數據庫的鏈接
            ln -s /usr/higlibc/lib/ld-linux.so.2 /lib/ld-linux.so.2

            然后, 修改/etc/ld.so.conf, 加入一行/usr/higlibc/lib, 執行下面代碼:
            ldconfig -v

            更新/etc/ld.so.cache的內容, 列出每個庫的版本號, 掃描目錄和所要創建及更新的鏈接.

            ?6.更改GCC設置

            cd /usr/lib/gcc-lib
            cp -r i386-redhat-linux higlibc

            ?7.更新符號鏈接
            cd /usr/higlibc/include
            ln -s /usr/src/linux/include/linux
            ln -s /usr/src/linux/include/asm
            ln -s /usr/X11R6/include/X11

            8.測試并完成

            五.高級共享庫特性
            ?1. soname

            共享庫的一個非常重要的, 也是非常難的概念是 soname——簡寫共享目標名(short for shared object name).這是一個為共享庫(.so)文件而內嵌在控制數據中的名字.如前面提到的, 每一個程序都有一個需要使用的庫的清單.這個清單的內容是一系列庫的 soname, 如同 ldd 顯示的那樣, 共享庫裝載器必須找到這個清單.

            soname 的關鍵功能是它提供了兼容性的標準.當要升級系統中的一個庫時, 并且新庫的 soname 和老的庫的 soname 一樣, 用舊庫連接生成的程序, 使用新的庫依然能正常運行.這個特性使得在 Linux 下, 升級使用共享庫的程序和定位錯誤變得十分容易.

            在 Linux 中, 應用程序通過使用 soname, 來指定所希望庫的版本.庫作者也可以通過保留或者改變 soname 來聲明, 哪些版本是相互兼容的, 這使得程序員擺脫了共享庫版本沖突問題的困擾.

            查看/usr/local/lib 目錄, 分析 MiniGUI 的共享庫文件之間的關系

            2. 共享庫裝載器

            當程序被調用的時候, Linux 共享庫裝載器(也被稱為動態連接器)也自動被調用.它的作用是保證程序所需要的所有適當版本的庫都被調入內存.共享庫裝載器名字是 ld.so 或者是 ld-linux.so, 這取決于 Linux libc 的版本, 它必須使用一點外部交互, 才能完成自己的工作.然而它接受在環境變量和配置文件中的配置信息.

            文件 /etc/ld.so.conf 定義了標準系統庫的路徑.共享庫裝載器把它作為搜索路徑.為了改變這個設置, 必須以 root 身份運行 ldconfig 工具.這將更新 /etc/ls.so.cache 文件, 這個文件其實是裝載器內部使用的文件之一.

            3. 使用 dlopen

            另外一個強大的庫函數是 dlopen().該函數將打開一個新庫, 并把它裝入內存.該函數主要用來加載庫中的符號, 這些符號在編譯的時候是不知道的.比如 Apache Web 服務器利用這個函數在運行過程中加載模塊, 這為它提供了額外的能力.一個配置文件控制了加載模塊的過程.這種機制使得在系統中添加或者刪除一個模塊時, 都不需要重新編譯了.

            可以在自己的程序中使用 dlopen().dlopen() 在 dlfcn.h 中定義, 并在 dl 庫中實現.它需要兩個參數:一個文件名和一個標志.文件名可以是我們學習過的庫中的 soname.標志指明是否立刻計算庫的依賴性.如果設置為 RTLD_NOW 的話, 則立刻計算;如果設置的是 RTLD_LAZY, 則在需要的時候才計算.另外, 可以指定 RTLD_GLOBAL, 它使得那些在以后才加載的庫可以獲得其中的符號.

            當庫被裝入后, 可以把 dlopen() 返回的句柄作為給 dlsym() 的第一個參數, 以獲得符號在庫中的地址.使用這個地址, 就可以獲得庫中特定函數的指針, 并且調用裝載庫中的相應函數.

            六、LINUX下動態鏈接庫的使用
            重要的dlfcn.h頭文件
            LINUX下使用動態鏈接庫, 源程序需要包含dlfcn.h頭文件, 此文件定義了調用動態鏈接庫的函數的原型.下面詳細說明一下這些函數.
            1. dlerror
            原型為: const char *dlerror(void);
            當動態鏈接庫操作函數執行失敗時, dlerror可以返回出錯信息, 返回值為NULL時表示操作函數執行成功.
            2. dlopen
            原型為: void *dlopen (const char *filename, int flag);
            dlopen用于打開指定名字(filename)的動態鏈接庫, 并返回操作句柄.
            filename: 如果名字不以/開頭, 則非絕對路徑名, 將按下列先后順序查找該文件.
            (1) 用戶環境變量中的LD_LIBRARY值;
            (2) 動態鏈接緩沖文件/etc/ld.so.cache
            (3) 目錄/lib, /usr/lib
            flag表示在什么時候解決未定義的符號(調用).取值有兩個:
            1) RTLD_LAZY : 表明在動態鏈接庫的函數代碼執行時解決.
            2) RTLD_NOW : 表明在dlopen返回前就解決所有未定義的符號, 一旦未解決, dlopen將返回錯誤.
            dlopen調用失敗時, 將返回NULL值, 否則返回的是操作句柄.
            3. dlsym : 取函數執行地址
            原型為: void *dlsym(void *handle, char *symbol);
            dlsym根據動態鏈接庫操作句柄(handle)與符號(symbol), 返回符號對應的函數的執行代碼地址.由此地址, 可以帶參數執行相應的函數.
            如程序代碼: void (*add)(int x,int y); /* 說明一下要調用的動態函數add */
            add=dlsym("xxx.so","add"); /* 打開xxx.so共享庫,取add函數地址 */
            add(89,369); /* 帶兩個參數89和369調用add函數 */
            4. dlclose : 關閉動態鏈接庫
            原型為: int dlclose (void *handle);
            dlclose用于關閉指定句柄的動態鏈接庫, 只有當此動態鏈接庫的使用計數為0時,才會真正被系統卸載.

            posted on 2006-04-22 01:32 Jerry Cat 閱讀(3425) 評論(1)  編輯 收藏 引用

            FeedBack:
            # re: Linux靜態、共享和動態庫之編程
            2009-08-25 19:46 | Haifeng
            精辟  回復  更多評論
              

            <2006年4月>
            2627282930311
            2345678
            9101112131415
            16171819202122
            23242526272829
            30123456

            常用鏈接

            留言簿(7)

            隨筆檔案

            最新隨筆

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            国产亚洲婷婷香蕉久久精品| 亚洲精品国产自在久久| 国产精品无码久久久久久| 国产精品久久久久jk制服| 国产香蕉97碰碰久久人人| 久久久亚洲裙底偷窥综合| 久久久精品国产sm调教网站| 久久久久亚洲?V成人无码| 久久综合给合久久狠狠狠97色69| 中文字幕成人精品久久不卡| 亚洲va中文字幕无码久久不卡| 国产精品狼人久久久久影院| 人妻无码中文久久久久专区| 欧美精品福利视频一区二区三区久久久精品 | 久久人人爽人人爽人人片AV东京热 | 91精品久久久久久无码| 怡红院日本一道日本久久 | 久久伊人色| 国内精品久久久久伊人av| 麻豆av久久av盛宴av| 精品熟女少妇aⅴ免费久久| 丁香狠狠色婷婷久久综合| 国内精品伊人久久久久777| 欧美日韩中文字幕久久久不卡| 久久青青草原综合伊人| 久久久久亚洲AV成人片| 亚洲精品乱码久久久久久久久久久久| 日韩十八禁一区二区久久| 久久久久婷婷| 亚洲国产成人久久笫一页| 久久精品国产亚洲av瑜伽| 国产精品VIDEOSSEX久久发布| 国产精品久久久久无码av| 久久久久亚洲av无码专区喷水| 久久亚洲美女精品国产精品| 亚洲国产精品无码久久| 欧美一区二区三区久久综合| 亚洲精品国产字幕久久不卡| 久久久久久亚洲精品成人 | 欧美性大战久久久久久| 久久久久99精品成人片三人毛片|