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

鍵盤的詠嘆調(diào)

常用鏈接

統(tǒng)計(jì)

最新評(píng)論

[zz]漫談malloc的實(shí)現(xiàn)

         malloc()是C語言中動(dòng)態(tài)存儲(chǔ)管理的一組標(biāo)準(zhǔn)庫函數(shù)之一。其作用是在內(nèi)存的動(dòng)態(tài)存儲(chǔ)區(qū)中分配一個(gè)長(zhǎng)度為size的連續(xù)空間。其參數(shù)是一個(gè)無符號(hào)整形數(shù),返回值是一個(gè)指向所分配的連續(xù)存儲(chǔ)域的起始地址的指針。

   動(dòng)態(tài)內(nèi)存分配就是指在程序執(zhí)行的過程中動(dòng)態(tài)地分配或者回收存儲(chǔ)空間的分配內(nèi)存的方法。動(dòng)態(tài)內(nèi)存分配不像數(shù)組等靜態(tài)內(nèi)存分配方法那樣需要預(yù)先分配存儲(chǔ)空間,而是由系統(tǒng)根據(jù)程序的需要即時(shí)分配,且分配的大小就是程序要求的大小。本文簡(jiǎn)單介紹動(dòng)態(tài)內(nèi)存分配函數(shù)malloc()及幾種實(shí)現(xiàn)方法。

   1. 簡(jiǎn)介

  malloc()是C語言中動(dòng)態(tài)存儲(chǔ)管理的一組標(biāo)準(zhǔn)庫函數(shù)之一。其作用是在內(nèi)存的動(dòng)態(tài)存儲(chǔ)區(qū)中分配一個(gè)長(zhǎng)度為size的連續(xù)空間。其參數(shù)是一個(gè)無符號(hào)整形數(shù),返回值是一個(gè)指向所分配的連續(xù)存儲(chǔ)域的起始地址的指針。還有一點(diǎn)必須注意的是,當(dāng)函數(shù)未能成功分配存儲(chǔ)空間(如內(nèi)存不足)就會(huì)返回一個(gè)NULL指針。所以在調(diào)用該函數(shù)時(shí)應(yīng)該檢測(cè)返回值是否為NULL并執(zhí)行相應(yīng)的操作。

   2. 函數(shù)說明

  C語言的動(dòng)態(tài)存儲(chǔ)管理由一組標(biāo)準(zhǔn)庫函數(shù)實(shí)現(xiàn),其原型在標(biāo)準(zhǔn)文件<stdlib.h>里描述,需要用這些功能時(shí)應(yīng)包含這個(gè)文件。與動(dòng)態(tài)存儲(chǔ)分配有關(guān)的函數(shù)共有四個(gè),其中就包括存儲(chǔ)分配函數(shù)malloc()。函數(shù)原型是:void *malloc (size_t n);這里的size_t是標(biāo)準(zhǔn)庫里定義的一個(gè)類型,它是一個(gè)無符號(hào)整型。這個(gè)整型能夠滿足所有對(duì)存儲(chǔ)塊大小描述的需要,具體相當(dāng)于哪個(gè)整型由具體的C系統(tǒng)確定。malloc的返回值為(void *)類型(這是通用指針的一個(gè)重要用途),它分配一片能存放大小為n的數(shù)據(jù)的存儲(chǔ)塊,返回對(duì)應(yīng)的指針值;如果不能滿足申請(qǐng)(找不到能滿足要求的存儲(chǔ)塊)就返回NULL。在使用時(shí),應(yīng)該把malloc的返回值轉(zhuǎn)換到特定指針類型,賦給一個(gè)指針。

    注意,雖然這里的存儲(chǔ)塊是通過動(dòng)態(tài)分配得到的,但是它的大小也是確定的,同樣不允許越界使用。例如上面程序段分配的塊里能存n個(gè)雙精度數(shù)據(jù),隨后的使用就必須在這個(gè)范圍內(nèi)進(jìn)行。越界使用動(dòng)態(tài)分配的存儲(chǔ)塊,尤其是越界賦值,可能引起非常嚴(yán)重的后果,通常會(huì)破壞程序的運(yùn)行系統(tǒng),可能造成本程序或者整個(gè)計(jì)算機(jī)系統(tǒng)垮臺(tái)。

  下例是一個(gè)動(dòng)態(tài)分配的例子:
#include <stdlib.h>

main()
{
 int count,*array; /*count是一個(gè)計(jì)數(shù)器,array是一個(gè)整型指針,也可以理解為指向一個(gè)整型數(shù)組的首地址*/
 if((array(int *) malloc (10*sizeof(int)))==NULL)
 {
  printf("不能成功分配存儲(chǔ)空間。");
  exit(1);
 }
 for (count=0;count〈10;count++) /*給數(shù)組賦值*/
  array[count]=count;
 for(count=0;count〈10;count++) /*打印數(shù)組元素*/
  printf("%2d",array[count]);
}

  上例中動(dòng)態(tài)分配了10個(gè)整型存儲(chǔ)區(qū)域,然后進(jìn)行賦值并打印。例中if((array(int *) malloc (10*sizeof(int)))==NULL)語句可以分為以下幾步:
  1)分配10個(gè)整型的連續(xù)存儲(chǔ)空間,并返回一個(gè)指向其起始地址的整型指針
  2)把此整型指針地址賦給array
  3)檢測(cè)返回值是否為NULL

   3. malloc()工作機(jī)制

  malloc函數(shù)的實(shí)質(zhì)體現(xiàn)在,它有一個(gè)將可用的內(nèi)存塊連接為一個(gè)長(zhǎng)長(zhǎng)的列表的所謂空閑鏈表。調(diào)用malloc函數(shù)時(shí),它沿連接表尋找一個(gè)大到足以滿足用戶請(qǐng)求所需要的內(nèi)存塊。然后,將該內(nèi)存塊一分為二(一塊的大小與用戶請(qǐng)求的大小相等,另一塊的大小就是剩下的字節(jié))。接下來,將分配給用戶的那塊內(nèi)存?zhèn)鹘o用戶,并將剩下的那塊(如果有的話)返回到連接表上。調(diào)用free函數(shù)時(shí),它將用戶釋放的內(nèi)存塊連接到空閑鏈上。到最后,空閑鏈會(huì)被切成很多的小內(nèi)存片段,如果這時(shí)用戶申請(qǐng)一個(gè)大的內(nèi)存片段,那么空閑鏈上可能沒有可以滿足用戶要求的片段了。于是,malloc函數(shù)請(qǐng)求延時(shí),并開始在空閑鏈上翻箱倒柜地檢查各內(nèi)存片段,對(duì)它們進(jìn)行整理,將相鄰的小空閑塊合并成較大的內(nèi)存塊。

   4. malloc()在操作系統(tǒng)中的實(shí)現(xiàn)

  在 C 程序中,多次使用malloc () 和 free()。不過,您可能沒有用一些時(shí)間去思考它們?cè)谀牟僮飨到y(tǒng)中是如何實(shí)現(xiàn)的。本節(jié)將向您展示 malloc 和 free 的一個(gè)最簡(jiǎn)化實(shí)現(xiàn)的代碼,來幫助說明管理內(nèi)存時(shí)都涉及到了哪些事情。

  在大部分操作系統(tǒng)中,內(nèi)存分配由以下兩個(gè)簡(jiǎn)單的函數(shù)來處理:

  void *malloc (long numbytes):該函數(shù)負(fù)責(zé)分配 numbytes 大小的內(nèi)存,并返回指向第一個(gè)字節(jié)的指針。

  void free(void *firstbyte):如果給定一個(gè)由先前的 malloc 返回的指針,那么該函數(shù)會(huì)將分配的空間歸還給進(jìn)程的“空閑空間”。

  malloc_init 將是初始化內(nèi)存分配程序的函數(shù)。它要完成以下三件事:將分配程序標(biāo)識(shí)為已經(jīng)初始化,找到系統(tǒng)中最后一個(gè)有效內(nèi)存地址,然后建立起指向我們管理的內(nèi)存的指針。這三個(gè)變量都是全局變量:

  清單 1. 我們的簡(jiǎn)單分配程序的全局變量

        int has_initialized = 0;
        void *managed_memory_start;
        void *last_valid_address;

  如前所述,被映射的內(nèi)存的邊界(最后一個(gè)有效地址)常被稱為系統(tǒng)中斷點(diǎn)或者 當(dāng)前中斷點(diǎn)。在很多 UNIX? 系統(tǒng)中,為了指出當(dāng)前系統(tǒng)中斷點(diǎn),必須使用 sbrk(0) 函數(shù)。 sbrk 根據(jù)參數(shù)中給出的字節(jié)數(shù)移動(dòng)當(dāng)前系統(tǒng)中斷點(diǎn),然后返回新的系統(tǒng)中斷點(diǎn)。使用參數(shù) 0 只是返回當(dāng)前中斷點(diǎn)。這里是我們的 malloc 初始化代碼,它將找到當(dāng)前中斷點(diǎn)并初始化我們的變量:

  清單 2. 分配程序初始化函數(shù)
/* Include the sbrk function */
 
#include
void malloc_init()
{
/* grab the last valid address from the OS */
last_valid_address = sbrk(0);
/* we don't have any memory to manage yet, so
 *just set the beginning to be last_valid_address
 */
managed_memory_start = last_valid_address;
/* Okay, we're initialized and ready to go */
 has_initialized = 1;
}

  現(xiàn)在,為了完全地管理內(nèi)存,我們需要能夠追蹤要分配和回收哪些內(nèi)存。在對(duì)內(nèi)存塊進(jìn)行了 free 調(diào)用之后,我們需要做的是諸如將它們標(biāo)記為未被使用的等事情,并且,在調(diào)用 malloc 時(shí),我們要能夠定位未被使用的內(nèi)存塊。因此, malloc 返回的每塊內(nèi)存的起始處首先要有這個(gè)結(jié)構(gòu):

  清單 3. 內(nèi)存控制塊結(jié)構(gòu)定義
struct mem_control_block {
int is_available;
int size;
};
   

   現(xiàn)在,您可能會(huì)認(rèn)為當(dāng)程序調(diào)用 malloc 時(shí)這會(huì)引發(fā)問題 —— 它們?nèi)绾沃肋@個(gè)結(jié)構(gòu)?答案是它們不必知道;在返回指針之前,我們會(huì)將其移動(dòng)到這個(gè)結(jié)構(gòu)之后,把它隱藏起來。這使得返回的指針指向沒有用于任何其他用途的內(nèi)存。那樣,從調(diào)用程序的角度來看,它們所得到的全部是空閑的、開放的內(nèi)存。然后,當(dāng)通過 free() 將該指針傳遞回來時(shí),我們只需要倒退幾個(gè)內(nèi)存字節(jié)就可以再次找到這個(gè)結(jié)構(gòu)。

  在討論分配內(nèi)存之前,我們將先討論釋放,因?yàn)樗?jiǎn)單。為了釋放內(nèi)存,我們必須要做的惟一一件事情就是,獲得我們給出的指針,回退 sizeof(struct mem_control_block) 個(gè)字節(jié),并將其標(biāo)記為可用的。這里是對(duì)應(yīng)的代碼:

  清單 4. 解除分配函數(shù)
void free(void *firstbyte) {
struct mem_control_block *mcb;
/* Backup from the given pointer to find the
 * mem_control_block
 */
mcb = firstbyte - sizeof(struct mem_control_block);
/* Mark the block as being available */
mcb->is_available = 1;
/* That's It!  We're done. */
return;
}

  如您所見,在這個(gè)分配程序中,內(nèi)存的釋放使用了一個(gè)非常簡(jiǎn)單的機(jī)制,在固定時(shí)間內(nèi)完成內(nèi)存釋放。分配內(nèi)存稍微困難一些。以下是該算法的略述:

  清單 5. 主分配程序的偽代碼
1. If our allocator has not been initialized, initialize it.
2. Add sizeof(struct mem_control_block) to the size requested.
3. start at managed_memory_start.
4. Are we at last_valid address?
5. If we are:
   A. We didn't find any existing space that was large enough
      -- ask the operating system for more and return that.
6. Otherwise:
   A. Is the current space available (check is_available from
      the mem_control_block)?
   B. If it is:
      i)   Is it large enough (check "size" from the
           mem_control_block)?
      ii)  If so:
           a. Mark it as unavailable
           b. Move past mem_control_block and return the
              pointer
      iii) Otherwise:
           a. Move forward "size" bytes
           b. Go back go step 4
   C. Otherwise:
      i)   Move forward "size" bytes
      ii)  Go back to step 4

  我們主要使用連接的指針遍歷內(nèi)存來尋找開放的內(nèi)存塊。這里是代碼:

  清單 6. 主分配程序
void *malloc(long numbytes) {
/* Holds where we are looking in memory */
void *current_location;
/* This is the same as current_location, but cast to a
 * memory_control_block
 */
struct mem_control_block *current_location_mcb;
/* This is the memory location we will return.  It will
 * be set to 0 until we find something suitable
 */
void *memory_location;
/* Initialize if we haven't already done so */
if(! has_initialized) {
malloc_init();
}
/* The memory we search for has to include the memory
 * control block, but the users of malloc don't need
 * to know this, so we'll just add it in for them.
 */
numbytes = numbytes + sizeof(struct mem_control_block);
/* Set memory_location to 0 until we find a suitable
 * location
 */
memory_location = 0;
/* Begin searching at the start of managed memory */
current_location = managed_memory_start;
/* Keep going until we have searched all allocated space */
while(current_location != last_valid_address)
{
/* current_location and current_location_mcb point
 * to the same address.  However, current_location_mcb
 * is of the correct type, so we can use it as a struct.
 * current_location is a void pointer so we can use it
 * to calculate addresses.
 */
current_location_mcb =
(struct mem_control_block *)current_location;
if(current_location_mcb->is_available)
{
if(current_location_mcb->size >= numbytes)
{
/* Woohoo!  We've found an open,
 * appropriately-size location.
 */
/* It is no longer available */
current_location_mcb->is_available = 0;
/* We own it */
memory_location = current_location;
/* Leave the loop */
break;
}
}
/* If we made it here, it's because the Current memory
 * block not suitable; move to the next one
 */
current_location = current_location +
current_location_mcb->size;
}
/* If we still don't have a valid location, we'll
 * have to ask the operating system for more memory
 */
if(! memory_location)
{
/* Move the program break numbytes further */
sbrk(numbytes);
/* The new memory will be where the last valid
 * address left off
 */
memory_location = last_valid_address;
/* We'll move the last valid address forward
 * numbytes
 */
last_valid_address = last_valid_address + numbytes;
/* We need to initialize the mem_control_block */
current_location_mcb = memory_location;
current_location_mcb->is_available = 0;
current_location_mcb->size = numbytes;
}
/* Now, no matter what (well, except for error conditions),
 * memory_location has the address of the memory, including
 * the mem_control_block
 */
/* Move the pointer past the mem_control_block */
memory_location = memory_location + sizeof(struct mem_control_block);
/* Return the pointer */
return memory_location;
 }

  這就是我們的內(nèi)存管理器。現(xiàn)在,我們只需要構(gòu)建它,并在程序中使用它即可。
 

  5. malloc()的其他實(shí)現(xiàn)

  malloc() 的實(shí)現(xiàn)有很多,這些實(shí)現(xiàn)各有優(yōu)點(diǎn)與缺點(diǎn)。在設(shè)計(jì)一個(gè)分配程序時(shí),要面臨許多需要折衷的選擇,其中包括:

分配的速度。
回收的速度。
有線程的環(huán)境的行為。
內(nèi)存將要被用光時(shí)的行為。
局部緩存。
簿記(Bookkeeping)內(nèi)存開銷。
虛擬內(nèi)存環(huán)境中的行為。
小的或者大的對(duì)象。
實(shí)時(shí)保證。
每一個(gè)實(shí)現(xiàn)都有其自身的優(yōu)缺點(diǎn)集合。在我們的簡(jiǎn)單的分配程序中,分配非常慢,而回收非常快。另外,由于它在使用虛擬內(nèi)存系統(tǒng)方面較差,所以它最適于處理大的對(duì)象。

  還有其他許多分配程序可以使用。其中包括:

  Doug Lea Malloc:Doug Lea Malloc 實(shí)際上是完整的一組分配程序,其中包括 Doug Lea 的原始分配程序,GNU libc 分配程序和 ptmalloc。 Doug Lea 的分配程序有著與我們的版本非常類似的基本結(jié)構(gòu),但是它加入了索引,這使得搜索速度更快,并且可以將多個(gè)沒有被使用的塊組合為一個(gè)大的塊。它還支持緩存,以便更快地再次使用最近釋放的內(nèi)存。 ptmalloc 是 Doug Lea Malloc 的一個(gè)擴(kuò)展版本,支持多線程。在本文后面的 參考資料部分中,有一篇描述 Doug Lea 的 Malloc 實(shí)現(xiàn)的文章。

  BSD Malloc:BSD Malloc 是隨 4.2 BSD 發(fā)行的實(shí)現(xiàn),包含在 FreeBSD 之中,這個(gè)分配程序可以從預(yù)先確實(shí)大小的對(duì)象構(gòu)成的池中分配對(duì)象。它有一些用于對(duì)象大小的 size 類,這些對(duì)象的大小為 2 的若干次冪減去某一常數(shù)。所以,如果您請(qǐng)求給定大小的一個(gè)對(duì)象,它就簡(jiǎn)單地分配一個(gè)與之匹配的 size 類。這樣就提供了一個(gè)快速的實(shí)現(xiàn),但是可能會(huì)浪費(fèi)內(nèi)存。在 參考資料部分中,有一篇描述該實(shí)現(xiàn)的文章。

  Hoard:編寫 Hoard 的目標(biāo)是使內(nèi)存分配在多線程環(huán)境中進(jìn)行得非常快。因此,它的構(gòu)造以鎖的使用為中心,從而使所有進(jìn)程不必等待分配內(nèi)存。它可以顯著地加快那些進(jìn)行很多分配和回收的多線程進(jìn)程的速度。在 參考資料部分中,有一篇描述該實(shí)現(xiàn)的文章。
眾多可用的分配程序中最有名的就是上述這些分配程序。如果您的程序有特別的分配需求,那么您可能更愿意編寫一個(gè)定制的能匹配您的程序內(nèi)存分配方式的分配程序。不過,如果不熟悉分配程序的設(shè)計(jì),那么定制分配程序通常會(huì)帶來比它們解決的問題更多的問題。

   6. 結(jié)束語

  前面已經(jīng)提過,多次調(diào)用malloc()后空閑內(nèi)存被切成很多的小內(nèi)存片段,這就使得用戶在申請(qǐng)內(nèi)存使用時(shí),由于找不到足夠大的內(nèi)存空間,malloc()需要進(jìn)行內(nèi)存整理,使得函數(shù)的性能越來越低。聰明的程序員通過總是分配大小為2的冪的內(nèi)存塊,而最大限度地降低潛在的malloc性能喪失。也就是說,所分配的內(nèi)存塊大小為4字節(jié)、8字節(jié)、16字節(jié)、18446744073709551616字節(jié),等等。這樣做最大限度地減少了進(jìn)入空閑鏈的怪異片段(各種尺寸的小片段都有)的數(shù)量。盡管看起來這好像浪費(fèi)了空間,但也容易看出浪費(fèi)的空間永遠(yuǎn)不會(huì)超過50%。

   參考文獻(xiàn):

  [1]  Jonathan Bartlett,內(nèi)存管理內(nèi)幕. developerWorks 中國,2004年11月

posted on 2009-01-25 13:13 鍵盤的詠嘆調(diào) 閱讀(672) 評(píng)論(0)  編輯 收藏 引用 所屬分類: C++

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美大片国产精品| 欧美一区在线视频| 亚洲黄页一区| 国产精品爽黄69| 欧美国产精品| 欧美日韩中文字幕精品| 欧美国产日韩精品免费观看| 久久婷婷蜜乳一本欲蜜臀| 欧美一站二站| 午夜精品久久久久久久99热浪潮| 一区二区三区国产精华| 一区二区三区不卡视频在线观看| 亚洲伦理一区| 亚洲激情六月丁香| 激情成人亚洲| 亚洲精品免费一区二区三区| 永久555www成人免费| 欧美色综合网| 国产欧美欧美| 好看的日韩av电影| 亚洲激情国产精品| 亚洲婷婷综合久久一本伊一区| 一本在线高清不卡dvd | 欧美在线视频一区二区| 一区二区三区精品国产| 妖精成人www高清在线观看| 亚洲国产精品视频| 亚洲无线视频| 性亚洲最疯狂xxxx高清| 久久久久久久久伊人| 久久精品国产91精品亚洲| 久久久久免费观看| 国产综合色产在线精品| 午夜精品在线| 久久精品国产亚洲a| 日韩亚洲欧美一区二区三区| 亚洲欧美欧美一区二区三区| 老司机免费视频久久| 国产精品久久久久久超碰 | 亚洲视频一区二区| 久久久一二三| 亚洲午夜免费视频| 老牛嫩草一区二区三区日本| 国产精品入口尤物| 亚洲美女在线观看| 久久久久**毛片大全| 在线视频精品一| 久久最新视频| 国产日韩一区二区三区在线播放| 亚洲国产毛片完整版| 欧美一级二区| 亚洲人午夜精品免费| 亚洲影院在线观看| 欧美日韩在线精品一区二区三区| 伊人成综合网伊人222| 正在播放亚洲| 亚洲人成高清| 蜜桃久久精品一区二区| 国产一区二区久久| 亚洲小说区图片区| 日韩视频免费| 欧美高潮视频| 亚洲精品国产精品国自产观看 | 国产欧美一区二区白浆黑人| 亚洲亚洲精品三区日韩精品在线视频 | 亚洲免费在线精品一区| 欧美视频在线免费| 日韩午夜av在线| 亚洲国产日韩在线| 久热综合在线亚洲精品| 韩国自拍一区| 欧美激情精品久久久久久黑人| 久久久国产精品一区| 伊人婷婷久久| 欧美电影在线播放| 久久夜色精品国产欧美乱极品| 国产一区二区三区在线免费观看| 久久精品99国产精品酒店日本| 亚洲欧美美女| 国产欧美在线播放| 欧美有码视频| 在线免费观看日本欧美| 国产精品美女久久久久久2018| 亚洲一区视频在线| 亚洲一区二区三区免费在线观看 | 国产综合18久久久久久| 久久精品一本| 久久免费99精品久久久久久| 亚洲国产第一| 亚洲伦理在线观看| 国产精品sss| 欧美在线观看视频| 可以看av的网站久久看| 亚洲图片欧洲图片日韩av| 亚洲欧美国产日韩中文字幕| 伊人伊人伊人久久| 亚洲精品在线三区| 国产精品一区二区黑丝| 欧美在线视频播放| 欧美黄网免费在线观看| 午夜免费久久久久| 久久久久久一区二区三区| 最新成人在线| 亚洲图中文字幕| 在线不卡亚洲| 中日韩在线视频| 在线看成人片| 亚洲一级黄色av| 在线看日韩欧美| 亚洲视频中文| 91久久精品美女| 久久成人在线| 亚洲欧美激情视频在线观看一区二区三区| 欧美一区二区免费观在线| 亚洲美女在线看| 久久黄色影院| 亚洲欧美日韩电影| 欧美成人亚洲成人| 久久精品亚洲国产奇米99| 欧美日韩精品免费在线观看视频| 久久久久一区二区三区| 欧美日一区二区三区在线观看国产免| 狼人社综合社区| 国产精品一区毛片| 亚洲片国产一区一级在线观看| 国产偷久久久精品专区| 99国产精品视频免费观看一公开| 有坂深雪在线一区| 久久久久9999亚洲精品| 亚洲性图久久| 欧美日韩精品久久久| 欧美大尺度在线观看| 国内精品久久久久影院色 | 男人插女人欧美| 久久久综合香蕉尹人综合网| 国产精品久久久久久久9999| 亚洲日本成人| 日韩一级网站| 欧美精品久久久久久久免费观看| 女人色偷偷aa久久天堂| 国内一区二区在线视频观看 | 99re热精品| 亚洲日本理论电影| 久久婷婷人人澡人人喊人人爽| 久久激情婷婷| 国产日韩精品视频一区| 亚洲午夜久久久久久久久电影网| 亚洲午夜羞羞片| 国产精品久久久久久久久久妞妞| 99视频热这里只有精品免费| 一道本一区二区| 国产精品高清免费在线观看| 日韩视频一区二区| 午夜免费久久久久| 国产又爽又黄的激情精品视频 | 国语精品中文字幕| 久久久久国产精品一区二区| 欧美成人免费在线视频| 日韩亚洲国产欧美| 欧美日韩18| 亚洲一区二区av电影| 久久久亚洲成人| 亚洲精品视频一区| 国产精品扒开腿做爽爽爽视频| 午夜精品久久久久久99热| 米奇777在线欧美播放| 亚洲天堂av图片| 国产一区白浆| 欧美国产日本韩| 亚洲一区二区三区中文字幕在线| 久久久久国产一区二区三区| 亚洲国产欧美日韩另类综合| 欧美日韩一区二区在线| 欧美伊人久久| 日韩亚洲一区在线播放| 久久伊人一区二区| 亚洲小视频在线| 在线观看亚洲精品视频| 欧美三区视频| 久久综合色播五月| 亚洲手机成人高清视频| 久热精品视频在线观看| 中日韩视频在线观看| 在线看不卡av| 国产日韩欧美三级| 欧美日韩日本国产亚洲在线| 久久精品亚洲一区二区三区浴池| a4yy欧美一区二区三区| 美女在线一区二区| 亚洲一区在线免费| 亚洲日本激情| 国内精品久久久久久| 欧美日韩a区| 久久久久久夜| 午夜伦欧美伦电影理论片| 亚洲人成网站777色婷婷| 噜噜噜91成人网| 欧美亚洲系列| 一区二区三区 在线观看视频| 激情婷婷亚洲|