• <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>
            隨筆-4  評論-40  文章-117  trackbacks-0


            一、基本概念

            1.1什么是庫

            在windows平臺和linux平臺下都大量存在著庫。

            本質上來說庫是一種可執(zhí)行代碼的二進制形式,可以被操作系統(tǒng)載入內(nèi)存執(zhí)行。

            由于windows和linux的平臺不同(主要是編譯器、匯編器和連接器的不同),因此二者庫的二進制是不兼容的。

            本文僅限于介紹linux下的庫。

             

             

            1.2庫的種類

            linux下的庫有兩種:靜態(tài)庫和共享庫(動態(tài)庫)。

            二者的不同點在于代碼被載入的時刻不同。

            靜態(tài)庫的代碼在編譯過程中已經(jīng)被載入可執(zhí)行程序,因此體積較大。

            共享庫的代碼是在可執(zhí)行程序運行時才載入內(nèi)存的,在編譯過程中僅簡單的引用,因此代碼體積較小。

             

             

            1.3庫存在的意義

            庫是別人寫好的現(xiàn)有的,成熟的,可以復用的代碼,你可以使用但要記得遵守許可協(xié)議。

            現(xiàn)實中每個程序都要依賴很多基礎的底層庫,不可能每個人的代碼都從零開始,因此庫的存在意義非同尋常。

            共享庫的好處是,不同的應用程序如果調用相同的庫,那么在內(nèi)存里只需要有一份該共享庫的實例。

             

             

            1.4庫文件是如何產(chǎn)生的在linux下

            靜態(tài)庫的后綴是.a,它的產(chǎn)生分兩步

            Step 1.由源文件編譯生成一堆.o,每個.o里都包含這個編譯單元的符號表

            Step 2.ar命令將很多.o轉換成.a,成為靜態(tài)庫

            動態(tài)庫的后綴是.so,它由gcc加特定參數(shù)編譯產(chǎn)生。

            具體方法參見后文實例。

             

            1.5庫文件是如何命名的,有沒有什么規(guī)范

            在linux下,庫文件一般放在/usr/lib和/lib下,

            靜態(tài)庫的名字一般為libxxxx.a,其中xxxx是該lib的名稱

            動態(tài)庫的名字一般為libxxxx.so.major.minor,xxxx是該lib的名稱,major是主版本號, minor是副版本號

             

             

            1.6如何知道一個可執(zhí)行程序依賴哪些庫

            ldd命令可以查看一個可執(zhí)行程序依賴的共享庫,

            例如# ldd /bin/lnlibc.so.6

            => /lib/libc.so.6 (0×40021000)/lib/ld-linux.so.2

            => /lib/ld- linux.so.2 (0×40000000)

            可以看到ln命令依賴于libc庫和ld-linux庫

             

             

            1.7可執(zhí)行程序在執(zhí)行的時候如何定位共享庫文件

            當系統(tǒng)加載可執(zhí)行代碼時候,能夠知道其所依賴的庫的名字,但是還需要知道絕對路徑。

            此時就需要系統(tǒng)動態(tài)載入器(dynamic linker/loader)

            對于elf格式的可執(zhí)行程序,是由ld-linux.so*來完成的,它先后搜索elf文件的 DT_RPATH段—環(huán)境變量LD_LIBRARY_PATH—/etc/ld.so.cache文件列表—/lib/,/usr/lib目錄找到庫文件后將其載入內(nèi)存

            如:export LD_LIBRARY_PATH=’pwd’

            將當前文件目錄添加為共享目錄

             

            1.8在新安裝一個庫之后如何讓系統(tǒng)能夠找到他

            如果安裝在/lib或者/usr/lib下,那么ld默認能夠找到,無需其他操作。

            如果安裝在其他目錄,需要將其添加到/etc/ld.so.cache文件中,步驟如下

            1.編輯/etc/ld.so.conf文件,加入庫文件所在目錄的路徑

            2.運行l(wèi)dconfig,該命令會重建/etc/ld.so.cache文件


            二、用gcc生成靜態(tài)和動態(tài)鏈接庫的示例

            我們通常把一些公用函數(shù)制作成函數(shù)庫,供其它程序使用。

            函數(shù)庫分為靜態(tài)庫和動態(tài)庫兩種。

             

            靜態(tài)庫在程序編譯時會被連接到目標代碼中,程序運行時將不再需要該靜態(tài)庫。

             

            動態(tài)庫在程序編譯時并不會被連接到目標代碼中,而是在程序運行是才被載入,因此在程序運行時還需要動態(tài)庫存在。

             

            本文主要通過舉例來說明在Linux中如何創(chuàng)建靜態(tài)庫和動態(tài)庫,以及使用它們。

             

            為了便于闡述,我們先做一部分準備工作。

             

            2.1準備好測試代碼hello.h、hello.c和main.c;

            hello.h(見程序1)為該函數(shù)庫的頭文件。

             

            hello.c(見程序2)是函數(shù)庫的源程序,其中包含公用函數(shù)hello,該函數(shù)將在屏幕上輸出"Hello XXX!"。

             

            main.c(見程序3)為測試庫文件的主程序,在主程序中調用了公用函數(shù)hello。

             

             程序1: hello.h

            #ifndef HELLO_H 
            #define HELLO_H 
              
            void hello(const char *name); 
              
            #endif


            程序2:hello.c

            #include <stdio.h> 
            void hello(const char *name) { 

                    printf("Hello %s!\n", name); 
            }


            程序3:main.c

            #include "hello.h" 
             int main() 
             { 
                 hello("everyone"); 
                 return 0; 
             }

            2.2問題的提出

            注意:這個時候,我們編譯好的hello.o是無法通過gcc –o 編譯的,這個道理非常簡單,

            hello.c是一個沒有main函數(shù)的.c程序,因此不夠成一個完整的程序,如果使用gcc –o 編譯并連接它,GCC將報錯。

            無論靜態(tài)庫,還是動態(tài)庫,都是由.o文件創(chuàng)建的。因此,我們必須將源程序hello.c通過gcc先編譯成.o文件。

            這個時候我們有三種思路:

            1)  通過編譯多個源文件,直接將目標代碼合成一個.o文件。

            2)  通過創(chuàng)建靜態(tài)鏈接庫libmyhello.a,使得main函數(shù)調用hello函數(shù)時可調用靜態(tài)鏈接庫。

            3)  通過創(chuàng)建動態(tài)鏈接庫libmyhello.so,使得main函數(shù)調用hello函數(shù)時可調用靜態(tài)鏈接庫。

            2.3思路一:編譯多個源文件

            在系統(tǒng)提示符下鍵入以下命令得到hello.o文件。

            # gcc -c hello.c

            為什么不使用gcc–o hello hello.cpp 這個道理我們之前已經(jīng)說了,使用-c是什么意思呢?這涉及到gcc 編譯選項的常識。

             

            我們通常使用的gcc –o 是將.c源文件編譯成為一個可執(zhí)行的二進制代碼(-o選項其實是制定輸出文件文件名,如果不加-c選項,gcc默認會編譯連接生成可執(zhí)行文件,文件的名稱有-o選項指定),這包括調用作為GCC內(nèi)的一部分真正的C編譯器(ccl),以及調用GNU C編譯器的輸出中實際可執(zhí)行代碼的外部GNU匯編器(as)和連接器工具(ld)。

            gcc –c是使用GNU匯編器將源文件轉化為目標代碼之后就結束,在這種情況下,只調用了C編譯器(ccl)和匯編器(as),而連接器(ld)并沒有被執(zhí)行,所以輸出的目標文件不會包含作為Linux程序在被裝載和執(zhí)行時所必須的包含信息,但它可以在以后被連接到一個程序。

            我們運行ls命令看看是否生存了hello.o文件。

            # ls

            hello.c hello.h hello.o main.c

             

            ls命令結果中,我們看到了hello.o文件,本步操作完成。

             

            同理編譯main

            #gcc –c main.c

             

            將兩個文件鏈接成一個.o文件。

            #gcc –o hello hello.o main.o

             

            運行

            # ./hello

             

            Hello everyone!

             

            完成^ ^!

            2.4思路二:靜態(tài)鏈接庫

             

            下面我們先來看看如何創(chuàng)建靜態(tài)庫,以及使用它。

             

            靜態(tài)庫文件名的命名規(guī)范是以lib為前綴,緊接著跟靜態(tài)庫名,擴展名為.a。例如:我們將創(chuàng)建的靜態(tài)庫名為myhello,則靜態(tài)庫文件名就是libmyhello.a。在創(chuàng)建和使用靜態(tài)庫時,需要注意這點。創(chuàng)建靜態(tài)庫用ar命令

             

            在系統(tǒng)提示符下鍵入以下命令將創(chuàng)建靜態(tài)庫文件libmyhello.a

             

            # ar rcs libmyhello.a hello.o

             

             

            我們同樣運行ls命令查看結果:

             

            # ls

             

            hello.c  hello.h hello.o libmyhello.a main.c

             

            ls命令結果中有libmyhello.a

             

            靜態(tài)庫制作完了,如何使用它內(nèi)部的函數(shù)呢?只需要在使用到這些公用函數(shù)的源程序中包含這些公用函數(shù)的原型聲明,然后在用gcc命令生成目標文件時指明靜態(tài)庫名,gcc將會從靜態(tài)庫中將公用函數(shù)連接到目標文件中。注意,gcc會在靜態(tài)庫名前加上前綴lib,然后追加擴展名.a得到的靜態(tài)庫文件名來查找靜態(tài)庫文件,因此,我們在寫需要連接的庫時,只寫名字就可以,如libmyhello.a的庫,只寫:-lmyhello

             

            在程序3:main.c中,我們包含了靜態(tài)庫的頭文件hello.h,然后在主程序main中直接調用公用函數(shù)hello。下面先生成目標程序hello,然后運行hello程序看看結果如何。

             

            # gcc -o hello main.c -static -L. -lmyhello

             

            # ./hello

             

            Hello everyone!

             

            我們刪除靜態(tài)庫文件試試公用函數(shù)hello是否真的連接到目標文件 hello中了。

             

            # rm libmyhello.a

             

            rm: remove regular file `libmyhello.a'? y

             

            # ./hello

             

            Hello everyone!

             

            程序照常運行,靜態(tài)庫中的公用函數(shù)已經(jīng)連接到目標文件中了。

            靜態(tài)鏈接庫的一個缺點是,如果我們同時運行了許多程序,并且它們使用了同一個庫函數(shù),這樣,在內(nèi)存中會大量拷貝同一庫函數(shù)。這樣,就會浪費很多珍貴的內(nèi)存和存儲空間。使用了共享鏈接庫的Linux就可以避免這個問題。

            共享函數(shù)庫和靜態(tài)函數(shù)在同一個地方,只是后綴有所不同。比如,在一個典型的Linux系統(tǒng),標準的共享數(shù)序函數(shù)庫是/usr/lib/libm.so。

            當一個程序使用共享函數(shù)庫時,在連接階段并不把函數(shù)代碼連接進來,而只是鏈接函數(shù)的一個引用。當最終的函數(shù)導入內(nèi)存開始真正執(zhí)行時,函數(shù)引用被解析,共享函數(shù)庫的代碼才真正導入到內(nèi)存中。這樣,共享鏈接庫的函數(shù)就可以被許多程序同時共享,并且只需存儲一次就可以了。共享函數(shù)庫的另一個優(yōu)點是,它可以獨立更新,與調用它的函數(shù)毫不影響。

            2.5思路三、動態(tài)鏈接庫(共享函數(shù)庫)

             

            我們繼續(xù)看看如何在Linux中創(chuàng)建動態(tài)庫。我們還是從.o文件開始。

             

            動態(tài)庫文件名命名規(guī)范和靜態(tài)庫文件名命名規(guī)范類似,也是在動態(tài)庫名增加前綴lib,但其文件擴展名為.so。例如:我們將創(chuàng)建的動態(tài)庫名為myhello,則動態(tài)庫文件名就是libmyhello.so。用gcc來創(chuàng)建動態(tài)庫。

             

            在系統(tǒng)提示符下鍵入以下命令得到動態(tài)庫文件libmyhello.so

             

            # gcc -shared -fPIC -o libmyhello.so hello.o

             

             “PIC”命令行標記告訴GCC產(chǎn)生的代碼不要包含對函數(shù)和變量具體內(nèi)存位置的引用,這是因為現(xiàn)在還無法知道使用該消息代碼的應用程序會將它連接到哪一段內(nèi)存地址空間。這樣編譯出的hello.o可以被用于建立共享鏈接庫。建立共享鏈接庫只需要用GCC”-shared”標記即可。

             

            我們照樣使用ls命令看看動態(tài)庫文件是否生成。

             

            # ls

             

            hello.cpp hello.h hello.o libmyhello.so main.cpp

            調用動態(tài)鏈接庫編譯目標文件。

             

            在程序中使用動態(tài)庫和使用靜態(tài)庫完全一樣,也是在使用到這些公用函數(shù)的源程序中包含這些公用函數(shù)的原型聲明,然后在用gcc命令生成目標文件時指明動態(tài)庫名進行編譯。我們先運行gcc命令生成目標文件,再運行它看看結果。

             

            如果直接用如下方法進行編譯,并連接:

            # gcc -o hello main.c -L. -lmyhello

             

            (使用”-lmyhello”標記來告訴GCC驅動程序在連接階段引用共享函數(shù)庫libmyhello.so”-L.”標記告訴GCC函數(shù)庫可能位于當前目錄。否則GNU連接器會查找標準系統(tǒng)函數(shù)目錄:它先后搜索1.elf文件的 DT_RPATH段—2.環(huán)境變量LD_LIBRARY_PATH—3./etc/ld.so.cache文件列表—4./lib/,/usr/lib目錄找到庫文件后將其載入內(nèi)存,但是我們生成的共享庫在當前文件夾下,并沒有加到上述的4個路徑的任何一個中,因此,執(zhí)行后會出現(xiàn)錯誤)

             

            # ./hello

             

            ./hello: error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory

             

            #

            錯誤提示,找不到動態(tài)庫文件libmyhello.so。程序在運行時,會在/usr/lib/lib等目錄中查找需要的動態(tài)庫文件。若找到,則載入動態(tài)庫,否則將提示類似上述錯誤而終止程序運行。有多種方法可以解決,

            (1)我們將文件 libmyhello.so復制到目錄/usr/lib中,再試試。

             

            # mv libmyhello.so /usr/lib

             

            # ./hello

            成功!

            (2)既然連接器會搜尋LD_LIBRARY_PATH所指定的目錄,那么我們可以將這個環(huán)境變量設置成當前目錄:

            先執(zhí)行:

            export LD_LIBRARY_PATH=$(pwd)

            再執(zhí)行:

            ./hello

            成功!

            (3)

            執(zhí)行:  

            ldconfig   /usr/zhsoft/lib     
                   
                  
              注:   當用戶在某個目錄下面創(chuàng)建或拷貝了一個動態(tài)鏈接庫,若想使其被系統(tǒng)共享,可以執(zhí)行一下"ldconfig   目錄名"這個命令.此命令的功能在于讓ldconfig將指定目錄下的動態(tài)鏈接庫被系統(tǒng)共享起來,意即:在緩存文件/etc/ld.so.cache中追加進指定目錄下的共享庫.本例讓系統(tǒng)共享了/usr/zhsoft/lib目錄下的動態(tài)鏈接庫.該命令會重建/etc/ld.so.cache文件

             

            成功!

            ¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥

            下面的這個錯誤我沒有遇到,不過也記錄下,給遇到的人:

             {  這步后我沒有成功,報錯內(nèi)容如下:/hello: error while loading shared libraries: /usr/lib/libmyhello.so: cannot restore segment prot after reloc: Permission denied

            google了一下,發(fā)現(xiàn)是SELinux搞的鬼,解決辦法有兩個:

            1.
                chcon -t texrel_shlib_t   
            /usr/lib/libmyhello.so
                (chcon -t texrel_shlib_t "你不能share的庫的絕對路徑")

            2.
                #vi /etc/sysconfig/selinux file
                或者用
                #gedit /etc/sysconfig/selinux file
                修改SELINUX=disabled
                重啟

            }

            #

            ¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥

            這也進一步說明了動態(tài)庫在程序運行時是需要的。

             

            可以查看程序執(zhí)行時調用動態(tài)庫的過程:

            # ldd hello
            執(zhí)行 test,可以看到它是如何調用動態(tài)庫中的函數(shù)的。
            [pin@localhost 20090505]$ ldd hello
                    linux-gate.so.1 => (0x00110000)
                    libmyhello.so => /usr/lib/libmyhello.so (0x00111000)
                    libc.so.6 => /lib/libc.so.6 (0x00859000)
                    /lib/ld-linux.so.2 (0x0083a000)

            我們回過頭看看,發(fā)現(xiàn)使用靜態(tài)庫和使用動態(tài)庫編譯成目標程序使用的gcc命令完全一樣,
            那當靜態(tài)庫和動態(tài)庫同名時,gcc命令會使用哪個庫文件呢?抱著對問題必究到底的心情,
            來試試看。

            先刪除除.c和.h外的所有文件,恢復成我們剛剛編輯完舉例程序狀態(tài)。

            # rm -f hello hello.o /usr/lib/libmyhello.so

            # ls

            hello.c hello.h main.c

            #

            在來創(chuàng)建靜態(tài)庫文件libmyhello.a和動態(tài)庫文件libmyhello.so。

            # gcc -c hello.c

            # ar rcs libmyhello.a hello.o

            # gcc -shared -fPCI -o libmyhello.so hello.o

            # ls

            hello.c hello.h hello.o libmyhello.a libmyhello.so main.c

            #

            通過上述最后一條ls命令,可以發(fā)現(xiàn)靜態(tài)庫文件libmyhello.a和動態(tài)庫文件libmyhello.so都已經(jīng)生成,并都在當前目錄中。然后,我們運行gcc命令來使用函數(shù)庫myhello生成目標文件hello,并運行程序 hello。

            # gcc -o hello main.c -L. -lmyhello

            # ./hello

            ./hello: error while loading shared libraries: libmyhello.so: cannot open shar
            ed object file: No such file or directory

            #

            從程序hello運行的結果中很容易知道,當靜態(tài)庫和動態(tài)庫同名時, gcc命令將優(yōu)先使用動態(tài)庫。

            Note:

            編譯參數(shù)解析


            最主要的是GCC命令行的一個選項:
            -shared 該選項指定生成動態(tài)連接庫(讓連接器生成T類型的導出符號表,有時候也生成弱連接W類型的導出符號),不用該標志外部程序無法連接。相當于一個可執(zhí)行文件
            l -fPIC:表示編譯為位置獨立的代碼,不用此選項的話編譯后的代碼是位置相關的所以動態(tài)載入時是通過代碼拷貝的方式來滿足不同進程的需要,而不能達到真正代碼段共享的目的。
            l -L.:表示要連接的庫在當前目錄中
            l -ltest:編譯器查找動態(tài)連接庫時有隱含的命名規(guī)則,即在給出的名字前面加上lib,后面加上.so來確定庫的名稱
            l LD_LIBRARY_PATH:這個環(huán)境變量指示動態(tài)連接器可以裝載動態(tài)庫的路徑。
            l 當然如果有root權限的話,可以修改/etc/ld.so.conf文件,然后調用 /sbin/ldconfig來達到同樣的目的,不過如果沒有root權限,那么只能采用輸出LD_LIBRARY_PATH的方法了。

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


            靜態(tài)庫鏈接時搜索路徑順序:

            1. ld會去找GCC命令中的參數(shù)-L

            2. 再找gcc的環(huán)境變量LIBRARY_PATH

            3. 再找內(nèi)定目錄 /lib /usr/lib /usr/local/lib 這是當初compile gcc時寫在程序內(nèi)的


            動態(tài)鏈接時、執(zhí)行時搜索路徑順序:


            1.  編譯目標代碼時指定的動態(tài)庫搜索路徑;

            2.  環(huán)境變量LD_LIBRARY_PATH指定的動態(tài)庫搜索路徑;

            3.  配置文件/etc/ld.so.conf中指定的動態(tài)庫搜索路徑;

            4. 默認的動態(tài)庫搜索路徑/lib;

            5. 默認的動態(tài)庫搜索路徑/usr/lib。


            有關環(huán)境變量:

            LIBRARY_PATH環(huán)境變量:指定程序靜態(tài)鏈接庫文件搜索路徑

            LD_LIBRARY_PATH環(huán)境變量:指定程序動態(tài)鏈接庫文件搜索路徑


            posted on 2012-02-09 13:43 李陽 閱讀(32881) 評論(7)  編輯 收藏 引用 所屬分類: Linux

            評論:
            # re: Linux下Gcc生成和使用靜態(tài)庫和動態(tài)庫詳解(轉) 2012-08-01 16:00 |
            寫的很詳細,謝謝分享!  回復  更多評論
              
            # re: Linux下Gcc生成和使用靜態(tài)庫和動態(tài)庫詳解(轉) 2013-01-15 15:25 | lwVampire
            受教了,很細致的文章  回復  更多評論
              
            # re: Linux下Gcc生成和使用靜態(tài)庫和動態(tài)庫詳解(轉) 2013-03-04 16:49 | zhangmo
            非常詳細的文章,謝謝分享。  回復  更多評論
              
            # re: Linux下Gcc生成和使用靜態(tài)庫和動態(tài)庫詳解(轉) 2013-04-25 15:54 | molixiaoge
            謝謝 看了很好  回復  更多評論
              
            # re: Linux下Gcc生成和使用靜態(tài)庫和動態(tài)庫詳解(轉) 2014-05-23 17:20 | zpyws
            非常好的文章,受益匪淺  回復  更多評論
              
            # re: Linux下Gcc生成和使用靜態(tài)庫和動態(tài)庫詳解(轉) 2015-01-29 08:27 | lemonsky
            寫的很好,最近在看embeded compile,這篇文章很有啟發(fā)  回復  更多評論
              
            # re: Linux下Gcc生成和使用靜態(tài)庫和動態(tài)庫詳解(轉) 2016-05-18 18:09 | hdp
            gta@gta-virtual-machine:~/Test/gcc$ gcc -shared -fPIC -o libmyhello.so hello.o
            /usr/bin/ld: hello.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
            hello.o: could not read symbols: Bad value
            collect2: ld returned 1 exit status

            按照你的方式,在制作動態(tài)庫時出現(xiàn)了問題。
            后來在其他博客中發(fā)現(xiàn)是hello.o的問題。
            我想問,是我電腦環(huán)境的問題,還是你的博客有問題?  回復  更多評論
              
            婷婷五月深深久久精品| 一本久道久久综合狠狠躁AV| 日日狠狠久久偷偷色综合0| 久久福利青草精品资源站| 色8久久人人97超碰香蕉987| 青青草国产97免久久费观看| 狠狠精品久久久无码中文字幕| 久久青青草原精品影院| 狠狠色噜噜狠狠狠狠狠色综合久久| 久久久无码一区二区三区| 亚洲人成伊人成综合网久久久| 久久久久亚洲av成人网人人软件 | 久久免费高清视频| 久久精品国产亚洲AV大全| AV色综合久久天堂AV色综合在| 久久狠狠高潮亚洲精品| 久久国产成人精品麻豆| 久久精品国产99国产精品澳门| 中文精品久久久久国产网址| 成人精品一区二区久久久| 国产精品熟女福利久久AV| 亚洲第一永久AV网站久久精品男人的天堂AV | 久久久久精品国产亚洲AV无码| 久久99国产精品久久99| 色综合久久中文综合网| 久久久精品无码专区不卡| 久久婷婷五月综合97色直播| 久久丫精品国产亚洲av| 久久亚洲国产中v天仙www| 欧美久久一区二区三区| 亚洲精品乱码久久久久久| 人人狠狠综合久久亚洲88| 亚洲国产天堂久久综合| 久久久久久九九99精品| 精品久久久久久无码人妻蜜桃| 亚洲日韩欧美一区久久久久我| 久久精品中文无码资源站| 久久亚洲中文字幕精品一区| 久久精品中文騷妇女内射| 四虎影视久久久免费观看| 久久精品国产福利国产秒|