日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux .so文件

發(fā)布時(shí)間:2024/3/26 linux 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux .so文件 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
  • 相冊(cè)
  • 廣場
  • 登錄

  • 注冊(cè)
關(guān)注此空間

buptwinnie的空間

生活從linux開始.....

2011-11-17 10:04

【轉(zhuǎn)】linux .so文件

linux下文件的類型是不依賴于其后綴名的,但一般來講:
.o,是目標(biāo)文件,相當(dāng)于windows中的.obj文件
.so 為共享庫,是shared object,用于動(dòng)態(tài)連接的,和dll差不多
.a為靜態(tài)庫,是好多個(gè).o合在一起,用于靜態(tài)連接
.la為libtool自動(dòng)生成的一些共享庫,vi編輯查看,主要記錄了一些配置信息。可以用如下命令查看*.la文件的格式 ? $file *.la
? ? ? *.la: ASCII English text
所以可以用vi來查看其內(nèi)容。
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
創(chuàng)建.a庫文件和.o庫文件:
[yufei@localhost perl_c2]$ pwd
/home/yufei/perl_c2

[yufei@localhost perl_c2]$ cat mylib.c
#include <stdio.h>
#include <string.h>
void hello(){
??????? printf("success call from perl to c library\n");
}
[yufei@localhost perl_c2]$ cat mylib.h
extern void hello();


[yufei@localhost perl_c2]$ gcc -c mylib.c
[yufei@localhost perl_c2]$ dir
mylib.c? mylib.h? mylib.o
[yufei@localhost perl_c2]$ ar -r mylib.a mylib.o
ar: 正在創(chuàng)建 mylib.a
[yufei@localhost perl_c2]$ dir
mylib.a? mylib.c? mylib.h? mylib.o


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

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

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

so_test.h:

#include <stdio.h>
#include <stdlib.h>
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_c.c:

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

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

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

在1、中,我們已經(jīng)成功生成了一個(gè)自己的動(dòng)態(tài)鏈接庫libtest.so,下面我們通過一個(gè)程序來調(diào)用這個(gè)庫里的函數(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)庫libtest.so鏈接生成執(zhí)行文件test:
$ gcc test.c -L. -ltest -o test


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

$ ldd test
l? ?? ?? ?執(zhí)行test,可以看到它是如何調(diào)用動(dòng)態(tài)庫中的函數(shù)的。
3、編譯參數(shù)解析
最主要的是GCC命令行的一個(gè)選項(xiàng):
??? ?? ? -shared 該選項(xiàng)指定生成動(dòng)態(tài)連接庫(讓連接器生成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.:表示要連接的庫在當(dāng)前目錄中

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

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

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

makefile里面怎么正確的編譯和連接生成.so庫文件,然后又是在其他程序的makefile里面如何編譯和連接才能調(diào)用這個(gè)庫文件的函數(shù)????
答:
?????? 你需要告訴動(dòng)態(tài)鏈接器、加載器ld.so在哪里才能找到這個(gè)共享庫,可以設(shè)置環(huán)境變量把庫的路徑添加到庫目錄/lib和/usr/lib,LD_LIBRARY_PATH=$(pwd),這種方法采用命令行方法不太方便,一種替代方法
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^注釋^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LD_LIBRARY_PATH可以在/etc/profile還是 ~/.profile還是 ./bash_profile里設(shè)置,或者.bashrc里,

改完后運(yùn)行source /etc/profile或 . /etc/profile
更好的辦法是添入/etc/ld.so.conf, 然后執(zhí)行 /sbin/ldconfig
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^注釋^^^^^^^^^^^^^^^^^^^^^^^^^^^^
是把庫路徑添加到/etc/ld.so.conf,然后以root身份運(yùn)行l(wèi)dconfig
????? 也可以在連接的時(shí)候指定文件路徑和名稱?-I??-L.

????? GCC=gcc
CFLAGS=-Wall?-ggdb?-fPIC
#CFLAGS=
all:?libfunc?test
libfunc:func.o?func1.o
????????$(GCC)?-shared?-Wl,-soname,libfunc.so.1?-o?libfunc.so.1.1?$<
????????ln?-sf?libfunc.so.1.1?libfunc.so.1
????????ln?-sf?libfunc.so.1?libfunc.so
***********************************************注釋************************************************
ln -s是用來創(chuàng)建軟鏈接,也就相當(dāng)于windows中的快捷方式,在當(dāng)前目錄中創(chuàng)建上一級(jí)目錄中的文件ttt的命名為ttt2軟鏈接的命令是ln -s ../ttt ttt2,如果原文件也就是ttt文件刪除的話,ttt2也變成了空文件。
ln -d是用來創(chuàng)建硬鏈接,也就相當(dāng)于windows中文件的副本,當(dāng)原文件刪除的時(shí)候,并不影響“副本”的內(nèi)容。

編譯目標(biāo)文件時(shí)使用gcc的-fPIC選項(xiàng),產(chǎn)生與位置無關(guān)的代碼并能被加載到任何地址:
gcc –fPIC –g –c liberr.c –o liberr.o

使用gcc的-shared和-soname選項(xiàng);
使用gcc的-Wl選項(xiàng)把參數(shù)傳遞給連接器ld;
使用gcc的-l選項(xiàng)顯示的連接C庫,以保證可以得到所需的啟動(dòng)(startup)代碼,從而避免程序在使用不同的,可能不兼容版本的C庫的系統(tǒng)上不能啟動(dòng)執(zhí)行。
gcc –g –shared –Wl,-soname,liberr.so –o liberr.so.1.0.0 liberr.o –lc

建立相應(yīng)的符號(hào)連接:
ln –s liberr.so.1.0.0 liberr.so.1;
ln –s liberr.so.1.0.0 liberr.so;

在MAKEFILE中:
$@
??? 表示規(guī)則中的目標(biāo)文件集。在模式規(guī)則中,如果有多個(gè)目標(biāo),那么,"$@"就是匹配于目標(biāo)中模式定義的集合。
$%
??? 僅當(dāng)目標(biāo)是函數(shù)庫文件中,表示規(guī)則中的目標(biāo)成員名。例如,如果一個(gè)目標(biāo)是"foo.a(bar.o)",那么,"$%"就是"bar.o","$@"就是 "foo.a"。如果目標(biāo)不是函數(shù)庫文件(Unix下是[.a],Windows下是[.lib]),那么,其值為空。
$<
??? 依賴目標(biāo)中的第一個(gè)目標(biāo)名字。如果依賴目標(biāo)是以模式(即"%")定義的,那么"$<"將是符合模式的一系列的文件集。注意,其是一個(gè)一個(gè)取出來的。
$?
??? 所有比目標(biāo)新的依賴目標(biāo)的集合。以空格分隔。
$^
??? 所有的依賴目標(biāo)的集合。以空格分隔。如果在依賴目標(biāo)中有多個(gè)重復(fù)的,那個(gè)這個(gè)變量會(huì)去除重復(fù)的依賴目標(biāo),只保留一份。
*********************************************注釋***********************************************************************
test:?test.o?libfunc
????????$(GCC)?-o?test?test.o?-L.?-lfunc
%.o:%.c
????????$(GCC)?-c?$(CFLAGS)?-o?$@?$<
clean:
????????rm?-fr?*.o
????????rm?-fr?*.so*
????????rm?-fr?test

要生成.so文件,cc要帶-shared?參數(shù);要調(diào)用.so的文件,比如libfunc.so,可以在cc命令最后加上-lfunc,還要視情況加上 -L/usr/xxx?指出libfunc.so的路徑;這樣,在你要編譯的源文件中就可以調(diào)用libfunc.so這個(gè)庫文件的函數(shù).
?????? 前面的都說的差不多了,最后提醒一下最好提供一個(gè)接口頭文件
?????? 動(dòng)態(tài)加載,用dlopen,dlclose,dlsym
?


ref:http://niefei.blog.ccidnet.com/blog/ccid/do_showone/tid_42855.html
1. 介紹

  使用GNU的工具我們?nèi)绾卧贚inux下創(chuàng)建自己的程序函數(shù)庫?一個(gè)“程序 函數(shù)庫”簡單的說就是一個(gè)文件包含了一些編譯好的代碼和數(shù)據(jù),這些編 譯好的代碼和數(shù)據(jù)可以在事后供其他的程序使用。程序函數(shù)庫可以使整個(gè)程序更加模塊化,更容易重新編譯,而且更方便升級(jí)。程序函數(shù)庫可分為3種類型:靜態(tài)函 數(shù)庫(static libraries)、共享函數(shù)庫(shared libraries)和動(dòng)態(tài)加載函數(shù)庫(dynamically loaded libraries)。

  靜態(tài)函數(shù)庫是在程序執(zhí)行前就加入到目標(biāo)程序中去了;而共享函數(shù)庫則是在程序啟動(dòng)的時(shí)候加載到程序中,它可以被 不同的程序共享;動(dòng)態(tài)加載函數(shù)庫則可以在程序運(yùn)行的任何時(shí)候動(dòng)態(tài)的加載。實(shí)際上,動(dòng)態(tài)函數(shù)庫并非另外一種庫函數(shù)格式,區(qū)別是動(dòng)態(tài)加載函數(shù)庫是如何被程序員 使用的。后面我們將舉例說明。

  本文檔主要參考Program Library HOWTO,作者是luster(),任何非商業(yè)目的的再次發(fā)行本文檔都是允許的,但是請(qǐng)保留作者信息和本版權(quán)聲明。本文檔首先在發(fā)布。

  2. 靜態(tài)函數(shù)庫

   靜態(tài)函數(shù)庫實(shí)際上就是簡單的一個(gè)普通的目標(biāo)文件的集合,一般來說習(xí)慣用“.a”作為文件的后綴。可以用ar這個(gè)程序來產(chǎn)生靜態(tài)函數(shù)庫文件。Ar 是archiver的縮寫。靜態(tài)函數(shù)庫現(xiàn)在已經(jīng)不在像以前用得那么多了,主要是共享函數(shù)庫與之相比較有很多的優(yōu)勢的原因。慢慢地,大家都喜歡使用共享函數(shù) 庫了。不過,在一些場所靜態(tài)函數(shù)庫仍然在使用,一來是保持一些與以前某些程序的兼容,二來它描述起來也比較簡單。

  靜態(tài)庫函數(shù)允許程序 員把程序link起來而不用重新編譯代碼,節(jié)省了重新編譯代碼的時(shí)間。不過,在今天這么快速的計(jì)算機(jī)面前,一般的程序的重新編譯也花費(fèi)不了多少時(shí)間,所以 這個(gè)優(yōu)勢已經(jīng)不是像它以前那么明顯了。靜態(tài)函數(shù)庫對(duì)開發(fā)者來說還是很有用的,例如你想把自己提供的函數(shù)給別人使用,但是又想對(duì)函數(shù)的源代碼進(jìn)行保密,你就 可以給別人提供一個(gè)靜態(tài)函數(shù)庫文件。理論上說,使用ELF格式的靜態(tài)庫函數(shù)生成的代碼可以比使用共享函數(shù)庫(或者動(dòng)態(tài)函數(shù) 庫)的程序運(yùn)行速度上快一些,大概1-5%。

  創(chuàng)建一個(gè)靜態(tài)函數(shù)庫文件,或者往一個(gè)已經(jīng)存在地靜態(tài)函數(shù)庫文件添加新的目標(biāo)代碼,可以用下面的命令:



ar rcs my_library.a file1.o file2.o

   這個(gè)例子中是把目標(biāo)代碼file1.o和file2.o加入到my_library.a這個(gè)函數(shù)庫文件中,如果my_library.a不存在 則創(chuàng)建一個(gè)新的文件。在用ar命令創(chuàng)建靜態(tài)庫函數(shù)的時(shí)候,還有其他一些可以選擇的參數(shù),可以參加ar的使用幫助。這里不再贅述。

  一旦 你創(chuàng)建了一個(gè)靜態(tài)函數(shù)庫,你可以使用它了。你可以把它作為你編譯和連接過程中的一部分用來生成你的可執(zhí)行代碼。如果你用gcc來編譯產(chǎn)生可 執(zhí)行代碼的話,你可以用“-l”參數(shù)來指定這個(gè)庫函數(shù)。你也可以用ld來做,使用它的“-l”和“-L”參數(shù)選項(xiàng)。具體用法,可以參考info:gcc。

 3. 共享函數(shù)庫

  共享函數(shù)庫中的函數(shù)是在當(dāng)一個(gè)可執(zhí)行程序在啟動(dòng)的時(shí)候被加載。如果一個(gè)共享函數(shù)庫正常安裝,所有的程序在重新運(yùn)行的時(shí)候都可以自動(dòng)加載最新的函數(shù)庫中的函數(shù)。對(duì)于Linux系統(tǒng)還有更多的可以實(shí)現(xiàn)的功能:

o 升級(jí)了函數(shù)庫但是仍然允許程序使用老版本的函數(shù)庫。 o 當(dāng)執(zhí)行某個(gè)特定程序的時(shí)候可以覆蓋某個(gè)特定的庫或者庫中指定的函數(shù)。 o 可以在庫函數(shù)被使用的過程中修改這些函數(shù)庫。

  3.1. 一些約定

   如果你要編寫的共享函數(shù)庫支持所有有用的特性,你在編寫的過程中必須遵循一系列約定。你必須理解庫的不同的名字間的區(qū)別,例如它的 “soname”和“real name”之間的區(qū)別和它們是如何相互作用的。你同樣還要知道你應(yīng)該把這些庫函數(shù)放在你文件系統(tǒng)的什么位置等等。下面我們具體看看這些問題。

  3.1.1. 共享庫的命名

  每個(gè)共享函數(shù)庫都有個(gè)特殊的名字,稱作“soname”。Soname名字命名必須以“l(fā)ib”作為前綴,然后是函數(shù)庫的名字,然后是“.so”,最后是版本號(hào)信息。不過有個(gè)特例,就是非常底層的C庫函數(shù)都不是以lib開頭這樣命名的。

  每個(gè)共享函數(shù)庫都有一個(gè)真正的名字(“real name”),它是包含真正庫函數(shù)代碼的文件。真名有一個(gè)主版本號(hào),和一個(gè)發(fā)行版本號(hào)。最后一個(gè)發(fā)行版本號(hào)是可選的,可以沒有。主版本號(hào)和發(fā)行版本號(hào)使你可以知道你到底是安裝了什么版本的庫函數(shù)。

另外,還有一個(gè)名字是編譯器編譯的時(shí)候需要的函數(shù)庫的名字,這個(gè)名字就是簡單的soname名字,而不包含任何版本號(hào)信息。

   管理共享函數(shù)庫的關(guān)鍵是區(qū)分好這些名字。當(dāng)可執(zhí)行程序需要在自己的程序中列出這些他們需要的共享庫函數(shù)的時(shí)候,它只要用soname就可以了; 反過來,當(dāng)你要?jiǎng)?chuàng)建一個(gè)新的共享函數(shù)庫的時(shí)候,你要指定一個(gè)特定的文件名,其中包含很細(xì)節(jié)的版本信息。當(dāng)你安裝一個(gè)新版本的函數(shù)庫的時(shí)候,你只要先將這些 函數(shù)庫文件拷貝到一些特定的目錄中,運(yùn)行l(wèi)dconfig這個(gè)實(shí)用就可以。Ldconfig檢查已經(jīng)存在的庫文件,然后創(chuàng)建soname的符號(hào)鏈接到真正 的函數(shù)庫,同時(shí)設(shè)置/etc/ld.so.cache這個(gè)緩沖文件。這個(gè)我們稍后再討論。

  Ldconfig并不設(shè)置鏈接的名字,通常 的做法是在安裝過程中完成這個(gè)鏈接名字的建立,一般來說這個(gè)符號(hào)鏈接就簡單的指向最新的soname 或者最新版本的函數(shù)庫文件。最好把這個(gè)符號(hào)鏈接指向soname,因?yàn)橥ǔ.?dāng)你升級(jí)你的庫函數(shù)的后,你就可以自動(dòng)使用新版本的函數(shù)庫勒。

  我們來舉例看看:

   /usr/lib/libreadline.so.3 是一個(gè)完全的完整的soname,ldconfig可以設(shè)置一個(gè)符號(hào)鏈接到其他某個(gè)真正的函數(shù)庫文件,例如是 /usr/lib/libreadline.so.3.0。同時(shí)還必須有一個(gè)鏈接名字,例如/usr/lib/libreadline.so 就是一個(gè)符號(hào)鏈接指向/usr/lib/libreadline.so.3。

3.1.2. 文件系統(tǒng)中函數(shù)庫文件的位置

   共享函數(shù)庫文件必須放在一些特定的目錄里,這樣通過系統(tǒng)的環(huán)境變量設(shè)置,應(yīng)用程序才能正確的使用這些函數(shù)庫。大部分的源碼開發(fā)的程序都遵循 GNU的一些標(biāo)準(zhǔn),我們可以看info幫助文件獲得相信的說明,info信息的位置是:info: standards#Directory_Variables。GNU標(biāo)準(zhǔn)建議所有的函數(shù)庫文件都放在/usr/local/lib目錄下,而且建議命令 可執(zhí)行程序都放在/usr/local/bin目錄下。這都是一些習(xí)慣問題,可以改變的。

  文件系統(tǒng)層次化標(biāo)準(zhǔn)FHS(Filesystem Hierarchy Standard)()規(guī)定了在一個(gè)發(fā)行包中大部分的函數(shù)庫文件應(yīng)該安裝到/usr/lib目錄 下,但是如果某些庫是在系統(tǒng)啟動(dòng)的時(shí)候要加載的,則放到/lib目錄下,而那些不是系統(tǒng)本身一部分的庫則放到/usr/local/lib下面。

  上面兩個(gè)路徑的不同并沒有本質(zhì)的沖突。GNU提出的標(biāo)準(zhǔn)主要對(duì)于開發(fā)者開發(fā)源碼的,而FHS的建議則是針對(duì)發(fā)行版本的路徑的。具體的位置信息可以看/etc/ld.so.conf里面的配置信息。

  3.2. 這些函數(shù)庫如何使用

   在基于GNU glibc的系統(tǒng)里,包括所有的linux系統(tǒng),啟動(dòng)一個(gè)ELF格式的二進(jìn)制可執(zhí)行文件會(huì)自動(dòng)啟動(dòng)和運(yùn)行一個(gè)program loader。對(duì)于Linux系統(tǒng),這個(gè)loader的名字是/lib/ld-linux.so.X(X是版本號(hào))。這個(gè)loader啟動(dòng)后,反過來就會(huì) load所有的其他本程序要使用的共享函數(shù)庫。

  到底在哪些目錄里查找共享函數(shù)庫呢?這些定義缺省的是放在 /etc/ld.so.conf文件里面,我們可以修改這個(gè)文件,加入我們自己的一些 特殊的路徑要求。大多數(shù)RedHat系列的發(fā)行包的/etc/ld.so.conf文件里面不包括/usr/local/lib這個(gè)目錄,如果沒有這個(gè)目 錄的話,我們可以修改/etc/ld.so.conf,自己手動(dòng)加上這個(gè)條目。

  如果你想覆蓋某個(gè)庫中的一些函數(shù),用自己的函數(shù)替換它們,同時(shí)保留該庫中其他的函數(shù)的話,你可以在/etc/ld.so.preload中加入你想要替換的庫(.o結(jié)尾的文件),這些preloading的庫函數(shù)將有優(yōu)先加載的權(quán)利。

   當(dāng)程序啟動(dòng)的時(shí)候搜索所有的目錄顯然會(huì)效率很低,于是Linux系統(tǒng)實(shí)際上用的是一個(gè)高速緩沖的做法。Ldconfig缺省情況下讀出 /etc/ld.so.conf相關(guān)信息,然后設(shè)置適當(dāng)?shù)胤?hào)鏈接,然后寫一個(gè)cache到/etc/ld.so.cache這個(gè)文件中,而這個(gè) /etc/ld.so.cache則可以被其他程序有效的使用了。這樣的做法可以大大提高訪問函數(shù)庫的速度。這就要求每次新增加一個(gè)動(dòng)態(tài)加載的函數(shù)庫的時(shí) 候,就要運(yùn)行l(wèi)dconfig來更新這個(gè)cache,如果要?jiǎng)h除某個(gè)函數(shù)庫,或者某個(gè)函數(shù)庫的路徑修改了,都要重新運(yùn)行l(wèi)dconfig來更新這個(gè) cache。通常的一些包管理器在安裝一個(gè)新的函數(shù)庫的時(shí)候就要運(yùn)行l(wèi)dconfig。

  另外,FreeBSD使用cache的文件不一樣。FreeBSD的ELF cache是/var/run/ld-elf.so.hints,而a.out的cache責(zé)是/var/run/ld.so.hints。它們同樣是通過ldconfig來更新。

  3.3. 環(huán)境變量

   各種各樣的環(huán)境變量控制著一些關(guān)鍵的過程。例如你可以臨時(shí)為你特定的程序的一次執(zhí)行指定一個(gè)不同的函數(shù)庫。Linux系統(tǒng)中,通常變量 LD_LIBRARY_PATH就是可以用來指定函數(shù)庫查找路徑的,而且這個(gè)路徑通常是在查找標(biāo)準(zhǔn)的路徑之前查找。這個(gè)是很有用的,特別是在調(diào)試一個(gè)新的 函數(shù)庫的時(shí)候,或者在特殊的場合使用一個(gè)肥標(biāo)準(zhǔn)的函數(shù)庫的時(shí)候。環(huán)境變量LD_PRELOAD列出了所有共享函數(shù)庫中需要優(yōu)先加載的庫文件,功能和 /etc/ld.so.preload類似。這些都是有/lib/ld-linux.so這個(gè)loader來實(shí)現(xiàn)的。值得一提的是, LD_LIBRARY_PATH可以在大部分的UNIX-linke系統(tǒng)下正常起作用,但是并非所有的系統(tǒng)下都可以使用,例如HP-UX系統(tǒng)下,就是用 SHLIB_PATH這個(gè)變量,而在AIX下則使用LIBPATH這個(gè)變量。

  LD_LIBRARY_PATH在開發(fā)和調(diào)試過程中經(jīng)常大量使用,但是不應(yīng)該被一個(gè)普通用戶在安裝過程中被安裝程序修改,大家可以去參考 ,這里有一個(gè)文檔專門介紹為什么不使用LD_LIBRARY_PATH這個(gè) 變量。

  事實(shí)上還有更多的環(huán)境變量影響著程序的調(diào)入過程,它們的名字通常就是以LD_或者RTLD_打頭。大部分這些環(huán)境變量的使用的文檔都是不全,通常搞得人頭昏眼花的,如果要真正弄清楚它們的用法,最好去讀loader的源碼(也就是gcc的一部分)。

   允許用戶控制動(dòng)態(tài)鏈接函數(shù)庫將涉及到setuid/setgid這個(gè)函數(shù)如果特殊的功能需要的話。因此,GNU loader通常限制或者忽略用戶對(duì)這些變量使用setuid和setgid。如果loader通過判斷程序的相關(guān)環(huán)境變量判斷程序的是否使用了 setuid或者setgid,如果uid和euid不同,或者gid和egid部一樣,那么loader就假定程序已經(jīng)使用了setuid或者 setgid,然后就大大的限制器控制這個(gè)老鏈接的權(quán)限。如果閱讀GNU glibc的庫函數(shù)源碼,就可以清楚地看到這一點(diǎn),特別的我們可以看elf/rtld.c和sysdeps/generic/dl-sysdep.c這兩 個(gè)文件。這就意味著如果你使得uid和gid與euid和egid分別相等,然后調(diào)用一個(gè)程序,那么這些變量就可以完全起效。

3.4. 創(chuàng)建一個(gè)共享函數(shù)庫

   現(xiàn)在我們開始學(xué)習(xí)如何創(chuàng)建一個(gè)共享函數(shù)庫。其實(shí)創(chuàng)建一個(gè)共享函數(shù)庫非常容易。首先創(chuàng)建object文件,這個(gè)文件將加入通過gcc –fPIC 參數(shù)命令加入到共享函數(shù)庫里面。PIC的意思是“位置無關(guān)代碼”(Position Independent Code)。下面是一個(gè)標(biāo)準(zhǔn)的格式:



gcc -shared -Wl,-soname,your_soname -o library_name file_list library_list

  下面再給一個(gè)例子,它創(chuàng)建兩個(gè)object文件(a.o和b.o),然后創(chuàng)建一個(gè)包含a.o和b.o的共享函數(shù)庫。例子中”-g”和“-Wall”參數(shù)不是必須的。



gcc -fPIC -g -c -Wall a.cgcc -fPIC -g -c -Wall b.cgcc -shared -Wl,

-soname,liblusterstuff.so.1 -o liblusterstuff.so.1.0.1 a.o b.o -lc

  下面是一些需要注意的地方:

· 不用使用-fomit-frame-pointer這個(gè)編譯參數(shù)除非你不得不這樣。雖然使用了這個(gè)參數(shù)獲得的函數(shù)庫仍然可以使用,但是這使得調(diào)試程序幾乎 沒有用,無法跟蹤調(diào)試。 · 使用-fPIC來產(chǎn)生代碼,而不是-fpic。 · 某些情況下,使用gcc 來生成object文件,需要使用“-Wl,-export-dynamic”這個(gè)選項(xiàng)參數(shù)。通常,動(dòng)態(tài)函數(shù)庫的符號(hào)表里面包含了這些動(dòng)態(tài)的對(duì)象的符號(hào)。 這個(gè)選項(xiàng)在創(chuàng)建ELF格式的文件時(shí)候,會(huì)將所有的符號(hào)加入到動(dòng)態(tài)符號(hào)表中。可以參考ld的幫助獲得更詳細(xì)的說明。

  3.5. 安裝和使用共享函數(shù)庫

  一旦你了一個(gè)共享函數(shù)庫,你還需要安裝它。其實(shí)簡單的方法就是拷貝你的庫文件到指定的標(biāo)準(zhǔn)的目錄(例如/usr/lib),然后運(yùn)行l(wèi)dconfig。

   如果你沒有權(quán)限去做這件事情,例如你不能修改/usr/lib目錄,那么你就只好通過修改你的環(huán)境變量來實(shí)現(xiàn)這些函數(shù)庫的使用了。首先,你需要 創(chuàng)建這些共享函數(shù)庫;然后,設(shè)置一些必須得符號(hào)鏈接,特別是從soname到真正的函數(shù)庫文件的符號(hào)鏈接,簡單的方法就是運(yùn)行l(wèi)dconfig:



ldconfig -n directory_with_shared_libraries

  然后你就可以設(shè)置你的LD_LIBRARY_PATH這個(gè)環(huán)境變量,它是一個(gè)以逗號(hào)分隔的路徑的集合,這個(gè)可以用來指明共享函數(shù)庫的搜索路徑。例如,使用bash,就可以這樣來啟動(dòng)一個(gè)程序my_program:



LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH my_program

   如果你需要的是重載部分函數(shù),則你就需要?jiǎng)?chuàng)建一個(gè)包含需要重載的函數(shù)的object文件,然后設(shè)置LD_PRELOAD環(huán)境變量。通常你可以很 方便的升級(jí)你的函數(shù)庫,如果某個(gè)API改變了,創(chuàng)建庫的程序會(huì)改變soname。然而,如果一個(gè)函數(shù)升級(jí)了某個(gè)函數(shù)庫而保持了原來的soname,你可以 強(qiáng)行將老版本的函數(shù)庫拷貝到某個(gè)位置,然后重新命名這個(gè)文件(例如使用原來的名字,然后后面加.orig后綴),然后創(chuàng)建一個(gè)小的“wrapper”腳本 來設(shè)置這個(gè)庫函數(shù)和相關(guān)的東西。例如下面的例子:



#!/bin/sh export LD_LIBRARY_PATH=/usr/local/my_lib:$LD_LIBRARY_PATH exec

/usr/bin/my_program.orig $*

  我們可以通過運(yùn)行l(wèi)dd來看某個(gè)程序使用的共享函數(shù)庫。例如你可以看ls這個(gè)實(shí)用工具使用的函數(shù)庫:



ldd /bin/ls

? ? libtermcap.so.2 => /lib/libtermcap.so.2 (0x4001c000)

? ? libc.so.6 => /lib/libc.so.6 (0x40020000)

? ? /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

  通常我么可以看到一個(gè)soname的列表,包括路徑。在所有的情況下,你都至少可以看到兩個(gè)庫:



· /lib/ld-linux.so.N(N是1或者更大,一般至少2)。

這是這個(gè)用力加載其他所有的共享庫的庫。

· libc.so.N(N應(yīng)該大于或者等于6)。這是C語言函數(shù)庫。

   值得一提的是,不要在對(duì)你不信任的程序運(yùn)行l(wèi)dd命令。在ldd的manual里面寫得很清楚,ldd是通過設(shè)置某些特殊的環(huán)境變量(例如,對(duì) 于ELF對(duì)象,設(shè)置LD_TRACE_LOADED_OBJECTS),然后運(yùn)行這個(gè)程序。這樣就有可能使得某地程序可能使得ldd來執(zhí)行某些意想不到的 代碼,而產(chǎn)生不安全的隱患。

3.6. 不兼容的函數(shù)庫

  如果一個(gè)新版的函數(shù)庫要和老版本的二進(jìn)制的庫不兼容,則soname需要改變。對(duì)于C語言,一共有4個(gè)基本的理由使得它們?cè)诙M(jìn)制代碼上很難兼容:

  o. 一個(gè)函數(shù)的行文改變了,這樣它就可能與最開始的定義不相符合。

  o. 輸出的數(shù)據(jù)項(xiàng)改變了。

  o. 某些輸出的函數(shù)刪除了。

  o. 某些輸出函數(shù)的接口改變了。

  如果你能避免這些地方,你就可以保持你的函數(shù)庫在二進(jìn)制代碼上的兼容,或者說,你可以使得你的程序的應(yīng)用二進(jìn)制接口(ABI:Application Binary Interface)上兼容。

  4. 動(dòng)態(tài)加載的函數(shù)庫Dynamically Loaded (DL) Libraries

   動(dòng)態(tài)加載的函數(shù)庫Dynamically loaded (DL) libraries是一類函數(shù)庫,它可以在程序運(yùn)行過程中的任何時(shí)間加載。它們特別適合在函數(shù)中加載一些模塊和plugin擴(kuò)展模塊的場合,因?yàn)樗梢栽?當(dāng)程序需要某個(gè)plugin模塊時(shí)才動(dòng)態(tài)的加載。例如,Pluggable Authentication Modules(PAM)系統(tǒng)就是用動(dòng)態(tài)加載函數(shù)庫來使得管理員可以配置和重新配置身份驗(yàn)證信息。

  Linux系統(tǒng)下,DL函數(shù)庫與其 他函數(shù)庫在格式上沒有特殊的區(qū)別,我們前面提到過,它們創(chuàng)建的時(shí)候是標(biāo)準(zhǔn)的object格式。主要的區(qū)別就是 這些函數(shù)庫不是在程序鏈接的時(shí)候或者啟動(dòng)的時(shí)候加載,而是通過一個(gè)API來打開一個(gè)函數(shù)庫,尋找符號(hào)表,處理錯(cuò)誤和關(guān)閉函數(shù)庫。通常C語言環(huán)境下,需要包 含這個(gè)頭文件。

  Linux中使用的函數(shù)和Solaris中一樣,都是dlpoen() API。當(dāng)時(shí)不是所有的平臺(tái)都使用同樣的接口,例如HP-UX使用shl_load()機(jī)制,而Windows平臺(tái)用另外的其他的調(diào)用接口。如果你的目的 是使得你的代碼有很強(qiáng)的移植性,你應(yīng)該使用一些wrapping函數(shù)庫,這樣的wrapping函數(shù)庫隱藏不同的平臺(tái)的接口區(qū)別。一種方法是使用 glibc函數(shù)庫中的對(duì)動(dòng)態(tài)加載模塊的支持,它使用一些潛在的動(dòng)態(tài)加載函數(shù)庫界面使得它們可以夸平臺(tái)使用。具體可以參考http: //developer.gnome.org/doc/API/glib/glib-dynamic-loading-of-modules.html. 另外一個(gè)方法是使用libltdl,是GNU libtool的一部分,可以進(jìn)一步參考CORBA相關(guān)資料。

  4.1. dlopen()

  dlopen函數(shù)打開一個(gè)函數(shù)庫然后為后面的使用做準(zhǔn)備。C語言原形是:



void * dlopen(const char *filename, int flag);

  如果文件名filename是以“/”開頭,也就是使用絕對(duì)路徑,那么dlopne就直接使用它,而不去查找某些環(huán)境變量或者系統(tǒng)設(shè)置的函數(shù)庫所在的目錄了。否則dlopen()

  就會(huì)按照下面的次序查找函數(shù)庫文件:

1. 環(huán)境變量LD_LIBRARY指明的路徑。 2. /etc/ld.so.cache中的函數(shù)庫列表。 3. /lib目錄,然后/usr/lib。不過一些很老的a.out的loader則是采用相反的次序,也就是先查/usr/lib,然后是/lib。

   Dlopen()函數(shù)中,參數(shù)flag的值必須是RTLD_LAZY或者RTLD_NOW,RTLD_LAZY的意思是resolve undefined symbols as code from the dynamic library is executed,而RTLD_NOW的含義是resolve all undefined symbols before dlopen() returns and fail if this cannot be done'。

  如果有好幾個(gè)函數(shù)庫,它們之間有一些依賴關(guān)系的話,例如X依賴Y,那么你就要先加載那些被依賴的函數(shù)。例如先加載Y,然后加載X。

  dlopen()函數(shù)的返回值是一個(gè)句柄,然后后面的函數(shù)就通過使用這個(gè)句柄來做進(jìn)一步的操作。如果打開失敗dlopen()就返回一個(gè)NULL。如果一個(gè)函數(shù)庫被多次打開,它會(huì)返回同樣的句柄。

  如果一個(gè)函數(shù)庫里面有一個(gè)輸出的函數(shù)名字為_init,那么_init就會(huì)在dlopen()這個(gè)函數(shù)返回前被執(zhí)行。我們可以利用這個(gè)函數(shù)在我的函數(shù)庫里面做一些初始化的工作。我們后面會(huì)繼續(xù)討論這個(gè)問題的。

  4.2. dlerror()

  通過調(diào)用dlerror()函數(shù),我們可以獲得最后一次調(diào)用dlopen(),dlsym(),或者dlclose()的錯(cuò)誤信息。

4.3. dlsym()

  如果你加載了一個(gè)DL函數(shù)庫而不去使用當(dāng)然是不可能的了,使用一個(gè)DL函數(shù)庫的最主要的一個(gè)函數(shù)就是dlsym(),這個(gè)函數(shù)在一個(gè)已經(jīng)打開的函數(shù)庫里面查找給定的符號(hào)。這個(gè)函數(shù)如下定義:



void * dlsym(void *handle, char *symbol);

  函數(shù)中的參數(shù)handle就是由dlopen打開后返回的句柄,symbol是一個(gè)以NIL結(jié)尾的字符串。

   如果dlsym()函數(shù)沒有找到需要查找的symbol,則返回NULL。如果你知道某個(gè)symbol的值不可能是NULL或者0,那么就很 好,你就可以根據(jù)這個(gè)返回結(jié)果判斷查找的symbol是否存在了;不過,如果某個(gè)symbol的值就是NULL,那么這個(gè)判斷就有問題了。標(biāo)準(zhǔn)的判斷方法 是先調(diào)用dlerror(),清除以前可能存在的錯(cuò)誤,然后調(diào)用dlsym()來訪問一個(gè)symbol,然后再調(diào)用dlerror()來判斷是否出現(xiàn)了錯(cuò) 誤。一個(gè)典型的過程如下:



dlerror(); /* clear error code */

s = (actual_type) dlsym(handle, symbol_being_searched_for);

if ((err = dlerror()) != NULL)

{

/* handle error, the symbol wasn't found */

}

else

{

/* symbol found, its value is in s */

}

  4.4. dlclose()

   dlopen()函數(shù)的反過程就是dlclose()函數(shù),dlclose()函數(shù)用力關(guān)閉一個(gè)DL函數(shù)庫。Dl函數(shù)庫維持一個(gè)資源利用的計(jì)數(shù) 器,當(dāng)調(diào)用dlclose的時(shí)候,就把這個(gè)計(jì)數(shù)器的計(jì)數(shù)減一,如果計(jì)數(shù)器為0,則真正的釋放掉。真正釋放的時(shí)候,如果函數(shù)庫里面有_fini()這個(gè)函 數(shù),則自動(dòng)調(diào)用_fini()這個(gè)函數(shù),做一些必要的處理。Dlclose()返回0表示成功,其他非0值表示錯(cuò)誤。

  4.5. DL Library Example

  下面是一個(gè)例子。例子中調(diào)入math函數(shù)庫,然后打印2.0的余弦函數(shù)值。例子中每次都檢查是否出錯(cuò)。應(yīng)該是個(gè)不錯(cuò)的范例:



? #include

? #include

? #include

? int main(int argc, char **argv)

? {

? ? void *handle;

? ? double (*cosine)(double);

? ? char *error;

? ? handle = dlopen ("/lib/libm.so.6", RTLD_LAZY);

? ? if (!handle) {

? ? ? ? fputs (dlerror(), stderr);

? ? ? ? exit(1);

? ? }

? ? cosine = dlsym(handle, "cos");

? ? if ((error = dlerror()) != NULL)

? {

? ? ? ? fputs(error, stderr);

? ? ? ? exit(1);

? ? }

? ? printf ("%f ", (*cosine)(2.0));

? ? dlclose(handle);

}

  如果這個(gè)程序名字叫foo.c,那么用下面的命令來編譯:



? gcc -o foo foo.c -ldl



5. 其他

  5.1. nm命令

   nm命令可以列出一個(gè)函數(shù)庫文件中的符號(hào)表。它對(duì)于靜態(tài)的函數(shù)庫和共享的函數(shù)庫都起作用。對(duì)于一個(gè)給定的函數(shù)庫,nm命令可以列出函數(shù)庫中定義 的所有符號(hào),包括每個(gè)符號(hào)的值和類型。還可以給出在原程序中這個(gè)函數(shù)(符號(hào))是在多少行定義的,不過這必須要求編譯該函數(shù)庫的時(shí)候加“-l”選項(xiàng)。

   關(guān)于符號(hào)的類型,這里我們?cè)俣嘤懻撘幌隆7?hào)的類型是以一個(gè)字母的形式顯示的,小寫字母表示這個(gè)符號(hào)是本地(local)的,而大寫字母則表示 這個(gè)符號(hào)是全局的(global,externel)。一般來說,類型有一下幾種:T、D、B、U、W。各自的含義如下:T表示在代碼段中定義的一般變量 符號(hào);D表示時(shí)初始化過的數(shù)據(jù)段;B表示初始化的數(shù)據(jù)段;U表示沒有定義的,在這個(gè)庫里面使用了,但是在其他庫中定義的符號(hào);W,weak的縮寫,表示如 果其他函數(shù)庫中也有對(duì)這個(gè)符號(hào)的定義,則其他符號(hào)的定義可以覆蓋這個(gè)定義。

  如果你知道一個(gè)函數(shù)的名字,但是你不知道這個(gè)函數(shù)在什么庫中定義的,那么可以用mn的“-o”選項(xiàng)和grep命令來查找?guī)斓拿帧?o選項(xiàng)使得顯示的每一行都有這個(gè)函數(shù)庫文件名。例如,你要查找“cos”這個(gè)是在什么地方定義的,大致可以用下面的命令:



nm -o /lib/* /usr/lib/* /usr/lib/*/* /usr/local/lib/* 2> /dev/null

| grep 'cos$'

  關(guān)于nm的更詳細(xì)的用法我們可以參考info文檔,位置是info:binutils#nm。

  5.2. 特殊函數(shù)_init和_fini

   函數(shù)庫里面有兩個(gè)特殊的函數(shù),_init和_fini,這個(gè)我們?cè)谇懊嬉呀?jīng)說過了。主要是分別用來初始化函數(shù)庫和關(guān)閉的時(shí)候做一些必要的處理, 我們可以把自己認(rèn)為需要的代碼放到這兩個(gè)函數(shù)里面,它們分別在函數(shù)庫被加載和釋放的時(shí)候被執(zhí)行。具體說,如果一個(gè)函數(shù)庫里面有一個(gè)名字為“_init”的 函數(shù)輸出,那么在第一次通過dlopen()函數(shù)打開這個(gè)函數(shù)庫,或者只是簡單的作為共享函數(shù)庫被打開的時(shí)候,_init函數(shù)被自動(dòng)調(diào)用執(zhí)行。與之相對(duì)應(yīng) 的就是_fini函數(shù),當(dāng)一個(gè)程序調(diào)用dlclose()去釋放對(duì)這個(gè)函數(shù)庫的引用的時(shí)候,如果該函數(shù)庫的被引用計(jì)數(shù)器為0了,或者這個(gè)函數(shù)庫是作為一般 的共享函數(shù)庫被使用而使用它的程序正常退出的時(shí)候,_fini就會(huì)被調(diào)用執(zhí)行。C語言定義它們的原型如下:
void _init(void); void _fini(void);
  當(dāng)用gcc編譯源程序?yàn)椤?o”文件的時(shí)候,需要加一個(gè)“-nostartfiles”選項(xiàng)。這個(gè)選項(xiàng)使得C編譯器不鏈接系統(tǒng)的啟動(dòng)函數(shù)庫里面的啟動(dòng)函數(shù)。否則,就會(huì)得到一個(gè)“multiple-definition”的錯(cuò)誤。

  5.3. 共享函數(shù)庫也可以使腳本(Scripts)

  GNU的loader允許使用特殊格式的腳本語言來寫一個(gè)函數(shù)庫。這對(duì)于那些需要間接包含其他函數(shù)庫的情況還是有用的。例如,下面是一個(gè)/usr/lib/libc.so的例子:

/* GNU ld script Use the shared library, but some functions are only in

the static library, so try that secondarily. */GROUP ( /lib/libc.so.6

/usr/lib/libc_nonshared.a )

  更多的信息可以參考texinfo文檔中關(guān)于ld鏈接的腳本部分。一般的信息還可以參考: info:ld#Options 和info:ld#Commands,也可以參考info:ld#Option Commands。

  5.4. GNU libtool

   如果你正在編譯的系統(tǒng)相很方便的移植到其他操作系統(tǒng)下,你可以使用GNU libtool來創(chuàng)建和安裝這個(gè)函數(shù)庫。GNU libtool是一個(gè)函數(shù)庫支持的典型的腳本。Libtool隱藏了使用一個(gè)可移植的函數(shù)庫的負(fù)責(zé)性。Libtool提供了一個(gè)可以移植的界面來創(chuàng)建 object文件,鏈接函數(shù)庫(靜態(tài)或者共享的),并且安裝這些庫。它還包含了libltdl,一個(gè)可移植的動(dòng)態(tài)函數(shù)庫調(diào)入程序的wrapper。更多的 詳細(xì)討論,可以在看到。

  5.5. 刪除一些符號(hào)

  在一個(gè)生產(chǎn)的文件中很多符號(hào)都是為了debug而包含的,占用了不少空間。如果空間不夠,而且這些符號(hào)也許不再需要,就可以將其中一些刪除。

   最好的方法就是先正常的生成你需要的object文件,然后debug和測試你需要的一些東西。一旦你完全測試完畢了,就可以用strip去刪 除一些不需要的符號(hào)了。Strip命令可以使你很方便的控制刪除什么符號(hào),而保留什么符號(hào)。Strip的具體用法可以參考其幫助文件。

  另外的方法就是使用GNU ld的選項(xiàng)“-S”和“-s”;“-S”會(huì)刪除一些debugger的符號(hào),而“-s”則是將所有的符號(hào)信息都刪除。通常我們可以在gcc中加這樣的參數(shù)“-Wl,-S”和“-Wl,-s”來達(dá)到這個(gè)目的。

摘要

下 面是一些例子,例子中我們會(huì)使用三種函數(shù)庫(靜態(tài)的、共享的和動(dòng)態(tài)加載的函數(shù)庫)。文件libhello.c是一個(gè)函數(shù)庫,libhello.h 是它的頭文件;demo_use.c則是一個(gè)使用了libhello函數(shù)庫的。Script_static和script_dynamic分別演示如何以 靜態(tài)和共享方式使用函數(shù)庫,而后面的demo_dynamic.c和script_dynamic則表示演示如何以動(dòng)態(tài)加載函數(shù)庫的方式來使用它。

(2002-08-25 17:38:37)

By Wing

  6. 更多的例子

   下面是一些例子,例子中我們會(huì)使用三種函數(shù)庫(靜態(tài)的、共享的和動(dòng)態(tài)加載的函數(shù)庫)。文件libhello.c是一個(gè)函數(shù)庫, libhello.h是它的頭文件;demo_use.c則是一個(gè)使用了libhello函數(shù)庫的。Script_static和 script_dynamic分別演示如何以靜態(tài)和共享方式使用函數(shù)庫,而后面的demo_dynamic.c和script_dynamic則表示演示 如何以動(dòng)態(tài)加載函數(shù)庫的方式來使用它。

  6.1. File libhello.c



/* libhello.c - demonstrate library use. */

#include

void hello(void)

{

printf("Hello, library world.

");

}

  6.2. File libhello.h



/* libhello.h - demonstrate library use. */

void hello(void);

  6.3. File demo_use.c



/* demo_use.c -- demonstrate direct use of the "hello" routine */

#include "libhello.h"

int main(void)

{

hello();

return 0;

}

  6.4. File script_static



#!/bin/sh

# Static library demo

# Create static library's object file, libhello-static.o.

# I'm using the name libhello-static to clearly

# differentiate the static library from the

# dynamic library examples, but you don't need to use

# "-static" in the names of your

# object files or static libraries.gcc -Wall -g -c -o libhello-static.o

libhello.c

# Create static library.ar rcs libhello-static.a libhello-static.o

# At this point we could just copy libhello-static.a

# somewhere else to use it.

# For demo purposes, we'll just keep the library

# in the current directory.

# Compile demo_use program file.gcc -Wall -g -c demo_use.c -o demo_use.o

# Create demo_use program; -L. causes "." to be searched during

# creation of the program. Note that this command causes

# the relevant object file in libhello-static.a to be

# incorporated into file demo_use_static.gcc -g -o demo_use_static

demo_use.o -L. -lhello-static

# Execute the program../demo_use_static

  6.5. File script_shared



#!/bin/sh

# Shared library demo

# Create shared library's object file, libhello.o.gcc -fPIC -Wall

-g -c libhello.c

# Create shared library.

# Use -lc to link it against C library, since libhello

# depends on the C library.gcc -g -shared -Wl,-soname,libhello.so.0 -o

libhello.so.0.0 libhello.o -lc# At this point we could just copy

libhello.so.0.0 into

# some directory, say /usr/local/lib.

# Now we need to call ldconfig to fix up the symbolic links.

# Set up the soname. We could just execute:

# ln -sf libhello.so.0.0 libhello.so.0

# but let's let ldconfig figure it out./sbin/ldconfig -n .

# Set up the linker name.

# In a more sophisticated setting, we'd need to make

# sure that if there was an existing linker name,

# and if so, check if it should stay or not.ln -sf libhello.so.0

libhello.so

# Compile demo_use program file.gcc -Wall -g -c demo_use.c -o

demo_use.o

# Create program demo_use.

# The -L. causes "." to be searched during creation

# of the program; note that this does NOT mean that "."

# will be searched when the program is executed.gcc -g -o demo_use

demo_use.o -L. -lhello

# Execute the program. Note that we need to tell the program

# where the shared library is,

using LD_LIBRARY_PATH.LD_LIBRARY_PATH="." ./demo_use

  6.6. File demo_dynamic.c



/* demo_dynamic.c -- demonstrate dynamic loading and

use of the "hello" routine */

/* Need dlfcn.h for the routines to

dynamically load libraries */

#include

#include

#include

/* Note that we don't have to include "libhello.h".

? However, we do need to specify something related;

? we need to specify a type that will hold the value

? we're going to get from dlsym(). */

/* The type "simple_demo_function" describes a function that

? takes no arguments, and returns no value: */

typedef void (*simple_demo_function)(void);

int main(void)

{

const char *error;

void *module;

simple_demo_function demo_function;

/* Load dynamically loaded library */

module = dlopen("libhello.so", RTLD_LAZY);

if (!module)

{

? fprintf(stderr, "Couldn't open libhello.so: %s

",dlerror());

? exit(1);

}

/* Get symbol */

dlerror();

demo_function = dlsym(module, "hello");

if ((error = dlerror()))

{

? fprintf(stderr, "Couldn't find hello: %s

", error);

? exit(1);

}

/* Now call the function in the DL library */

(*demo_function)();

/* All done, close things cleanly */

dlclose(module);

return 0;

}

  6.7. File script_dynamic



#!/bin/sh

# Dynamically loaded library demo

# Presume that libhello.so and friends have

# been created (see dynamic example).

# Compile demo_dynamic program file into an object file.gcc

-Wall -g -c demo_dynamic.c

# Create program demo_use.

# Note that we don't have to tell it where to search

for DL libraries,

# since the only special library this program uses won't be

# loaded until after the program starts up.

# However, we DO need the option -ldl to include the library

# that loads the DL libraries.gcc -g -o demo_dynamic

demo_dynamic.o -ldl

# Execute the program. Note that we need to tell the
# program where get the dynamically loaded library,
# using LD_LIBRARY_PATH.LD_LIBRARY_PATH="." ./demo_dynamic #linux 編程&shell 編程 分享到: 舉報(bào) 瀏覽(4117) 評(píng)論(1) 轉(zhuǎn)載

你可能也喜歡

  • 妞第二次生病
  • 媽媽和孩子
  • 昨天在同濟(jì)大學(xué)玩
  • 早期優(yōu)勢育兒
  • 特殊家庭作業(yè)
  • 吃飯比賽
  • 關(guān)于libnetfilter_queue出錯(cuò),以及如何安裝libnetfilter_queue

本文最近訪客

  • _丹楓_ 5月20日
  • chb_seaok 5月18日
  • NUPT小飛俠 5月15日
  • 小人物的大事 5月7日
  • angelevan 5月3日
  • xiaogang8800 4月28日
  • 杯雪滿江湖 4月24日
  • 卡拉虎 4月16日
評(píng)論 bluebirdye有用 2012-08-01 10:01 回復(fù) 幫助中心|?空間客服|?投訴中心|?空間協(xié)議 ?2013?Baidu

總結(jié)

以上是生活随笔為你收集整理的linux .so文件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

天天操天天干天天操天天干 | 高清不卡一区二区三区 | 国产在线视频一区二区三区 | 日本黄色a级大片 | 国产原创在线视频 | 亚洲最大免费成人网 | www.亚洲精品| 2024av| www免费看 | 99国产一区二区三精品乱码 | 91一区二区三区在线观看 | 欧美伦理一区二区三区 | 中文字幕日韩精品有码视频 | 国产亚洲精品bv在线观看 | 1区2区视频| 亚洲精品黄 | av超碰在线 | 欧美久久99 | 国产永久免费高清在线观看视频 | 日本精品va在线观看 | 亚洲一区二区视频 | 国产福利在线不卡 | 在线国产精品视频 | 国产最新精品视频 | 亚洲国产伊人 | 国产精品久久久久久久久久 | 亚洲一区久久久 | 一区二区三区视频在线 | 亚洲伊人av| 97超碰站| 国产xvideos免费视频播放 | 成人丁香花 | 在线观看视频一区二区 | 亚洲精品小视频在线观看 | 国产视频精选在线 | 91在线小视频 | 亚洲一区日韩精品 | 欧美精品成人在线 | 久久第四色| 国产精品美女久久久 | 久久久久综合视频 | 久久久影视| 91精品国产一区二区在线观看 | 最近中文字幕国语免费高清6 | 国产免费久久精品 | 亚洲精品一区二区三区四区高清 | 一区二区伦理 | 人人爽人人av | 天天摸日日操 | 四虎在线免费观看 | 亚洲精品美女在线 | 国产黄色免费电影 | 亚洲一二三区精品 | av三级在线播放 | 亚洲视频每日更新 | 国产一级视屏 | 亚洲爱爱视频 | 日韩一区正在播放 | 久久精品国产第一区二区三区 | 亚洲精品成人在线 | 在线免费亚洲 | 日本精品久久久久中文字幕 | 欧美精品免费在线 | 久久国内精品视频 | 在线精品亚洲一区二区 | 国产精品黄色 | 蜜臀av性久久久久蜜臀av | 波多野结衣视频一区二区 | 久久久国产精品人人片99精片欧美一 | 天天操夜夜想 | 欧美综合在线视频 | 国产精彩视频一区二区 | 久久综合九色综合97婷婷女人 | 18+视频网站链接 | 亚洲成人蜜桃 | 91久久偷偷做嫩草影院 | 玖玖玖国产精品 | 婷婷激情欧美 | 日韩欧美黄色网址 | 狠狠的干 | 久久网页 | 在线播放av网址 | 成人免费观看大片 | 伊人天堂网 | www夜夜| 久久天天躁夜夜躁狠狠躁2022 | 亚洲国产精品va在线看黑人动漫 | 国产亚洲精品久久久久5区 成人h电影在线观看 | 日韩精品一区二区三区水蜜桃 | 麻豆一区二区 | 五月天堂网 | 免费观看9x视频网站在线观看 | 人人揉人人揉人人揉人人揉97 | 亚洲精品日韩一区二区电影 | 国产又粗又猛又黄又爽的视频 | 久久综合九色综合欧美就去吻 | www.久艹| 久久久久国产精品视频 | 免费视频久久 | 精品 一区 在线 | 国产人免费人成免费视频 | 美女网站一区 | 91av视频导航 | 久久精品999 | 一区二区三区精品在线视频 | 99爱国产精品 | 丁香综合av | 久久不卡国产精品一区二区 | 免费视频99 | 久草在线免费看视频 | 综合激情av | 97久久久免费福利网址 | 精品国自产在线观看 | 日韩精品综合在线 | 久久午夜国产 | 在线v | 欧美激情xxxx性bbbb | 日韩免费电影一区二区 | 亚洲aⅴ乱码精品成人区 | av色网站 | 亚洲国产美女久久久久 | 天天操天天拍 | 中文字幕在线成人 | 国产中文在线字幕 | 久久久久五月天 | 欧美精品久久久久久久久久 | 又爽又黄在线观看 | 国产日韩在线播放 | 久久综合九色综合久久久精品综合 | 亚洲手机天堂 | 欧美日韩高清在线一区 | 亚洲免费资源 | 亚洲精品久久久久久中文传媒 | 国产成人在线一区 | 在线日韩中文 | 色婷婷97 | 五月婷婷综合在线视频 | 久久久久久久久久久综合 | 久久久久欠精品国产毛片国产毛生 | 91av视频在线免费观看 | 99久热在线精品视频成人一区 | 成人一区不卡 | 亚洲精品国产高清 | 欧美成人手机版 | 婷婷久久精品 | 六月久久婷婷 | 在线亚洲欧美视频 | 99热这里只有精品久久 | 亚洲日本成人网 | 99精品视频在线看 | 欧美黄色成人 | 久久影院精品 | 天天操,夜夜操 | 久久免费视频国产 | 最新日韩视频在线观看 | av在线免费在线观看 | 天天插天天爽 | av日韩国产 | 免费在线观看国产黄 | 天天干夜夜夜 | 亚洲欧美国产精品va在线观看 | 午夜视频在线观看网站 | 免费a网址 | 精品无人国产偷自产在线 | 久久精品视频中文字幕 | 欧美性超爽 | 国产精品99久久久久久久久 | 国产不卡在线播放 | 久久69av | 五月综合久久 | 激情 婷婷| 国产精品99久久久久人中文网介绍 | 国产在线1区| 一区二区三区免费播放 | 亚洲精品视频网 | av综合在线观看 | 成人av电影在线播放 | 成人av免费在线观看 | 色资源网免费观看视频 | 特级黄色一级 | www.福利视频 | 香蕉在线视频播放网站 | 欧亚久久 | 久操视频在线免费看 | 99免费看片 | 欧美久久久久久久 | 国产精品99久久久久久有的能看 | 99人久久精品视频最新地址 | 黄色三级免费观看 | 国产精品久久久久国产a级 激情综合中文娱乐网 | bbbbb女女女女女bbbbb国产 | 日韩中文字幕a | a电影免费看 | 五月婷婷亚洲 | 亚洲黄色区 | 国产免费叼嘿网站免费 | 草久在线观看 | 色爱成人网 | 日韩精品一区在线观看 | 涩av在线 | 免费视频 你懂的 | 懂色av一区二区在线播放 | 亚洲综合成人专区片 | 日韩午夜三级 | 国产福利一区二区三区在线观看 | 国产在线 一区二区三区 | 91av在线视频播放 | 在线之家免费在线观看电影 | 九九热在线观看 | 99免费| 人人爽人人爽人人爽 | 国产综合视频在线观看 | 久久成人精品视频 | 亚洲成人高清在线 | 99热国产在线观看 | 国产在线精品福利 | 久久国产精品精品国产色婷婷 | 天天插综合 | 9幺看片| 国产精品色在线 | 国产一级二级av | 久久精品99国产精品日本 | 日韩电影在线观看一区 | 欧美a级免费视频 | 亚州日韩中文字幕 | 日日躁天天躁 | 天天干,天天射,天天操,天天摸 | 中文字幕电影网 | 911国产在线观看 | 亚洲综合在 | 成人小视频在线观看免费 | 9色在线视频 | 天天操天天操天天爽 | 国产一级精品绿帽视频 | 国产精品中文字幕在线观看 | 开心激情久久 | 亚洲天堂网在线视频 | 久久综合久久综合久久 | 久久精品视频观看 | 婷婷综合激情 | 国产美女无遮挡永久免费 | 国产一区视频在线 | 婷婷久久一区二区三区 | 亚洲一区美女视频在线观看免费 | 二区三区中文字幕 | 亚洲a网| 午夜在线观看影院 | 最近中文字幕国语免费av | 1000部国产精品成人观看 | 亚洲一区二区三区miaa149 | 久久精彩 | 亚洲国产精品人久久电影 | 国产日韩欧美在线观看视频 | 天堂资源在线观看视频 | 91成人在线观看高潮 | 亚洲国产精品传媒在线观看 | 国产成人精品免高潮在线观看 | 日本激情动作片免费看 | 日本性视频| 日韩久久午夜一级啪啪 | 中文字幕电影网 | 日韩精品免费在线观看视频 | 精品视频在线观看 | 九色porny真实丨国产18 | 三级a视频 | 在线观看色视频 | 午夜 在线 | 国产精品久久久久影院 | 天天干天天天天 | 久热精品国产 | 激情欧美日韩一区二区 | 亚洲精品久久久久中文字幕二区 | 婷婷av网| 午夜在线观看 | 国产精品99精品久久免费 | 有没有在线观看av | 精品国产一区二区三区在线观看 | 在线播放视频一区 | 国产黄色大片免费看 | 国产精品破处视频 | 成人毛片在线观看视频 | 亚洲婷婷在线视频 | 黄色高清视频在线观看 | 亚洲一区精品二人人爽久久 | 成人免费电影 | 97在线视频免费 | 日本激情视频中文字幕 | 91尤物在线播放 | 丝袜美腿一区 | 国产精品日韩在线播放 | 婷婷视频在线 | 国产黄色一级大片 | 99久热在线精品视频 | 国产精品9999久久久久仙踪林 | 爱爱av网 | 久久综合日 | 国产99久久久国产精品免费看 | 亚洲欧美日韩一二三区 | 亚洲最大在线视频 | av性在线| 天天干.com | 成人影视免费 | 久久只有精品 | 国内少妇自拍视频一区 | 伊人资源站 | 午夜精品视频福利 | 六月丁香婷婷久久 | 99热精品视 | 国产玖玖视频 | 免费观看一区 | 国产精品久久久久久久久久直播 | 欧美黑人猛交 | 99国产精品久久久久老师 | 草久在线观看视频 | 最新日韩精品 | 久久精品国产精品亚洲 | 精品国产精品久久 | 九九九九精品九九九九 | 国产999视频 | 91香蕉亚洲精品 | 人人爽人人片 | 有码中文在线 | 91视频在线免费观看 | 韩国av免费看 | 国产亚洲精品免费 | 国产在线最新 | 婷婷中文字幕综合 | 欧美在线一二 | 一区二区三区免费在线观看视频 | 国产精品涩涩屋www在线观看 | 国产精品入口麻豆 | 欧美性爽爽 | 亚洲综合五月天 | 97人人射 | 91成人久久 | 93久久精品日日躁夜夜躁欧美 | 中文字幕不卡在线88 | 丰满少妇一级片 | 国产精品毛片 | 天天色天天射天天综合网 | 又黄又爽又无遮挡免费的网站 | 国产亚洲精品免费 | 日本性久久 | 久草香蕉在线 | 免费网站在线观看人 | 伊人国产视频 | 免费黄色小网站 | 国产精品一区在线播放 | 日韩性xxxx | 日韩丝袜在线观看 | 午夜性生活片 | 亚洲精品小区久久久久久 | 六月丁香社区 | 精品国产一区二区三区四区在线观看 | 超碰在线99 | 永久中文字幕 | 欧美日本一区 | 蜜臀av性久久久久蜜臀aⅴ流畅 | 国产区精品视频 | 四虎成人精品永久免费av九九 | 在线观看黄色大片 | 中文字字幕在线 | 国产美女精品人人做人人爽 | 欧美日韩精品在线 | 欧美日韩精品二区第二页 | 久久久国产精品电影 | 中文字幕中文字幕在线一区 | 激情综合网在线观看 | 欧美综合色在线图区 | 成人在线免费观看视视频 | 久久综合久久88 | 97精品国产一二三产区 | 久久免费看a级毛毛片 | 欧美精品在线视频 | 久久久久国产精品一区 | 日日日天天天 | 久久99久国产精品黄毛片入口 | 永久免费毛片 | 国产一区免费在线观看 | 日日夜夜av | 久久久久久在线观看 | www日韩欧美 | 黄色在线观看www | 五月宗合网 | 久久久午夜精品福利内容 | 中文字幕在线国产 | 色婷婷在线视频 | 亚洲精区二区三区四区麻豆 | 波多野结衣电影久久 | 成人一级电影在线观看 | 在线欧美最极品的av | 在线亚洲高清视频 | 911香蕉视频 | 国产免费高清视频 | 视频一区二区在线 | 中文字幕第一页在线vr | 狠狠操操操 | 最近av在线 | 国产v在线观看 | 日韩欧美视频在线免费观看 | 国产在线不卡 | 狠狠激情中文字幕 | 日韩在线精品一区 | 精品美女久久久久久免费 | 欧美 日韩 视频 | 亚洲三级黄色 | 美女在线观看网站 | 精品久久久成人 | 国产精品久久久久久久久久久杏吧 | 免费高清影视 | 97手机电影网 | 亚洲干视频在线观看 | 西西大胆免费视频 | 国产一级二级在线观看 | 99在线免费视频观看 | 在线看日韩 | 日韩在线不卡视频 | 欧美精品久久久久久久免费 | 久草免费在线观看视频 | 一区二区视频在线播放 | 日韩欧美一区二区三区黑寡妇 | 99爱视频| 日韩欧美在线观看 | 91免费看黄 | 日日射天天射 | 婷婷六月中文字幕 | 亚洲91中文字幕无线码三区 | 色av网站 | 欧美日韩在线观看一区 | 国产精品一区二区你懂的 | 久久超碰在线 | 日韩美女av在线 | 欧美激情va永久在线播放 | 日日夜夜免费精品视频 | 欧美性生活大片 | 国产乱码精品一区二区蜜臀 | 欧美另类高清 videos | 久久精品一二三 | 久久久久99精品成人片三人毛片 | 久草在线99 | 1024在线看片 | 丁香综合五月 | 久久99精品久久久久久三级 | 国产高清在线精品 | 久久综合五月 | 国产夫妻av在线 | 天天色宗合 | 人人草人人做 | 久久久美女 | 黄网在线免费观看 | 国产成人精品午夜在线播放 | 91成人免费看片 | 成人免费观看网址 | 中文字幕.av.在线 | 久久久久久久久久久高潮一区二区 | 91在线产啪 | 欧美91精品久久久久国产性生爱 | 日韩三级不卡 | 五月婷婷中文网 | 亚洲三级毛片 | www.五月天激情 | 久久av中文字幕片 | 亚洲精品综合一区二区 | 久久免费视频在线观看 | 国产一区二区在线观看视频 | 最近字幕在线观看第一季 | 亚洲乱码精品久久久久 | 五月婷婷中文 | 91精品久久久久久久91蜜桃 | 国产精品av在线免费观看 | 国产成人av一区二区三区在线观看 | 97超碰色| 97国产精品视频 | 天天干天天看 | 日韩欧美高清免费 | 亚洲天堂精品 | 波多野结衣在线播放一区 | 国产精品18久久久久久不卡孕妇 | 久久精品人人做人人综合老师 | 91av综合| 又黄又爽又刺激的视频 | 在线观看视频在线观看 | 色五月成人 | 在线日韩| 国产不卡网站 | 国产小视频你懂的在线 | 精品国产精品久久一区免费式 | 在线中文字母电影观看 | 国产伦理久久精品久久久久_ | 3d黄动漫免费看 | 国产一卡久久电影永久 | 玖玖玖在线 | 国产精品一区在线观看你懂的 | 插婷婷 | 国产精品久久久久久久电影 | 婷婷在线观看视频 | 日韩中文字幕免费电影 | 精品视频在线视频 | 中文字幕在线专区 | 91中文字幕 | 中文字幕亚洲欧美 | 午夜免费福利视频 | 天天干天天插伊人网 | 欧美精品久久 | 干干夜夜 | 亚洲国产电影在线观看 | 亚洲女欲精品久久久久久久18 | 欧美激情另类 | 亚洲欧美乱综合图片区小说区 | 黄色大全免费网站 | 久久久久久久久综合 | 超碰97在线看| 国产一卡二卡四卡国 | 在线观看中文字幕第一页 | 亚洲最新av网址 | 成人在线免费视频 | 精品免费视频. | 亚洲精品国产精品国自产观看浪潮 | 欧产日产国产69 | 天天色天天射天天综合网 | 日韩精品一区二区不卡 | 三级黄色片在线观看 | 中文区中文字幕免费看 | 亚州黄色一级 | 天天伊人网 | 91人人视频在线观看 | 国产在线高清视频 | 超碰97.com| 久久avav| 午夜在线观看影院 | 免费91麻豆精品国产自产在线观看 | 日韩成人精品一区二区三区 | 黄av在线 | 成人精品亚洲 | 久久这里精品视频 | 欧美电影在线观看 | 国产精品欧美日韩在线观看 | 久久综合九色欧美综合狠狠 | 草久久久久| 日韩精品网址 | 国产午夜精品一区二区三区欧美 | 偷拍区另类综合在线 | 久久精品久久精品久久39 | 91麻豆国产福利在线观看 | 国产精品手机看片 | 九九热精品视频在线播放 | 日韩专区视频 | 国产一区91 | 色婷婷综合五月 | 国产中文字幕大全 | 亚洲午夜av | 久久久久久黄 | 精品九九九九 | 日本黄色大片免费看 | 九色精品免费永久在线 | 狠狠狠的干 | 99视频在线精品 | 美女视频黄免费的 | 色天堂在线视频 | 国产精品一区二区免费 | 色偷偷888欧美精品久久久 | 午夜久久久久久久久 | 国产亚洲精品福利 | 免费看黄20分钟 | 天天综合网在线观看 | 午夜性色| 在线观看韩日电影免费 | 国产精品24小时在线观看 | 日韩av男人的天堂 | 一本一本久久a久久精品综合妖精 | 国产精品久久久久久久久费观看 | 黄色一级在线视频 | 婷婷精品在线视频 | 在线免费国产视频 | 黄色资源在线 | 日日夜夜免费精品视频 | 中文字幕专区高清在线观看 | 国产色综合天天综合网 | 天天射天天射 | 久久99在线观看 | 欧美在线视频精品 | 精品久久久99 | 国产欧美在线一区二区三区 | 欧美一级片播放 | av电影在线观看 | 97视频在线观看视频免费视频 | 亚洲国产欧美在线人成大黄瓜 | 国产精品免费在线视频 | 国产美女精彩久久 | 人人干免费 | 成人在线视频免费看 | 伊人色综合久久天天网 | 久草av在线播放 | 人人揉人人揉人人揉人人揉97 | 亚洲伊人成综合网 | 日韩在线观看精品 | 国产精品精品久久久久久 | 九九综合久久 | 成人影片在线播放 | 中文字幕一区二区三区久久 | 在线观看视频你懂 | 欧美成人在线免费观看 | 成人午夜剧场在线观看 | 亚洲国产天堂av | 黄色网免费 | 日韩在线观看视频中文字幕 | 成人在线观看网址 | 精品伦理一区二区三区 | 日本h视频在线观看 | 亚州精品一二三区 | 欧美日一级片 | 不卡的av中文字幕 | 亚洲黄色a | 亚洲国产日本 | 国产一级视频在线 | 一区二区三区 中文字幕 | 天天干天天射天天插 | 日韩三级视频在线观看 | 国产一级视频免费看 | 亚洲国产三级在线 | 丰满少妇久久久 | 欧美一区二区三区在线看 | 久久不射网站 | 五月婷网站 | av先锋中文字幕 | 91激情视频在线 | 国产不卡一 | 天天做日日做天天爽视频免费 | 91正在播放| 国产精品资源在线 | www日韩欧美 | 久精品视频 | 成人黄色资源 | 91污视频在线观看 | 播五月婷婷 | 一区二区观看 | 香蕉视频4aa | av黄色一级片 | 日韩av午夜| 亚洲少妇天堂 | 色香蕉网 | 丁香花中文在线免费观看 | 午夜免费福利视频 | 久99久久| 国产成人一级 | 视频1区2区 | 日韩高清一区在线 | 色999五月色 | 免费日韩一区二区三区 | 丁香久久综合 | 日韩三级视频 | 黄色特一级片 | 国产99免费| 国产在线观看污片 | 欧美 另类 交 | www.夜色.com | 亚洲精品乱码久久久久久 | 在线观看亚洲免费视频 | 免费看wwwwwwwwwww的视频 久久久久久99精品 91中文字幕视频 | 亚洲黄a | 毛片在线播放网址 | 久草视频一区 | 黄色美女免费网站 | 天天艹 | 天天操天天操天天操天天操天天操 | 久久精品国产一区二区三区 | 在线免费观看视频一区 | 黄色视屏在线免费观看 | 日日摸日日爽 | 精品国产欧美一区二区三区不卡 | 国产小视频在线看 | 久久影视精品 | 日韩欧美不卡 | av天天草| 久久久久亚洲国产 | 亚洲免费av电影 | 亚洲日日日 | 亚洲精品久久在线 | 亚洲va综合va国产va中文 | 久久久污 | 国产免费黄视频在线观看 | 中文字幕av在线免费 | 美女精品在线 | 国产精品久久久精品 | 欧美一级特黄aaaaaa大片在线观看 | 91九色在线观看视频 | 少妇高潮冒白浆 | 日本mv大片欧洲mv大片 | 日本精品一二区 | 伊人超碰在线 | 日韩免费观看视频 | 久草网首页 | 中文字幕免费 | 欧美日韩精品在线观看视频 | 91欧美精品 | 婷婷久久一区 | 欧美极品少妇xbxb性爽爽视频 | 成年人黄色在线观看 | 日日操日日干 | 欧亚久久| 成人在线视频免费 | 日本韩国在线不卡 | 亚洲女欲精品久久久久久久18 | 久久精品99国产精品亚洲最刺激 | 久久久精品午夜 | 国产成人一区三区 | 国产剧情一区二区 | 天天操天天干天天 | 欧美日产在线观看 | 欧美激情综合五月色丁香 | 日韩精品久久一区二区三区 | 九九热有精品 | 黄色综合 | 国产在线一区观看 | 国内精品久久久久久久久久久久 | 成年人电影免费在线观看 | 欧美激情奇米色 | 亚洲综合色网站 | 一区二区久久久久 | 久久国产免| 免费福利影院 | 精品视频成人 | 福利视频午夜 | 久久不射电影网 | 91精品国产网站 | 激情丁香综合五月 | 一级性生活片 | 亚洲成av人片在线观看香蕉 | 制服丝袜一区二区 | 国产一区国产二区在线观看 | 国产91粉嫩白浆在线观看 | 国产成人在线播放 | 欧美尹人 | 久久亚洲区 | 国产视频一区在线播放 | 男女激情麻豆 | 黄色一区二区在线观看 | 国产精品 美女 | 国产一区二区中文字幕 | 国产成人精品不卡 | 免费av在线网站 | 国产韩国日本高清视频 | 亚洲精品乱码久久久久久蜜桃91 | 日韩电影中文字幕在线 | 99久久一区 | 亚洲极色 | 中文字幕在线观看视频一区二区三区 | 国产黄色视| 国产乱老熟视频网88av | 香蕉视频在线免费 | 99热在线精品观看 | 精品在线观看一区二区 | 黄色一级免费网站 | 69久久久久久久 | 1000部国产精品成人观看 | 国产精品美女久久久久久久 | 国产又粗又猛又色又黄视频 | 日韩欧美视频一区二区三区 | www日日夜夜 | 六月丁香婷婷网 | 香蕉视频在线免费 | 午夜aaaa | 91色偷偷| 国际精品网 | 一级黄色大片 | 久久伊人精品一区二区三区 | 亚洲精品456在线播放 | 91重口视频 | 韩国在线视频一区 | 免费在线国产黄色 | 青青河边草免费观看 | 国产精品理论视频 | 超碰在线人人97 | 久久爱www. | 一区二精品 | 91.dizhi永久地址最新 | 黄a网站 | 99色视频 | 99日韩精品 | 91视频链接 | 99精品热 | 久久久久亚洲最大xxxx | 午夜 久久 tv | 在线观看成人小视频 | 国产亚洲精品av | 99视频偷窥在线精品国自产拍 | 国产成人亚洲在线观看 | 丁香一区二区 | 69国产成人综合久久精品欧美 | 激情黄色一级片 | 91精品国产自产在线观看 | 国产精品露脸在线 | 日韩高清 一区 | 在线国产能看的 | 久久99免费观看 | 人人干网站 | 在线观看精品一区 | 波多野结衣视频一区二区 | 夜色资源网 | 不卡精品视频 | 日本aa在线 | 天天色成人网 | 亚洲精品国偷拍自产在线观看蜜桃 | 999久久a精品合区久久久 | 国产成人精品综合久久久久99 | 九月婷婷人人澡人人添人人爽 | 麻豆传媒视频在线播放 | 欧美亚洲精品一区 | 视色网站 | 激情五月综合网 | av中文字幕网站 | www.777奇米 | 亚洲欧美观看 | 欧美综合在线视频 | 久久久久亚洲精品 | 亚州av成人 | 亚洲理论在线观看 | 岛国av在线免费 | 日韩中文在线字幕 | 欧美电影在线观看 | 午夜久久久影院 | 国产精品一区久久久久 | 国产不卡网站 | 国产久草在线观看 | 国产又粗又猛又黄又爽视频 | 久久久久久久久国产 | 91视频91蝌蚪 | 日韩av电影手机在线观看 | 免费观看久久 | 成人禁用看黄a在线 | 1024手机基地在线观看 | 久久久久久久影院 | 天天操天天透 | 国产成人区 | 91麻豆精品国产91久久久久久 | 在线观看视频免费播放 | 午夜.dj高清免费观看视频 | 六月色播 | 片网站| 成人午夜精品久久久久久久3d | 成人精品一区二区三区中文字幕 | 91综合久久一区二区 | 五月天婷婷免费视频 | 久久免费国产电影 | 国产一级片不卡 | 免费在线观看av电影 | 麻豆视传媒官网免费观看 | 国产精品丝袜在线 | 免费日韩av电影 | 国产精品免费在线播放 | 在线国产高清 | 黄色www免费 | 亚洲免费av一区二区 | 久久人视频 | 日韩精品一区二区三区水蜜桃 | 国产日韩精品在线 | 成人免费在线看片 | 在线观看亚洲视频 | 成人一区二区在线 | 色全色在线资源网 | 黄色激情网址 | 久久综合五月天婷婷伊人 | 国产精品久久久久久久av电影 | 男女激情免费网站 | 国产一区二区电影在线观看 | 色在线免费视频 | 在线亚洲午夜片av大片 | 久久久久成人精品免费播放动漫 | 热re99久久精品国产99热 | 久久看片网站 | 午夜美女wwww | 日韩视频一区二区在线观看 | 精品久久久久久久久久久久久久久久 | 一区二区电影在线观看 | 成年人免费在线观看网站 | 欧美性生活久久 | 免费av在线网站 | 亚洲精品美女免费 | 国产一卡久久电影永久 | 国产精品美女在线观看 | 婷婷五情天综123 | 国产精品一区二区免费在线观看 | 欧美日韩在线免费视频 | 精品在线播放 | 高清av影院 | 超碰97人 | 中文字幕在线观看免费高清完整版 | 中文字幕高清 | av超碰在线 | 六月丁香综合 | 丝袜美女在线观看 | 超碰97人人爱 | 欧美日韩免费一区二区三区 | 国产中文字幕一区 | 欧洲精品视频一区 | japanesexxxxfreehd乱熟 | 国产精品久久久久久久久久免费看 | 麻豆视频入口 | 又黄又爽又湿又无遮挡的在线视频 | 精品在线亚洲视频 | 日韩a欧美 | 亚洲天天在线 | 亚洲综合精品在线 | 久久爽久久爽久久av东京爽 | 在线观看www. | 中文字幕乱在线伦视频中文字幕乱码在线 | 99精品视频在线免费观看 | 久久这里只有精品首页 | 国产99久久九九精品免费 | 欧美91精品国产自产 | 狠狠插狠狠操 | 精品91在线 | 亚洲理论在线观看电影 | 最新中文在线视频 | 国产精品久久久免费 | 97视频免费观看2区 亚洲视屏 | 久久精品美女 | 激情av一区二区 | 国产明星视频三级a三级点| 久草色在线观看 | 一级a性色生活片久久毛片波多野 | 97人人添人澡人人爽超碰动图 | 成年人国产精品 | h视频在线看 | 欧美aa在线 | 国产又粗又猛又爽又黄的视频先 | 国产精品视频免费观看 | 国产一区二区三区四区大秀 | 伊人亚洲精品 | 久久人人爽人人爽人人片av软件 | 亚洲精区二区三区四区麻豆 | 欧美极品xxx | 欧美在线观看禁18 | 欧美成人精品欧美一级乱 | 亚洲 欧洲av | 午夜久久久久久久久久影院 | 欧美日韩高清免费 | 国产精品69久久久久 | 日韩在线首页 | 久久精品99久久久久久2456 | 午夜精品一二三区 | av成人黄色| 久久国内精品视频 | 欧美日韩国产在线一区 | 人人爽久久涩噜噜噜网站 | 色干干 | 最新中文字幕在线播放 | 久久久久久毛片精品免费不卡 | 国产精品久久一区二区三区不卡 | 精品国产伦一区二区三区观看体验 | 久久这里只有精品视频首页 | 久久久久欠精品国产毛片国产毛生 | 成年人免费在线 | 精品久久美女 | 亚洲经典中文字幕 | 黄免费在线观看 | 国产a国产 | 国产网站在线免费观看 | 亚洲国产福利视频 | 久久69精品久久久久久久电影好 | 一级电影免费在线观看 | av看片在线| 九九视频网站 | 国产精品久久久一区二区 | 999视频在线播放 | 九九热只有精品 | 欧美一级黄色网 | 亚洲精品视频网站在线观看 | 少妇高潮冒白浆 | 国产成人av一区二区三区在线观看 | 天天av在线播放 | 在线日韩中文字幕 | 天天天天天天操 | 国产二区电影 | adn—256中文在线观看 | 国产专区在线视频 | 免费av片在线 | 夜夜视频资源 | 免费观看午夜视频 | 国产高清一 | 欧美 亚洲 另类 激情 另类 | 久久精品久久综合 | 99c视频高清免费观看 | 99热最新精品 | 精品国产视频一区 | 亚洲毛片一区二区三区 | 超碰97人| 91精品国产99久久久久久久 | 五月情婷婷 | 青青河边草观看完整版高清 | 中文字幕九九 | 久久免费黄色大片 | 97免费视频在线 | 人人人爽 | 国产精品久久久影视 | 九九涩涩av台湾日本热热 | 中文字幕在线看视频国产中文版 | 99在线热播精品免费99热 |