青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

蝸牛的家
男兒當自強
posts - 48,  comments - 21,  trackbacks - 0

linux內存管理策略
   
linux低層采用三層結構,實際使用中可以方便映射到兩層或者三層結構,以適用不同的硬件結構。最下層的申請內存函數get_free_page。之上有三種類型的內存分配函數
(1)kmalloc類型。內核進程使用,基于slab技術,用于管理小于內存頁的內存申請。思想出發點和應用層面的內存緩沖池同出一轍。但它針對內核結構,特別處理,應用場景固定,不考慮釋放。不再深入探討。
(2)vmalloc類型。內核進程使用。用于申請不連續內存。
(3)brk/mmap類型。用戶進程使用。malloc/free實現的基礎。
有關詳細內容,推薦http://www.kerneltravel.net/journal/v/mem.htmhttp://www.kerneltravel.net上有不少內核相關知識。
malloc系統的內存管理策略
   malloc系統有自己的內存池管理策略,malloc的時候,檢測池中是否有足夠內存,有則直接分配,無則從內存中調用brk/mmap函數分配,一般小于等于128k(可設置)的內存,使用brk函數,此時堆向上(有人有的硬件或系統向下)增長,大于128k的內存使用mmap函數申請,此時堆的位置任意,無固定增長方向。free的時候,檢測標記是否是mmap申請,是則調用unmmap歸還給操作系統,非則檢測堆頂是否有大于128k的空間,有則通過brk歸還給操作系統,無則標記未使用,仍在glibc的管理下。glibc為申請的內存存儲多余的結構用于管理,因此即使是malloc(0),也會申請出內存(一般16字節,依賴于malloc的實現方式),在應用程序層面,malloc(0)申請出的內存大小是0,因為malloc返回的時候在實際的內存地址上加了16個字節偏移,而c99標準則規定malloc(0)的返回行為未定義。除了內存塊頭域,malloc系統還有紅黑樹結構保存內存塊信息,不同的實現又有不同的分配策略。頻繁直接調用malloc,會增加內存碎片,增加和內核態交互的可能性,降低系統性能。linux下的glibc多為Doug Lea實現
應用層面的內存池管理
   1:不定長內存池。
   典型的實現有apr_pool。優點是不需要為不同的數據類型創建不同的內存池,缺點是造成分配出的內存不能回收到池中。這是由于這種方案以session為粒度,以業務處理的層次性為設計基礎。
   apr_pool中的內存池并不是僅僅一個內存池,相反而是存在多個內存池,這些內存池之間形成層次結構。根據處理階段的周期長短引出了子內存池的概念,與之對應的是父內存池以及根內存池的概念,它們的唯一區別就是存在的周期的不同而已。比如對于HTTP連接而言,包括兩種內存池:連接內存池和請求內存池。由于一個連接可能包含多個請求,因此連接的生存周期總是比一個請求的周期長,為此連接處理中所需要的內存則從連接內存池中分配,而請求則從請求內存池中分配。而一個請求處理完畢后請求內存池被釋放,一個連接處理后連接內存池被釋放。根內存池在整個Apache運行期間都存在,因此apr_pool比較適合用于內存使用的生命期有明顯層次的情況.
2:定長內存池
    典型的實現有BOOST,LOKI。特點是為不同類型的數據結構分別創建內存池,需要內存的時候從相應的內存池中申請內存,優點是可以在使用完畢立即把內存歸還池中,可以更為細粒度的控制內存塊。
 偽代碼分析LOKI內存池:


//char型的firstAvailableBlock_所以沒辦法存儲大于255的位置
struct Chunk 
{
    
void Init(std::size_t blockSize,unsigned char blocks);
    
void Release();
    
void* Allocate(std::size_t blockSize);
    
void Deallocate(void* p,std::size_t blockSize);
    unsigned 
char* pData_;
    unsigned 
char firstAvailableBlock_, blocksAvailable_; //第一個可用block塊和可用block塊總數
}
;
/*
每個chunk管理一定數量的block,每個chunk中lock的申請和釋放時間都是O(1)。
chunk:首次申請一塊連續內存,pdata_指向該內存基址,依據block大小,劃分成多個連續的block,每個block開頭的第一個字節保存該block的順序號,firstAvailableBlock_存儲上次分配出的block序號。
分配block:返回pdata_+firstAvailableBlock_*blocksize,同時firstAvailableBlock_賦值為該快的序列號
收回block:block指針假設為pblock,該塊序列號賦值為firstAvailableBlock_,firstAvailableBlock_賦值為(pblock-pdata_)/blocksize即可
*/

 

//得益于char的小所以可以分配很小的block出來,且在需要對齊的情況下不會出現問題
void Chunk::Init(std::size_t blockSize,unsigned char blocks)
{
    pData_ 
= new unsigned char(blockSize*blocks); 
    firstAvailableBlock_ 
= 0;    //上次分配的塊的序列號
    blocksAvailable_ = blocks;
    unsigned 
char i = 0;
    unsigned 
char *= pData_;
    
for (;i != blocks; p += blockSize)
    
{
        
*= ++i;
    }

}


//分配blockSize單位固定大小的內存
void* Chunk::Allocate(std::size_t blockSize)
{
    
if (!blocksAvailable_)
    
{
        
return 0;
    }

    unsigned 
char* pResult = pData_ +(firstAvailableBlock_ * blockSize); //得到該塊的序列號,第一個位置存儲的為序列號
    firstAvailableBlock_ = *pResult;
    
--blocksAvailable_;
    
return pResult;
}


void Chunk::Deallocate(void* p,std::size_t blockSize)
{
    ASSERT(p 
>= pData_);    //歸還的內存必須大于分配起始內存
    unsigned char* toRelese = static_cast<unsigned char*>(p); //強制轉換,靜態,不檢測運行態
    *toRelese = firstAvailableBlock_;
    firstAvailableBlock_ 
= static_cast<unsigned char>((toRelese - pData_)/blockSize);
    ASSERT(firstAvailableBlock_ 
== (toRelese - pData_)/blockSize);
    
++blockSize;
}

 

#include "pool.h"

class FixedAllocator
{
public:
    
void* Allocate(std::size_t blockSize_);
private:
    std::size_t blocksize_;
    unsigned 
char numBlocks_;
    typedef std::vector
<Chunk> Chunks;
    Chunks Chunks_;
    Chunk
* allocChunk_;    //上一次分配的Chunks
    Chunk* deallocChunk_;
}
;

/*
chunk中的block上限是255,不具有通用性,因此封裝了一層,成為FixedAllocator,它保存一個vector<chunk>。
FixedAllocator中的block申請:FixedAllocator中保存活動的chunk(上次有空閑空間的chunk),申請block的
    時候如果活動chunk有空閑快,直接申請,否則掃描vector,時間復雜度o(N),同時更新活動chunk。
FixedAllocator中的回收block:簡單想,給定block回收到FixedAllocator,自然要掃描vector,以確認 block屬于哪個chunk,以便chunk回收。
    實際實現的時候,Loki針對應用場景進行了優化,一般使用都是批量使用,回收一般和申請順序相同或者相反,
    因此FixedAllocator保存上次回收block的chunk指針,每次回收優先匹配這個chunk,匹配不上則以該chunk為中心,向兩側chunk順序檢測。
FixedAllocator帶來的優點:上文提到的消除了block的上限限制。另一方面,可以以chunk為單位,把內存歸還給操作系統。
    實際實現中防止剛釋放的內存立即又被申請,是存在兩個空閑chunk的時候才回收一個。這個特點,這里暫時歸結為優點吧。
    實際使用中,回收多余內存個人認為是個缺點,意義并不是很大。
FixedAllocator帶來的缺點:很明顯,就是申請回收block的時間復雜度。
*/

 


//////////////////////////////////////////////////////////////////////////
void* FixedAllocator::Allocate(std::size_t blockSize_)
{
    
if (allocChunk_ ==0 || allocChunk_.blocksAvailable_ == 0)
    
{
        Chunks::iterator i 
= Chunks.begin();
        
for (;;++i)
        
{
            
if (i ==  Chunks_.end())
            
{
                Chunks_.push_back(Chunk());
                Chunk
& newChunk = Chunks_.back();
                newChunk.Init(blockSize_,Blocks);
                allocChunk_ 
= newChunk;
                deallocChunk_ 
= &Chunks_.front();
            }

            
if (i->blocksAvailable_)
            
{
                allocChunk_ 
= &*i;
                
break;
            }

        }

    }

    ASSERT(allocChunk_ 
!= 0);
    ASSERT(allocChunk_
->blocksAvailable_ > 0);
    
return allocChunk_->Allocate(blockSize_);        
}

 

class SmallObjAllocator
{
public:
    SmallObjAllocator(std::size_t chunkSize,std::size_t maxObjectSize); 
//chunk的預設大小,超過maxObjectSize大小的用new申請
    void* Allocate(std::size_t numBytes);
    
void Deallocate(void* p, std::size_t size);
private:
    std::vector
<FixedAllocator> pool_;
    FixedAllocator
* pLastAlloc_;    //最后一次分配用的FixedAllocator
    FixedAllocator* pLastDealloc_;
}
;
/*
截至到FixedAllocator層面blocksize都是定長。因此封裝一層適用于任意長度的內存申請。
SmallObjAllocator保存了一個FixedAllocator的數組pool_,存儲擁有不同block長度的FixedAllocator。
    當前SmallObjAllocator的構造函數有3個參數:chunksize,maxblocksize,alignsize。
    數組元素個數取 maxblocksize除以alignsize的向上取整。每個FixedAllocator中實際的blocksize是(下標+1) *alignsize。
SmallObjAllocator中block申請:依據block和alignsize的商直接取到數組pool_下標,使用相應的FixedAllocator申請。
SmallObjAllocator中回收block:根據block和alignsize的商直接找到相應的FixedAllocator回收。
優點:差異化各種長度的對象申請,增強了易用性。
缺點:增加掃描的時間復雜度,當前版本的loki浪費內存。這也是進一步封裝,屏蔽定長申請的細節,帶來的負面效應。
*/

class SmallObject
{
//重載new,delete,設計為模板函數等
}
;
/*
暴露給外部使用的一層。引入模版,當前版本 SmallObject有6個模版參數,第一個是線程策略,緊接著的三個正好是SmallObjAllocator層面的
三個構造參數,下面的一個生存期策略,最后的是鎖方式。
這里說下SmallObjAllocator層面的三個默認參數值,分別是4096,256,4。意味著SmallObjAllocator層面有數組(256+4-1)/4=64個,
數組存儲的FixedAllocator中的chunksize一般都是4096(當4096<= blocksize*255時候)字節(第一個chunk的申請推遲到首次使用的時候),
各FixedAllocator中的chunk的 blocksize依次是4、8256,大于256字節的內存申請交給系統的malooc/new管理,
數組中FixedAllocator 中單個chunk中的blocknum依次是4096/4=824>255取255、2554096/256=16。如果這不能滿足需求,
請調用的時候顯式賦值。
當前loki提供了三種線程策略:
SingleThreaded  單線程 
ObjectLevelLockable  對象級別,一個對象一個鎖 
ClassLevelLockable  類級別,一個類一個鎖,該類的所有對象共用該鎖 
目前只提供了一種鎖機制:Mutex
它的基類SmallObjectBase復寫了new/delete操作子,因此直接繼承SmallObject就可以象普通的類一樣new/delete,并且從內存池分配內存。
SmalObject中block申請和釋放都從一個全局的SmallObjAllocator單例進行。
*/

(2)boost::pool系列。boost 的內存池最低層是simple_segregated_storage,類似于Loki中的chunk,在其中申請釋放block(boost中把 block稱為chunk,暈死,這里還是稱其為block)采用了和loki的chunk中同樣的算法,不同的是 simple_segregated_storage使用void*保存block的塊序號,loki中使用char,因此boost中的 simple_segregated_storage沒有255的上限限制,自然也就不需要再其上再封裝一層類似與FixedAllocator的層面。另boost沒有屏蔽塊的大小,直接提供定長的接口給用戶,省掉了SmallObjAllocator層面。因此boost的內存池申請釋放block的時間復雜度都是O(1)(object_pool和pool_allocator除外),另避免的小內存的浪費,同時boost不能象loki那樣在將 block歸還給內存池的時候根據chunk的空閑數量釋放內存歸還給系統,只能顯式調用釋放內存函數或者等內存池銷毀的時候,基本上和內存池生命周期內永不釋放沒什么區別。
    boost的最低層是simple_segregated_storage,主要算法和loki中的chunk一樣,不多說了。這里說下影響上層接口的兩類實現:add_block/malloc/free、add_ordered_block/malloc/ordered_free,兩種低層實現造成 boost上層設計的成功與失敗,前者效率高,和loki一樣直接增加釋放,時間復雜度O(1),后者掃描排序,時間復雜度O(n)。
    boost提供了四種內存池模型供使用:pool、object_pool、singleton_pool、pool_allocator/fast_pool_allocator。
1)pool
基本的定長內存池

#include <boost/pool/pool.hpp>
typedef struct student_st
{
   
char name[10];
   
int age;
}
CStudent;
int main()
{
   boost::pool
<> student_pool(sizeof(CStudent));
   CStudent 
* const obj=(CStudent *)student_pool.malloc();
   student_pool.free(obj);
   
return 0;
}

    pool的模版參數只有一個分配子類型,boost提供了兩種 default_user_allocator_new_delete/default_user_allocator_malloc_free,指明申請釋放內存的時候使用new/delete,還是malloc/free,默認是default_user_allocator_new_delete。構造函數有2個參數:nrequested_size,nnext_size。nrequested_size是block的大小(因為void*保存序號,因此boost內置了block的最小值,nrequested_size過小則取內置值),nnext_size是 simple_segregated_storage中內存不足的時候,申請的block數量,默認是32。最全面的實例化pool類似這樣: boost::pool<boost::default_user_allocator_malloc_free> student_pool(sizeof(CStudent),255);
    pool提供的函數主要有:
malloc/free  基于add_block/malloc/free實現,高效
ordered_malloc/ordered_free 基于add_ordered_block/malloc/ordered_free實現,在pool中無任何意義,切勿使用。
release_memory/purge_memory 前者釋放池中未使用內存,后者釋放池中所有內存。另池析構也會釋放內存

2)object_pool

#include <boost/pool/object_pool.hpp>

class A{
public:
   A():data_(
0){}
private:
   
int data_;
}
;
int main()
{
   boost::object_pool
<A> obj_pool;
   A 
*const pA=obj_pool.construct();
   obj_pool.destroy(pA);
   
return 0;
}

    object_pool繼承至pool,有兩個模版參數,第一個就是對象類型,第二個是分配子類型,默認同pool是 default_user_allocator_new_delete。構造函數參數只有nnext_size,意義以及默認值同pool。最全面的實例化object_pool類似這樣:boost::pool<A,boost:: default_user_allocator_malloc_free> obj_pool(255);
object_pool提供的函數主要有(繼承至父類的略):
malloc/free 復寫pool的malloc/free,add_ordered_block/malloc/ordered_free實現
construct/destroy 基于本類的malloc/free實現,額外調用默認構造函數和默認析構函數。
~object_pool 若析構的時候有對象未被destroy,可以檢測到,釋放內存前對其執行destroy
   object_pool 主要著眼于“自動析構”,在沒有gc的情況下,達到提高效率和自動管理內存的目的。而且它也特別適合于“多次申請,一次釋放”的情況.所以它甚至是鼓勵你忽略使用destroy(從它的例子就可以看出來)。

destroy函數并沒有提高復雜度,因為內部鏈表始終處于有序狀態(由于使用order_malloc,order_free),所以不論是逐個釋放,還是成批釋放,它的復雜度都是O(N)
3)singleton_pool
pool的加鎖版本。

#include <boost/pool/singleton_pool.hpp>
typedef struct student_st
{
   
char name[10];
   
int age;
}
CStudent;
typedef struct singleton_pool_tag
{}singleton_pool_tag;
int main()
{
   typedef boost::singleton_pool
<singleton_pool_tag,sizeof(CStudent)>  global;
   CStudent 
* const df=(CStudent *)global::malloc();
   global::free(df);
   
return 0;
}

    singleton_pool為單例類,是對pool的加鎖封裝,適用于多線程環境,其中所有函數都是靜態類型。它的模版參數有5個,tag:標記而已,無意義;RequestedSize:block的長度;UserAllocator:分配子,默認還是 default_user_allocator_new_delete;Mutex:鎖機制,默認值最終依賴于系統環境,linux下是 pthread_mutex,它是對pthread_mutex_t的封裝;NextSize:內存不足的時候,申請的block數量,默認是32。最全面的使用singleton_pool類似這樣:typedef boost::singleton_pool<singleton_pool_tag,sizeof(CStudent),default_user_allocator_new_delete,details::pool::default_mutex,200>  global;
    它暴露的函數和pool相同。
4)pool_allocator/fast_pool_allocator
    stl::allocator的替換方案。兩者都是基于singleton_pool實現,實現了stl::allocator要求的接口規范。兩者的使用相同,區別在于pool_allocator的實現調用ordered_malloc/ordered_free, fast_pool_allocator的實現調用malloc/free,因此推薦使用后者。

#include <boost/pool/pool_alloc.hpp>
#include 
<vector>
typedef struct student_st
{
 
char name[10];
 
int age;
}
CStudent;

int main()
{
  std::vector
<CStudent *,boost::fast_pool_allocator<CStudent *> > v(8);
  CStudent 
*pObj=new CStudent();
  v[
1]=pObj;
  boost::singleton_pool
<boost::fast_pool_allocator_tag,sizeof(CStudent *)>::purge_memory(); 
  
return 0;
}

    fast_pool_allocator的模版參數有四個:類型,分配子,鎖類型,內存不足時的申請的block數量,后三者都有默認值,不再說了。它使用的singleton_pool的tag是boost::fast_pool_allocator_tag。

posted on 2008-08-26 14:05 黑色天使 閱讀(2381) 評論(0)  編輯 收藏 引用 所屬分類: 內存管理技術

只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理



<2025年10月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

常用鏈接

留言簿(2)

隨筆分類

隨筆檔案

文章檔案

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            久久精品一二三| 香蕉成人啪国产精品视频综合网| 久久国产黑丝| 亚洲区中文字幕| 9i看片成人免费高清| 国产日韩高清一区二区三区在线| 免费的成人av| 国产精品青草久久| 欧美成人激情在线| 国产精品日本欧美一区二区三区| 欧美大片第1页| 国产九九精品视频| 亚洲三级免费观看| 夜夜躁日日躁狠狠久久88av| 性欧美暴力猛交69hd| 亚洲欧洲免费视频| 欧美亚洲一级| 一本色道88久久加勒比精品| 欧美一区二区高清在线观看| 99re66热这里只有精品3直播| 欧美一区二区视频97| 正在播放亚洲| 欧美+日本+国产+在线a∨观看| 午夜精品福利视频| 蜜乳av另类精品一区二区| 欧美影院成人| 国产精品国产精品国产专区不蜜| 欧美成人激情视频免费观看| 国产日本亚洲高清| 亚洲人成网站色ww在线| 影音先锋在线一区| 欧美一级成年大片在线观看| 午夜精品久久久久久久99樱桃| 欧美另类人妖| 欧美国产第一页| 在线观看不卡| 久久精品国产第一区二区三区| 欧美一区二区大片| 国产精品美女久久久久久免费 | 亚洲欧美日韩一区二区三区在线| 亚洲破处大片| 老司机午夜精品视频在线观看| 久久国产精品久久久久久| 国产精品视频xxxx| 亚洲欧美国产制服动漫| 午夜伦理片一区| 国产精品久久久久久久久久久久久久 | 久久婷婷国产综合精品青草| 久久岛国电影| 国产目拍亚洲精品99久久精品| 亚洲私人影院在线观看| 亚洲一区国产精品| 国产精品久久久久久模特| 一区二区三区色| 亚洲美女在线观看| 欧美激情一区三区| 亚洲精品日产精品乱码不卡| 日韩一级黄色片| 欧美日韩在线观看一区二区三区| 一本色道久久88精品综合| 亚洲男女毛片无遮挡| 国产精品一级在线| 久久狠狠婷婷| 免费一级欧美片在线播放| 亚洲国产91精品在线观看| 欧美高清视频一区二区三区在线观看| 亚洲欧洲精品一区二区三区不卡| 99国产一区二区三精品乱码| 欧美日韩国产成人在线观看| 在线综合亚洲欧美在线视频| 欧美伊人久久| 亚洲欧美日韩在线综合| 久久最新视频| 国产一本一道久久香蕉| 久久国产精品99国产| 欧美电影在线免费观看网站| 中文亚洲欧美| 国内精品视频一区| 免费视频一区| 亚洲色无码播放| 久久蜜臀精品av| 亚洲精品视频中文字幕| 国产精品第13页| 久久久精品一区二区三区| 亚洲国产精品悠悠久久琪琪| 亚洲一区二区三区在线观看视频| 国产偷自视频区视频一区二区| 麻豆91精品| 亚洲欧美国产毛片在线| 亚洲高清一区二区三区| 性视频1819p久久| 亚洲福利免费| 国产伦精品一区二区三区四区免费| 美女图片一区二区| 亚洲免费在线观看视频| 欧美aa在线视频| 亚洲欧美变态国产另类| 亚洲黄色视屏| 国产一级揄自揄精品视频| 欧美成人免费小视频| 午夜精品久久久久久久久久久久| 亚洲丶国产丶欧美一区二区三区| 欧美专区日韩专区| 亚洲精品一二三| 国产自产精品| 国产精品久久久久久久久果冻传媒 | 国产精品jizz在线观看美国 | 欧美影院精品一区| 99亚洲伊人久久精品影院红桃| 国产亚洲一区二区三区| 欧美日韩国产综合久久| 美女主播一区| 久久久久中文| 欧美一区1区三区3区公司| 夜夜嗨av一区二区三区网站四季av| 免费人成网站在线观看欧美高清| 欧美一二区视频| 亚洲天堂偷拍| 一区二区三区四区国产精品| 亚洲国语精品自产拍在线观看| 很黄很黄激情成人| 国产亚洲aⅴaaaaaa毛片| 国产精品久久久久999| 欧美日韩精品欧美日韩精品 | 亚洲承认在线| 久热精品视频在线| 久久久精品性| 欧美有码在线观看视频| 亚洲欧美中日韩| 亚洲欧美另类综合偷拍| 亚洲伊人一本大道中文字幕| 国产精品99久久久久久久vr| 一本色道久久88综合亚洲精品ⅰ| 亚洲国产片色| 亚洲电影免费在线| 在线观看91精品国产入口| 国产一区二区三区久久久久久久久| 国产精品免费小视频| 欧美午夜精品理论片a级大开眼界 欧美午夜精品理论片a级按摩 | 欧美一区二区在线免费播放| 亚洲国产mv| 欧美激情一区二区久久久| 欧美高清在线播放| 亚洲国产高清一区| 亚洲精品欧美专区| 99一区二区| 亚洲一区二区三区中文字幕在线 | 99re成人精品视频| 99国产精品久久| 亚洲网站在线| 欧美一区二区三区免费大片| 久久成人这里只有精品| 麻豆精品视频在线| 亚洲高清毛片| 一区二区欧美日韩| 亚洲欧美美女| 久久久久国内| 欧美高清视频一区二区| 欧美性理论片在线观看片免费| 国产精品久久久久毛片软件 | 亚洲在线观看视频| 一区二区三区.www| 香蕉亚洲视频| 欧美成人免费在线视频| 欧美日韩网站| 国产欧美日韩高清| 亚洲福利久久| 一区二区三区欧美在线| 欧美一区二区三区成人| 蜜臀久久99精品久久久画质超高清 | 久久综合给合| 欧美日韩www| 国产精品入口福利| 韩日精品中文字幕| 亚洲精品在线观看免费| 亚洲尤物在线| 欧美gay视频激情| 精品51国产黑色丝袜高跟鞋| 国产精品久久久久久久久久妞妞 | 欧美成人高清| 亚洲乱码国产乱码精品精可以看 | 亚洲精品日韩在线观看| 这里只有精品视频在线| 久久精品动漫| 91久久精品国产91久久性色tv | 亚洲一级在线观看| 久久全国免费视频| 亚洲久久成人| 久久精品视频免费播放| 欧美日韩999| 极品少妇一区二区三区精品视频| 99精品视频免费全部在线| 久久精品视频在线播放| 欧美激情中文字幕在线| 亚洲尤物影院| 欧美喷潮久久久xxxxx| 好男人免费精品视频| 亚洲欧美国产日韩中文字幕| 亚洲大片在线观看| 亚洲久久在线|