精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Linux內核里的數據結構——位數組

系統 Linux 系統運維
除了不同的基于鏈式和樹的數據結構以外,Linux 內核也為位數組(或稱為位圖)提供了 API。位數組在 Linux 內核里被廣泛使用,并且在以下的源代碼文件中包含了與這樣的結構搭配使用的通用API。

[[170504]]

Linux 內核中的位數組和位操作

除了不同的基于鏈式和樹的數據結構以外,Linux 內核也為位數組(或稱為位圖(bitmap))提供了 API。位數組在 Linux 內核里被廣泛使用,并且在以下的源代碼文件中包含了與這樣的結構搭配使用的通用 API:

除了這兩個文件之外,還有體系結構特定的頭文件,它們為特定的體系結構提供優化的位操作。我們將探討 x86_64 體系結構,因此在我們的例子里,它會是

頭文件。正如我上面所寫的,位圖在 Linux 內核中被廣泛地使用。例如,位數組常常用于保存一組在線/離線處理器,以便系統支持熱插拔的 CPU(你可以在 cpumasks 部分閱讀更多相關知識 ),一個位數組(bit array)可以在 Linux 內核初始化等期間保存一組已分配的中斷處理。

因此,本部分的主要目的是了解位數組(bit array)是如何在 Linux 內核中實現的。讓我們現在開始吧。

位數組聲明

在我們開始查看位圖操作的 API 之前,我們必須知道如何在 Linux 內核中聲明它。有兩種聲明位數組的通用方法。***種簡單的聲明一個位數組的方法是,定義一個 unsigned long 的數組,例如:

  1. unsigned long my_bitmap[8] 

第二種方法,是使用 DECLARE_BITMAP 宏,它定義于 include/linux/types.h 頭文件:

  1. #define DECLARE_BITMAP(name,bits) \ 
  2.     unsigned long name[BITS_TO_LONGS(bits)] 

我們可以看到 DECLARE_BITMAP 宏使用兩個參數:

  • name - 位圖名稱;
  • bits - 位圖中位數;

并且只是使用 BITS_TO_LONGS(bits) 元素展開 unsigned long 數組的定義。 BITS_TO_LONGS 宏將一個給定的位數轉換為 long 的個數,換言之,就是計算 bits 中有多少個 8 字節元素:

  1. #define BITS_PER_BYTE           8 
  2. #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) 
  3. #define BITS_TO_LONGS(nr)       DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) 

因此,例如 DECLARE_BITMAP(my_bitmap, 64) 將產生:

  1. >>> (((64) + (64) - 1) / (64)) 

與:

  1. unsigned long my_bitmap[1]; 

在能夠聲明一個位數組之后,我們便可以使用它了。

體系結構特定的位操作

我們已經看了上面提及的一對源文件和頭文件,它們提供了位數組操作的 API。其中重要且廣泛使用的位數組 API 是體系結構特定的且位于已提及的頭文件中 arch/x86/include/asm/bitops.h。

首先讓我們查看兩個最重要的函數:

  • set_bit;
  • clear_bit.

我認為沒有必要解釋這些函數的作用。從它們的名字來看,這已經很清楚了。讓我們直接查看它們的實現。如果你瀏覽 arch/x86/include/asm/bitops.h 頭文件,你將會注意到這些函數中的每一個都有原子性和非原子性兩種變體。在我們開始深入這些函數的實現之前,首先,我們必須了解一些有關原子(atomic)操作的知識。

簡而言之,原子操作保證兩個或以上的操作不會并發地執行同一數據。x86 體系結構提供了一系列原子指令,例如, xchg、cmpxchg 等指令。除了原子指令,一些非原子指令可以在 lock 指令的幫助下具有原子性。現在你已經對原子操作有了足夠的了解,我們可以接著探討 set_bit 和 clear_bit 函數的實現。

我們先考慮函數的非原子性(non-atomic)變體。非原子性的 set_bit 和 clear_bit 的名字以雙下劃線開始。正如我們所知道的,所有這些函數都定義于 arch/x86/include/asm/bitops.h 頭文件,并且***個函數就是 __set_bit:

  1. static inline void __set_bit(long nr, volatile unsigned long *addr) 
  2.     asm volatile("bts %1,%0" : ADDR : "Ir" (nr) : "memory"); 

正如我們所看到的,它使用了兩個參數:

  • nr - 位數組中的位號(LCTT 譯注:從 0 開始)
  • addr - 我們需要置位的位數組地址

注意,addr 參數使用 volatile 關鍵字定義,以告訴編譯器給定地址指向的變量可能會被修改。 __set_bit 的實現相當簡單。正如我們所看到的,它僅包含一行內聯匯編代碼。在我們的例子中,我們使用 bts 指令,從位數組中選出一個***操作數(我們的例子中的 nr)所指定的位,存儲選出的位的值到 CF 標志寄存器并設置該位(LCTT 譯注:即 nr 指定的位置為 1)。

注意,我們了解了 nr 的用法,但這里還有一個參數 addr 呢!你或許已經猜到秘密就在 ADDR。 ADDR 是一個定義在同一個頭文件中的宏,它展開為一個包含給定地址和 +m 約束的字符串:

  1. #define ADDR                BITOP_ADDR(addr) 
  2. #define BITOP_ADDR(x) "+m" (*(volatile long *) (x)) 

除了 +m 之外,在 __set_bit 函數中我們可以看到其他約束。讓我們查看并試著理解它們所表示的意義:

  • +m - 表示內存操作數,這里的 + 表明給定的操作數為輸入輸出操作數;
  • I - 表示整型常量;
  • r - 表示寄存器操作數

除了這些約束之外,我們也能看到 memory 關鍵字,其告訴編譯器這段代碼會修改內存中的變量。到此為止,現在我們看看相同的原子性(atomic)變體函數。它看起來比非原子性(non-atomic)變體更加復雜:

 

  1. static __always_inline void 
  2. set_bit(long nr, volatile unsigned long *addr) 
  3.     if (IS_IMMEDIATE(nr)) { 
  4.         asm volatile(LOCK_PREFIX "orb %1,%0" 
  5.             : CONST_MASK_ADDR(nr, addr) 
  6.             : "iq" ((u8)CONST_MASK(nr)) 
  7.             : "memory"); 
  8.     } else { 
  9.         asm volatile(LOCK_PREFIX "bts %1,%0" 
  10.             : BITOP_ADDR(addr) : "Ir" (nr) : "memory"); 
  11.     } 

(LCTT 譯注:BITOP_ADDR 的定義為:#define BITOP_ADDR(x) "=m" (*(volatile long *) (x)),ORB 為字節按位或。)

首先注意,這個函數使用了與 __set_bit 相同的參數集合,但額外地使用了 __always_inline 屬性標記。 __always_inline 是一個定義于 include/linux/compiler-gcc.h 的宏,并且只是展開為 always_inline 屬性:

  1. #define __always_inline inline __attribute__((always_inline)) 

其意味著這個函數總是內聯的,以減少 Linux 內核映像的大小?,F在讓我們試著了解下 set_bit 函數的實現。首先我們在 set_bit 函數的開頭檢查給定的位的數量。IS_IMMEDIATE 宏定義于相同的頭文件,并展開為 gcc 內置函數的調用:

  1. #define IS_IMMEDIATE(nr) (__builtin_constant_p(nr)) 

如果給定的參數是編譯期已知的常量,__builtin_constant_p 內置函數則返回 1,其他情況返回 0。假若給定的位數是編譯期已知的常量,我們便無須使用效率低下的 bts 指令去設置位。我們可以只需在給定地址指向的字節上執行 按位或 操作,其字節包含給定的位,掩碼位數表示高位為 1,其他位為 0 的掩碼。在其他情況下,如果給定的位號不是編譯期已知常量,我們便做和 __set_bit 函數一樣的事。CONST_MASK_ADDR 宏:

  1. #define CONST_MASK_ADDR(nr, addr)   BITOP_ADDR((void *)(addr) + ((nr)>>3)) 

展開為帶有到包含給定位的字節偏移的給定地址,例如,我們擁有地址 0x1000 和位號 0x9。因為 0x9 代表 一個字節 + 一位,所以我們的地址是 addr + 1:

  1. >>> hex(0x1000 + (0x9 >> 3)) 
  2. '0x1001' 

CONST_MASK 宏將我們給定的位號表示為字節,位號對應位為高位 1,其他位為 0:

  1. #define CONST_MASK(nr)          (1 << ((nr) & 7)) 
  1. >>> bin(1 << (0x9 & 7)) 
  2. '0b10' 

***,我們應用 按位或 運算到這些變量上面,因此,假如我們的地址是 0x4097 ,并且我們需要置位號為 9 的位為 1:

  1. >>> bin(0x4097) 
  2. '0b100000010010111' 
  3. >>> bin((0x4097 >> 0x9) | (1 << (0x9 & 7))) 
  4. '0b100010' 

第 9 位 將會被置位。(LCTT 譯注:這里的 9 是從 0 開始計數的,比如0010,按照作者的意思,其中的 1 是第 1 位)

注意,所有這些操作使用 LOCK_PREFIX 標記,其展開為 lock 指令,保證該操作的原子性。

正如我們所知,除了 set_bit 和 __set_bit 操作之外,Linux 內核還提供了兩個功能相反的函數,在原子性和非原子性的上下文中清位。它們是 clear_bit 和 __clear_bit。這兩個函數都定義于同一個頭文件 并且使用相同的參數集合。不僅參數相似,一般而言,這些函數與 set_bit 和 __set_bit 也非常相似。讓我們查看非原子性 __clear_bit 的實現吧:

  1. static inline void __clear_bit(long nr, volatile unsigned long *addr) 
  2.     asm volatile("btr %1,%0" : ADDR : "Ir" (nr)); 

沒錯,正如我們所見,__clear_bit 使用相同的參數集合,并包含極其相似的內聯匯編代碼塊。它只是使用 btr 指令替換了 bts。正如我們從函數名所理解的一樣,通過給定地址,它清除了給定的位。btr 指令表現得像 bts(LCTT 譯注:原文這里為 btr,可能為筆誤,修正為 bts)。該指令選出***操作數所指定的位,存儲它的值到 CF 標志寄存器,并且清除第二操作數指定的位數組中的對應位。

__clear_bit 的原子性變體為 clear_bit:

  1. static __always_inline void 
  2. clear_bit(long nr, volatile unsigned long *addr) 
  3.     if (IS_IMMEDIATE(nr)) { 
  4.         asm volatile(LOCK_PREFIX "andb %1,%0" 
  5.             : CONST_MASK_ADDR(nr, addr) 
  6.             : "iq" ((u8)~CONST_MASK(nr))); 
  7.     } else { 
  8.         asm volatile(LOCK_PREFIX "btr %1,%0" 
  9.             : BITOP_ADDR(addr) 
  10.             : "Ir" (nr)); 
  11.     } 

并且正如我們所看到的,它與 set_bit 非常相似,只有兩處不同。***處差異為 clear_bit 使用 btr 指令來清位,而 set_bit 使用 bts 指令來置位。第二處差異為 clear_bit 使用否定的位掩碼和 按位與 在給定的字節上置位,而 set_bit 使用 按位或 指令。

到此為止,我們可以在任意位數組置位和清位了,我們將看看位掩碼上的其他操作。

在 Linux 內核中對位數組最廣泛使用的操作是設置和清除位,但是除了這兩個操作外,位數組上其他操作也是非常有用的。Linux 內核里另一種廣泛使用的操作是知曉位數組中一個給定的位是否被置位。我們能夠通過 test_bit 宏的幫助實現這一功能。這個宏定義于 arch/x86/include/asm/bitops.h 頭文件,并根據位號分別展開為 constant_test_bit 或 variable_test_bit 調用。

  1. #define test_bit(nr, addr)          \ 
  2.     (__builtin_constant_p((nr))                 \ 
  3.      ? constant_test_bit((nr), (addr))          \ 
  4.      : variable_test_bit((nr), (addr))) 

因此,如果 nr 是編譯期已知常量,test_bit 將展開為 constant_test_bit 函數的調用,而其他情況則為 variable_test_bit。現在讓我們看看這些函數的實現,讓我們從 variable_test_bit 開始看起:

  1. static inline int variable_test_bit(long nr, volatile const unsigned long *addr) 
  2.     int oldbit; 
  3.     asm volatile("bt %2,%1\n\t" 
  4.              "sbb %0,%0" 
  5.              : "=r" (oldbit) 
  6.              : "m" (*(unsigned long *)addr), "Ir" (nr)); 
  7.     return oldbit; 

variable_test_bit 函數使用了與 set_bit 及其他函數使用的相似的參數集合。我們也可以看到執行 bt 和 sbb 指令的內聯匯編代碼。bt (或稱 bit test)指令從第二操作數指定的位數組選出***操作數指定的一個指定位,并且將該位的值存進標志寄存器的 CF 位。第二個指令 sbb 從第二操作數中減去***操作數,再減去 CF 的值。因此,這里將一個從給定位數組中的給定位號的值寫進標志寄存器的 CF 位,并且執行 sbb 指令計算: 00000000 - CF,并將結果寫進 oldbit 變量。

constant_test_bit 函數做了和我們在 set_bit 所看到的一樣的事:

  1. static __always_inline int constant_test_bit(long nr, const volatile unsigned long *addr) 
  2.     return ((1UL << (nr & (BITS_PER_LONG-1))) & 
  3.         (addr[nr >> _BITOPS_LONG_SHIFT])) != 0; 

它生成了一個位號對應位為高位 1,而其他位為 0 的字節(正如我們在 CONST_MASK 所看到的),并將 按位與 應用于包含給定位號的字節。

下一個被廣泛使用的位數組相關操作是改變一個位數組中的位。為此,Linux 內核提供了兩個輔助函數:

  • __change_bit;
  • change_bit.

你可能已經猜測到,就拿 set_bit 和 __set_bit 例子說,這兩個變體分別是原子和非原子版本。首先,讓我們看看 __change_bit 函數的實現:

  1. static inline void __change_bit(long nr, volatile unsigned long *addr) 
  2.     asm volatile("btc %1,%0" : ADDR : "Ir" (nr)); 

相當簡單,不是嗎? __change_bit 的實現和 __set_bit 一樣,只是我們使用 btc 替換 bts 指令而已。 該指令從一個給定位數組中選出一個給定位,將該為位的值存進 CF 并使用求反操作改變它的值,因此值為 1 的位將變為 0,反之亦然:

  1. >>> int(not 1) 
  2. >>> int(not 0) 

__change_bit 的原子版本為 change_bit 函數:

  1. static inline void change_bit(long nr, volatile unsigned long *addr) 
  2.     if (IS_IMMEDIATE(nr)) { 
  3.         asm volatile(LOCK_PREFIX "xorb %1,%0" 
  4.             : CONST_MASK_ADDR(nr, addr) 
  5.             : "iq" ((u8)CONST_MASK(nr))); 
  6.     } else { 
  7.         asm volatile(LOCK_PREFIX "btc %1,%0" 
  8.             : BITOP_ADDR(addr) 
  9.             : "Ir" (nr)); 
  10.     } 

它和 set_bit 函數很相似,但也存在兩點不同。***處差異為 xor 操作而不是 or。第二處差異為 btc( LCTT 譯注:原文為 bts,為作者筆誤) 而不是 bts。

目前,我們了解了最重要的體系特定的位數組操作,是時候看看一般的位圖 API 了。

通用位操作

除了 arch/x86/include/asm/bitops.h 中體系特定的 API 外,Linux 內核提供了操作位數組的通用 API。正如我們本部分開頭所了解的一樣,我們可以在 include/linux/bitmap.h 頭文件和 lib/bitmap.c 源文件中找到它。但在查看這些源文件之前,我們先看看 include/linux/bitops.h 頭文件,其提供了一系列有用的宏,讓我們看看它們當中一部分。

首先我們看看以下 4 個 宏:

  • for_each_set_bit
  • for_each_set_bit_from
  • for_each_clear_bit
  • for_each_clear_bit_from

所有這些宏都提供了遍歷位數組中某些位集合的迭代器。***個宏迭代那些被置位的位。第二個宏也是一樣,但它是從某一個確定的位開始。***兩個宏做的一樣,但是迭代那些被清位的位。讓我們看看 for_each_set_bit 宏:

  1. #define for_each_set_bit(bit, addr, size) \ 
  2.     for ((bit) = find_first_bit((addr), (size));        \ 
  3.          (bit) < (size);                    \ 
  4.          (bit) = find_next_bit((addr), (size), (bit) + 1)) 

正如我們所看到的,它使用了三個參數,并展開為一個循環,該循環從作為 find_first_bit 函數返回結果的***個置位開始,到小于給定大小的***一個置位為止。

除了這四個宏, arch/x86/include/asm/bitops.h 也提供了 64-bit 或 32-bit 變量循環的 API 等等。

下一個 頭文件 提供了操作位數組的 API。例如,它提供了以下兩個函數:

  • bitmap_zero;
  • bitmap_fill.

它們分別可以清除一個位數組和用 1 填充位數組。讓我們看看 bitmap_zero 函數的實現:

  1. static inline void bitmap_zero(unsigned long *dst, unsigned int nbits) 
  2.     if (small_const_nbits(nbits)) 
  3.         *dst = 0UL; 
  4.     else { 
  5.         unsigned int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long); 
  6.         memset(dst, 0, len); 
  7.     } 

首先我們可以看到對 nbits 的檢查。 small_const_nbits 是一個定義在同一個頭文件 的宏:

  1. #define small_const_nbits(nbits) \ 
  2.     (__builtin_constant_p(nbits) && (nbits) <= BITS_PER_LONG) 

正如我們可以看到的,它檢查 nbits 是否為編譯期已知常量,并且其值不超過 BITS_PER_LONG 或 64。如果位數目沒有超過一個 long 變量的位數,我們可以僅僅設置為 0。在其他情況,我們需要計算有多少個需要填充位數組的 long 變量并且使用 memset 進行填充。

bitmap_fill 函數的實現和 biramp_zero 函數很相似,除了我們需要在給定的位數組中填寫 0xff 或 0b11111111:

  1. static inline void bitmap_fill(unsigned long *dst, unsigned int nbits) 
  2.     unsigned int nlongs = BITS_TO_LONGS(nbits); 
  3.     if (!small_const_nbits(nbits)) { 
  4.         unsigned int len = (nlongs - 1) * sizeof(unsigned long); 
  5.         memset(dst, 0xff,  len); 
  6.     } 
  7.     dst[nlongs - 1] = BITMAP_LAST_WORD_MASK(nbits); 

除了 bitmap_fill 和 bitmap_zero,include/linux/bitmap.h 頭文件也提供了和 bitmap_zero 很相似的 bitmap_copy,只是僅僅使用 memcpy 而不是 memset 這點差異而已。它也提供了位數組的按位操作,像 bitmap_and, bitmap_or, bitamp_xor等等。我們不會探討這些函數的實現了,因為如果你理解了本部分的所有內容,這些函數的實現是很容易理解的。無論如何,如果你對這些函數是如何實現的感興趣,你可以打開并研究 include/linux/bitmap.h 頭文件。

本部分到此為止。

責任編輯:龐桂玉 來源: Linux中國
相關推薦

2023-03-28 07:44:23

數據結構數組

2017-04-12 14:30:45

Linux內核DebugFS

2020-09-28 08:11:14

JavaScript數據

2024-07-11 11:35:08

數組結構內部機制

2021-06-08 06:01:00

C++數據結構向量和數組

2015-07-27 11:34:03

Linux內核指針

2024-01-15 06:01:36

C++數組

2010-03-16 16:47:25

Python數組

2009-09-28 10:09:09

Linux內核Linux循環鏈表

2023-10-31 08:51:25

數據結構存儲數據

2021-03-08 06:28:57

JAVA數據結構與算法稀疏數組

2010-07-16 10:38:24

Perl關聯數組

2011-03-31 15:41:51

Cacti數據表結構

2014-12-10 10:35:43

微信 數據結構

2023-07-03 17:24:33

數據結構

2012-04-28 14:21:47

Java數據結構線性結構

2021-07-14 23:55:18

數據結構數組

2009-12-09 14:03:18

2022-01-18 19:13:52

背包問題數據結構算法

2021-04-25 14:29:02

數據結構動態數組時間復雜度
點贊
收藏

51CTO技術棧公眾號

国产一区亚洲一区| 久久精品亚洲成在人线av网址| 国产91精品久久久久久久网曝门| 国产香蕉一区二区三区在线视频| 国内性生活视频| 成年人在线视频| 国产成人在线视频免费播放| 69久久夜色精品国产69| 久久精品国产亚洲AV成人婷婷| 性欧美freehd18| 亚洲女人小视频在线观看| 精品免费国产| av免费观看在线| 老鸭窝毛片一区二区三区| 色吧影院999| 中文字幕在线播放视频| 激情国产在线| 91麻豆精东视频| 青青草精品毛片| 色婷婷在线视频观看| 亚洲视频一起| 欧美酷刑日本凌虐凌虐| 亚洲 高清 成人 动漫| 在线āv视频| 中文字幕欧美日韩一区| 国产精品视频区1| 日本熟妇毛茸茸丰满| 亚洲不卡av不卡一区二区| 亚洲毛茸茸少妇高潮呻吟| 一卡二卡三卡四卡五卡| 超碰资源在线| 久久久久久久精| 国产区精品视频| 精品国产一区二区三区四| 国产精品v欧美精品v日本精品动漫| 精品成人一区二区三区四区| 国产成人无码aa精品一区| fc2ppv国产精品久久| 国产资源精品在线观看| 全亚洲最色的网站在线观看| 亚洲ⅴ国产v天堂a无码二区| 秋霞影院一区二区三区| 欧美r级在线观看| 国产不卡的av| 亚洲午夜剧场| 欧美日韩激情一区二区| 欧美 日韩 国产 激情| 亚洲性色av| 欧美性猛交xxxx免费看漫画| 伊人久久大香线蕉精品| 亚洲av无码乱码国产精品| 精品一区二区综合| 91精品国产综合久久香蕉最新版| 久草中文在线视频| 女同性一区二区三区人了人一| 日韩电影免费在线观看中文字幕| 黄大色黄女片18第一次| 欧美韩日亚洲| 国产亚洲欧美日韩俺去了| 91久久精品www人人做人人爽 | 日本欧美三级| 日韩成人av一区| 亚洲国产无码精品| 欧美日韩国产高清电影| 中文字幕日韩精品在线观看| 中文字幕美女视频| 外国成人在线视频| 亚洲乱亚洲乱妇无码| 在哪里可以看毛片| 丁香5月婷婷久久| 亚洲国产精品999| 91看片破解版| 国产成年精品| 精品人伦一区二区色婷婷| 精品伦一区二区三区| 精品三级av| 日韩一区二区电影| 东京热av一区| 免费一区二区三区视频导航| 精品国产一区二区三区忘忧草| 日本中文字幕影院| 日本一区影院| 亚洲欧美另类人妖| 国产jizz18女人高潮| 欧美a级片一区| 欧美性在线视频| 亚洲一区二区人妻| 蜜桃在线一区二区三区| 91九色露脸| 国产黄色免费大片| 久久中文字幕电影| 正在播放亚洲| 九色porny丨入口在线| 欧美日韩亚洲综合在线| 熟妇人妻无乱码中文字幕真矢织江| 中文字幕在线中文字幕在线中三区| 亚洲国产aⅴ成人精品无吗| 成人污网站在线观看| 午夜久久中文| 欧美性xxxx极品高清hd直播| 日韩av片专区| 亚洲精品无吗| 欧美www在线| 波多野结衣视频网址| 成人免费毛片aaaaa**| 亚洲精品tv久久久久久久久| 97在线视频免费观看完整版| 欧美日韩国产一区二区三区地区| 岛国毛片在线播放| 日韩美女精品| 欧美巨大黑人极品精男| 亚洲成人av影片| 国产99久久久久久免费看农村| 亚洲一区二区在线| 亚洲av无码乱码国产精品| 国产精品天天摸av网| 精品少妇在线视频| japansex久久高清精品| 亚洲视频综合网| 中文字幕观看av| 视频一区视频二区中文字幕| 国产三级精品网站| 邻家有女韩剧在线观看国语| 亚洲国产成人av网| 精品国产aⅴ一区二区三区东京热 久久久久99人妻一区二区三区 | 成人免费观看毛片| 网站一区二区| 久久精品2019中文字幕| 免费黄色一级大片| 26uuu国产电影一区二区| 日本aa在线观看| 国产高清精品二区| 综合136福利视频在线| 久久中文字幕免费| 不卡视频免费播放| 日韩欧美猛交xxxxx无码| 涩涩网在线视频| 亚洲精品在线免费播放| 日韩在线中文字幕视频| 国产综合久久久久影院| 在线视频亚洲自拍| 欧美成人毛片| 久久精品久久精品亚洲人| 色婷婷久久综合中文久久蜜桃av| 国产精品一区在线| 人禽交欧美网站免费| 国产自产自拍视频在线观看| 精品99999| 日韩免费一二三区| 成人av在线播放网址| 亚洲中文字幕无码av永久| 国产精品男女| 欧美有码在线观看| 福利视频在线导航| 欧美吞精做爰啪啪高潮| 国产视频123区| a91a精品视频在线观看| 久久99热只有频精品91密拍| 性国裸体高清亚洲| 欧美大片在线观看| 日本视频www| 久久色在线视频| 中文字幕第21页| 999精品视频| 99re在线播放| 自拍偷拍亚洲视频| 色七七影院综合| 国产三级伦理片| 亚洲午夜视频在线| 人人妻人人澡人人爽人人精品| 综合一区在线| 国产精品视频免费观看| 免费观看欧美大片| 最近2019中文字幕第三页视频| 久久精品这里有| 久久久久久婷| 中文字幕在线亚洲精品| 一级毛片精品毛片| 欧美亚洲另类在线| 欧美精品videos另类| 日韩免费一区二区三区在线播放| 亚洲色图日韩精品| 国产69精品久久久久毛片| 欧美a在线视频| 成人看的视频| aa日韩免费精品视频一| 国产精品极品美女在线观看| 不卡毛片在线看| 青青操视频在线| 欧美性猛交xxxx免费看| 来吧亚洲综合网| av动漫一区二区| 精品无码国模私拍视频| 精品视频自拍| 国产有码在线一区二区视频| 国产资源在线观看入口av| 日韩中文字幕网址| 日韩偷拍自拍| 欧美一卡2卡三卡4卡5免费| 中文字幕求饶的少妇| 粉嫩绯色av一区二区在线观看| 最新av网址在线观看| 一本色道久久综合狠狠躁的番外| 欧美最顶级的aⅴ艳星| 亚洲欧美一区二区三| 欧美视频中文在线看| 午夜剧场免费在线观看| 久久精品一区蜜桃臀影院| 国产一区视频免费观看| 国产专区一区| 亚洲一区二区精品在线观看| 久久久久久久久久久久电影| 国产精品com| free性m.freesex欧美| 日韩一二三在线视频播| 欧美视频综合| 亚洲国产高清自拍| av网站在线观看免费| 欧美日韩综合一区| 一级黄色大片视频| 五月天丁香久久| 久久精品国产亚洲av高清色欲 | 91精品久久久久久久久久久久| 日本不卡123| 波多野结衣家庭教师视频| 欧美一级精品| 欧美专区一二三 | 奇米四色…亚洲| 国产视频九色蝌蚪| 日本一本不卡| 日韩欧美激情一区二区| 国产成人ay| 欧美精品一区二区三区久久| 8848成人影院| 国产精品yjizz| 亚洲专区**| 亚洲jizzjizz日本少妇| 亚洲精品三区| 欧美亚洲国产精品| 僵尸再翻生在线观看| 高清欧美一区二区三区| heyzo中文字幕在线| 午夜精品久久久久久久久久久久 | 成人性生交大合| 精品人妻一区二区乱码| 韩国av一区二区三区在线观看| 亚洲 欧美 日韩 国产综合 在线| 99欧美视频| 亚洲美女搞黄| 99热国内精品永久免费观看| 二级片在线观看| 亚洲欧洲美洲一区二区三区| 永久免费在线看片视频| 亚洲精品3区| 日韩精品一区二区三区四区五区 | 91麻豆精品91久久久久同性| 在线免费看毛片| 欧美日本一区二区在线观看| 99精品视频在线播放免费| 日韩精品专区在线影院观看| 人人妻人人澡人人爽人人欧美一区| 欧美精品精品一区| 国产裸体永久免费无遮挡| 日韩一区二区视频| 免费国产精品视频| 日韩视频永久免费| 亚洲免费不卡视频| 日韩电影大片中文字幕| 国产午夜在线视频| 日韩亚洲在线观看| 男人天堂亚洲天堂| 日韩免费观看在线观看| 久久天天久久| 国产精品对白刺激久久久| 欧美男男gaygay1069| 国产精品久久久久久中文字| 电影中文字幕一区二区| 国产精品日韩一区二区免费视频| 精品麻豆剧传媒av国产九九九| 国产精品国产三级国产aⅴ9色| 美女在线视频免费| 国产精品三级美女白浆呻吟| 久久亚洲精品人成综合网| 福利视频一区二区三区| 久久综合亚洲| 屁屁影院ccyy国产第一页| 美女日韩在线中文字幕| 九九九九九九九九| 国产最新精品精品你懂的| 中文字幕人妻一区| 中日韩av电影| 亚州国产精品视频| 欧美乱妇20p| 日韩午夜影院| 欧美成人在线影院| 成人精品电影在线| 国产69精品久久久久9999apgf| 北条麻妃在线一区二区免费播放| 97人人做人人人难人人做| 久久最新网址| 亚洲高清资源综合久久精品| 亚洲午夜极品| 精品少妇人妻av免费久久洗澡| 在线精品观看| 99视频在线观看视频| 国产亚洲精品7777| www成人啪啪18软件| 狠狠色噜噜狠狠狠狠97| 精品国产九九九| 中文字幕日韩欧美在线| 日本三级一区| 国产精品免费观看高清| 亚洲乱码电影| 亚洲精品自拍网| 国产精品资源网| 污污视频网站在线免费观看| 色网综合在线观看| 天天插天天干天天操| 中文欧美在线视频| 亚洲精品一区| 精品一区二区国产| 欧美日韩激情| 亚洲精品无码久久久久久| 国产成人精品一区二区三区网站观看| 亚洲中文字幕一区| 亚洲最大成人综合| 99国产精品99| 久久国产精彩视频| 24小时成人在线视频| 亚洲欧美日本国产有色| 日韩高清电影一区| 永久免费成人代码| 日韩欧美一区二区三区久久| 香蕉久久一区二区三区| 97在线免费观看| www.久久99| 在线看视频不卡| 一区二区三区四区五区在线 | 国产一区二区精品调教| 免费国产一区| 久久久久久9| 欧美多人猛交狂配| 91久久久免费一区二区| 精品视频一二区| 国产精品久久久久久久7电影| 亚洲**毛片| 成人在线免费观看视频网站| 国产精品香蕉一区二区三区| 免费污网站在线观看| 欧美性开放视频| 精品美女视频在线观看免费软件 | 黄网站免费久久| 紧身裙女教师波多野结衣| 欧美一级高清片在线观看| 影音先锋男人在线资源| 国产高清精品一区二区三区| 激情视频一区二区三区| www.超碰97| 日本高清成人免费播放| lutube成人福利在线观看| 91精品美女在线| 亚洲无吗在线| 亚洲狠狠婷婷综合久久久久图片| 亚洲精品乱码久久久久久| 亚洲第一免费视频| 欧美洲成人男女午夜视频| 国产一区二区三区四区五区传媒 | 亚洲综合影视| 成人激情视频小说免费下载| 你懂的国产精品| 一区二区三区欧美精品| 一二三区精品视频| 亚洲日本香蕉视频| 国产精品一区二区久久国产| 一区二区电影在线观看| 国产精品无码电影| 日本久久一区二区| 18+视频在线观看| 美女被啪啪一区二区| 在线欧美一区| 亚洲午夜久久久久久久国产| 91精品国产一区二区人妖| 天堂中文在线播放| 精品国产电影| 国产视频一区免费看| 成人黄色短视频| 亚洲国产精品久久| 国产精品久久久久久久久久齐齐| 欧美日韩亚洲在线| 国产精品一区专区| 久久久久99精品成人片毛片| 日韩精品一区二区三区老鸭窝| 羞羞网站在线免费观看| 欧美日韩精品久久久免费观看| 美女久久一区| 久久久久久久极品内射| 在线日韩中文字幕| 婷婷精品在线观看| 国产成人强伦免费视频网站| 在线观看网站黄不卡|