• <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>
            posts - 200, comments - 8, trackbacks - 0, articles - 0
            一、引言

            通常情況下,對(duì)函數(shù)庫(kù)的鏈接是放在編譯時(shí)期(compile time)完成的。所有相關(guān)的對(duì)象文件(object file)與牽涉到的函數(shù)庫(kù)(library)被鏈接合成一個(gè)可執(zhí)行文件(executable file)。程序運(yùn)行時(shí),與函數(shù)庫(kù)再無瓜葛,因?yàn)樗行枰暮瘮?shù)已拷貝到自己門下。所以這些函數(shù)庫(kù)被成為靜態(tài)庫(kù)(static libaray),通常文件名為“libxxx.a”的形式。

            其實(shí),我們也可以把對(duì)一些庫(kù)函數(shù)的鏈接載入推遲到程序運(yùn)行的時(shí)期(runtime)。這就是如雷貫耳的動(dòng)態(tài)鏈接庫(kù)(dynamic link library)技術(shù)。

            二、動(dòng)態(tài)鏈接庫(kù)的特點(diǎn)與優(yōu)勢(shì)

            首先讓我們來看一下,把庫(kù)函數(shù)推遲到程序運(yùn)行時(shí)期載入的好處:

            1. 可以實(shí)現(xiàn)進(jìn)程之間的資源共享。

            什么概念呢?就是說,某個(gè)程序的在運(yùn)行中要調(diào)用某個(gè)動(dòng)態(tài)鏈接庫(kù)函數(shù)的時(shí)候,操作系統(tǒng)首先會(huì)查看所有正在運(yùn)行的程序,看在內(nèi)存里是否已有此庫(kù)函數(shù)的拷貝了。如果有,則讓其共享那一個(gè)拷貝;只有沒有才鏈接載入。這樣的模式雖然會(huì)帶來一些“動(dòng)態(tài)鏈接”額外的開銷,卻大大的節(jié)省了系統(tǒng)內(nèi)存資源。C的標(biāo)準(zhǔn)庫(kù)就是動(dòng)態(tài)鏈接庫(kù),也就是說系統(tǒng)中所有運(yùn)行的程序共享著同一個(gè)C標(biāo)準(zhǔn)庫(kù)的代碼段。

            2. 將一些程序升級(jí)變得簡(jiǎn)單。用戶只需要升級(jí)動(dòng)態(tài)鏈接庫(kù),而無需重新編譯鏈接其他原有的代碼就可以完成整個(gè)程序的升級(jí)。Windows 就是一個(gè)很好的例子。

            3. 甚至可以真正坐到鏈接載入完全由程序員在程序代碼中控制。

            程序員在編寫程序的時(shí)候,可以明確的指明什么時(shí)候或者什么情況下,鏈接載入哪個(gè)動(dòng)態(tài)鏈接庫(kù)函數(shù)。你可以有一個(gè)相當(dāng)大的軟件,但每次運(yùn)行的時(shí)候,由于不同的操作需求,只有一小部分程序被載入內(nèi)存。所有的函數(shù)本著“有需求才調(diào)入”的原則,于是大大節(jié)省了系統(tǒng)資源。比如現(xiàn)在的軟件通常都能打開若干種不同類型的文件,這些讀寫操作通常都用動(dòng)態(tài)鏈接庫(kù)來實(shí)現(xiàn)。在一次運(yùn)行當(dāng)中,一般只有一種類型的文件將會(huì)被打開。所以直到程序知道文件的類型以后再載入相應(yīng)的讀寫函數(shù),而不是一開始就將所有的讀寫函數(shù)都載入,然后才發(fā)覺在整個(gè)程序中根本沒有用到它們。

            三、動(dòng)態(tài)鏈接庫(kù)的創(chuàng)建

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

            對(duì)gcc編譯器,只需添加上 -fPIC 標(biāo)簽,如:

            gcc -fPIC -c file1.c
            gcc -fPIC -c file2.c
            gcc -shared libxxx.so file1.o file2.o

            注意到最后一行,-shared 標(biāo)簽告訴編譯器這是要建立動(dòng)態(tài)鏈接庫(kù)。這與靜態(tài)鏈接庫(kù)的建立很不一樣,后者用的是 ar 命令。也注意到,動(dòng)態(tài)鏈接庫(kù)的名字形式為 “libxxx.so” 后綴名為 “.so”

            四、動(dòng)態(tài)鏈接庫(kù)的使用

            使用動(dòng)態(tài)鏈接庫(kù),首先需要在編譯期間讓編譯器檢查一些語(yǔ)法與定義。

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

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

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

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

            setenv LD_LIBRARY_PATH your/full/path/to/dll

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

            ldd program.exe


            動(dòng)態(tài)鏈接庫(kù)*.so的編譯與使用- -


            動(dòng)態(tài)庫(kù)*.so在linux下用c和c++編程時(shí)經(jīng)常會(huì)碰到,最近在網(wǎng)站找了幾篇文章介紹動(dòng)態(tài)庫(kù)的編譯和鏈接,總算搞懂了這個(gè)之前一直不太了解得東東,這里做個(gè)筆記,也為其它正為動(dòng)態(tài)庫(kù)鏈接庫(kù)而苦惱的兄弟們提供一點(diǎn)幫助。
            1、動(dòng)態(tài)庫(kù)的編譯

            下面通過一個(gè)例子來介紹如何生成一個(gè)動(dòng)態(tài)庫(kù)。這里有一個(gè)頭文件:so_test.h,三個(gè).c文件:test_a.c、test_b.c、test_c.c,我們將這幾個(gè)文件編譯成一個(gè)動(dòng)態(tài)庫(kù):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");
            }

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

            2、動(dòng)態(tài)庫(kù)的鏈接

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

            test.c:

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

            }

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

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

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

            $ ldd test

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

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

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

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

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

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

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

            久久久青草久久久青草| 久久综合综合久久综合| 狠狠色伊人久久精品综合网| 精品久久久无码中文字幕| AA级片免费看视频久久| 久久国产精品无| 亚洲狠狠婷婷综合久久久久| 久久久久99精品成人片欧美| 久久99精品久久久久久秒播| 午夜欧美精品久久久久久久| 久久久久久无码国产精品中文字幕| 亚洲精品午夜国产VA久久成人| 国产精品女同一区二区久久| 久久久久久精品免费看SSS| 91久久成人免费| 99re久久精品国产首页2020| 久久久久亚洲AV成人网人人网站| 久久精品国产免费| 久久久久无码精品国产不卡| 一本大道久久东京热无码AV| 精品多毛少妇人妻AV免费久久| WWW婷婷AV久久久影片| 久久无码高潮喷水| 久久影视国产亚洲| 国产福利电影一区二区三区久久久久成人精品综合| 久久精品国产欧美日韩| 老色鬼久久亚洲AV综合| 亚洲精品tv久久久久久久久| 久久久99精品成人片中文字幕| 久久伊人精品青青草原高清| 国产精品久久久久jk制服| 久久夜色精品国产噜噜噜亚洲AV| 免费精品久久天干天干| 武侠古典久久婷婷狼人伊人| 久久伊人五月天论坛| 日韩电影久久久被窝网| 色综合久久久久综合99| 香蕉99久久国产综合精品宅男自| 亚洲国产精品成人AV无码久久综合影院 | 热re99久久6国产精品免费| 热久久最新网站获取|