精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

欧美性xxxx图片| 色综合久久久久无码专区| 国产麻豆一精品一男同| 国产一区亚洲| 亚洲欧美福利视频| 免费网站在线观看黄| 懂色av一区| 国产日韩欧美激情| 91精品久久久久久蜜桃| 日本一级片免费看| 色呦哟—国产精品| 欧美精品一区二区三区视频| 亚洲综合在线网站| 1区2区在线观看| av亚洲精华国产精华精华| 国产精品美女主播| 伊人国产在线观看| 99九九热只有国产精品| 亚洲黄色在线观看| 在线a免费观看| 欧美黑人粗大| 亚洲国产欧美一区二区三区丁香婷| 欧美日本韩国一区二区三区| 国产夫妻自拍av| 日本成人中文字幕在线视频| 国内精品在线一区| 糖心vlog免费在线观看| 亚洲精品进入| 亚洲国产高清高潮精品美女| 欧美专区第二页| 欧美精品高清| 欧美日韩视频免费播放| 成人国产在线看| 日日夜夜精品一区| 久久精品男人天堂av| 国产欧美一区二区三区另类精品| 中文字幕观看在线| 久久精品盗摄| 91av视频导航| 妺妺窝人体色www聚色窝仙踪 | 成年人一级黄色片| 精品日韩免费| 亚洲摸下面视频| 国产精品无码电影| 成人台湾亚洲精品一区二区| 欧美巨大另类极品videosbest| 国产l精品国产亚洲区久久| 俄罗斯一级**毛片在线播放| 亚洲综合丁香婷婷六月香| 亚洲小视频在线播放| 国产激情小视频在线| 国产精品网站在线| 日韩激情久久| 91在线看黄| 国产精品视频免费看| 婷婷久久伊人| 欧美成熟毛茸茸| 91首页免费视频| 狠狠久久综合婷婷不卡| 日韩中文字幕免费在线观看| 国产成人福利片| av激情久久| 欧美综合视频在线| 91蜜桃在线观看| 美国av一区二区三区| 三级av在线播放| 久久久91精品国产一区二区三区| 欧美日韩大片一区二区三区| 国产天堂素人系列在线视频| 国产女主播一区| 亚洲资源视频| 影音先锋男人在线资源| 亚洲一级二级三级| 国产精品无码一区二区在线| 欧美18—19sex性hd| 色婷婷av一区二区三区之一色屋| 成人黄色一区二区| 亚洲色图综合| 欧美va亚洲va国产综合| 亚洲の无码国产の无码步美| 久久93精品国产91久久综合| 日韩一区二区三区国产| 久久久久亚洲av无码专区体验| 欧美日韩国产综合网| 91精品国产乱码久久久久久久久| 欧美日韩一级黄色片| 蜜臀av一区二区在线免费观看| 成人黄色网免费| 亚洲精品久久久久久久久久久久久久| av中文字幕亚洲| 日韩和欧美的一区二区| a级片国产精品自在拍在线播放| 亚洲午夜av在线| 中文字幕第21页| 久久久久久久久成人| 亚洲精品动漫100p| 免费一级suv好看的国产网站| 亚洲二区三区不卡| 91精品国产99久久久久久| 中文字幕一区二区三区四区视频| 国产91丝袜在线18| 日韩一区二区三区资源| 国内在线视频| 欧美日韩中文字幕一区| 在线免费观看污视频| 欧美xxav| 国产91精品久| 国产免费福利视频| 国产日韩欧美综合在线| 欧美大黑帍在线播放| 精品免费av一区二区三区 | 日韩一级片免费在线观看| 欧美国产在线观看| 一二三四视频社区在线| 亚洲高清影院| 亚洲欧洲国产伦综合| 九九热精品免费视频| 日韩中文字幕区一区有砖一区| 亚洲综合色激情五月| 国产精品久久久久一区二区国产 | 亚洲天堂成人在线视频| 麻豆国产尤物av尤物在线观看| 首页国产欧美日韩丝袜| 国产一区二区三区无遮挡| 国产成人无吗| 欧美自拍偷拍午夜视频| 波多野结衣先锋影音| 欧美激情1区2区3区| 国产精品日韩在线播放| 日本a一级在线免费播放| 亚洲精品国产高清久久伦理二区| 性chinese极品按摩| 猛男gaygay欧美视频| 久久久女人电视剧免费播放下载| 国产精品高潮呻吟AV无码| 欧美激情综合五月色丁香| 欧美a v在线播放| 粉嫩av一区二区| 久久6免费高清热精品| 国产精品久久久午夜夜伦鲁鲁 | 久久爱一区二区| 日本大胆欧美人术艺术动态| 区一区二区三区中文字幕| 成人观看网址| 亚洲精品久久久久久久久久久| 欧美黄色免费在线观看| 黑人巨大精品欧美黑白配亚洲| 手机成人在线| 国产精品久久久久久吹潮| 亚洲欧美制服中文字幕| 99久久久无码国产精品免费蜜柚 | 久久99精品久久久久久久青青日本| 欧美卡一卡二| 欧美mv和日韩mv的网站| 国产在线视频二区| www.亚洲在线| 国产极品在线视频| 伊人久久大香线蕉综合网站 | 天堂中文字幕在线观看| 久久久久久久久久久黄色| 北条麻妃视频在线| 日韩夫妻性生活xx| 91免费国产视频| 亚洲精品天堂| 日韩精品极品视频免费观看| 日韩精品在线免费视频| 国产日韩精品一区二区三区| 91人人澡人人爽人人精品| 91亚洲国产| 狠狠色噜噜狠狠狠狠97| 国产亚洲欧美日韩在线观看一区二区| 亚洲少妇中文在线| 精品91久久久| 99久久精品国产一区二区三区 | 男人的天堂成人在线| 久久影院理伦片| 你懂得影院夜精品a| 中文日韩在线视频| 国产精品探花视频| 亚洲中国最大av网站| 色婷婷精品久久二区二区密| 国产乱码精品| 日本一区二区精品视频| 国产精品第一| 欧美巨大黑人极品精男| 天天干天天操av| 欧美在线观看视频一区二区三区| 成人无码精品1区2区3区免费看| 国产精品亚洲午夜一区二区三区 | 欧美日韩精品在线| 91视频免费观看网站| 美女精品自拍一二三四| 青春草在线视频免费观看| 国产精品欧美大片| 国产成人短视频| 成人看av片| 精品久久国产老人久久综合| 国产熟妇一区二区三区四区| 亚洲色图制服诱惑| 久久人人爽人人爽人人片| 开心九九激情九九欧美日韩精美视频电影 | 久久久夜色精品亚洲| 五月天视频在线观看| 亚洲美女一区| 中文字幕在线亚洲精品| 欧美日韩另类图片| 成人女保姆的销魂服务| 台湾佬中文娱乐网欧美电影| 久久精品2019中文字幕| 日韩精品系列| 日韩视频一区二区三区| 自拍偷拍18p| 亚洲成a人片在线观看中文| 国产三级黄色片| heyzo一本久久综合| 999这里有精品| 男人的天堂亚洲在线| 黄色三级中文字幕| 日韩精品一区二区三区免费观看| 国产偷国产偷亚洲高清97cao| 亚洲成人毛片| 国产精品都在这里| 蜜桃视频在线网站| 美女精品久久久| 中文字幕日本在线| 亚洲社区在线观看| 亚洲三级中文字幕| 精品国产一二三区| 99久久免费国产精精品| 欧美日韩三级在线| av片免费观看| 欧美小视频在线| 青青草成人av| 亚洲h动漫在线| 青青草手机在线视频| 中文字幕亚洲一区二区va在线| 精品人妻无码一区二区三区换脸| 99久久久精品免费观看国产蜜| aaaaa黄色片| 国产成人日日夜夜| 欧美国产日韩另类| 狠狠色狠狠色合久久伊人| 国产又猛又黄的视频| 日韩电影一二三区| 苍井空浴缸大战猛男120分钟| 日韩午夜电影| 人妻夜夜添夜夜无码av| 激情成人综合| 中国丰满熟妇xxxx性| 韩日成人在线| 男人添女人荫蒂免费视频| 亚洲视频精品| 18禁免费观看网站| 国产亚洲毛片在线| 欧美 国产 日本| 丝袜亚洲另类欧美| 午夜欧美福利视频| 久久se这里有精品| 激情成人在线观看| 国产成人免费视| 美女久久久久久久久| gogo大胆日本视频一区| 久久久久久久久免费看无码| 91理论电影在线观看| 四虎永久免费在线观看| 中文一区二区在线观看| 欧美大片xxxx| 亚洲一二三四在线观看| 国产成人免费观看视频| 91搞黄在线观看| 综合久久中文字幕| 91精品国产综合久久福利软件 | 亚洲第一在线视频| 国内av一区二区三区| 日韩小视频网址| 国产经典三级在线| 国产99久久精品一区二区 夜夜躁日日躁| 色香欲www7777综合网| 成人久久18免费网站图片| 99亚洲乱人伦aⅴ精品| 欧美激情第六页| 色999日韩| 真人抽搐一进一出视频| 日韩精品免费专区| 91精品999| 99久久免费国产| 国产7777777| 亚洲一区二区五区| 日本欧美www| 日韩丝袜情趣美女图片| 男女网站在线观看| 久久久国产在线视频| 久草在线中文最新视频| 国产日韩欧美自拍| 欧美福利在线播放网址导航| 亚洲二区自拍| 1024成人| 九九九九九九九九| 91首页免费视频| 午夜精品一区二区三区视频| 岛国av在线不卡| 国产美女免费看| 亚洲欧洲激情在线| 3344国产永久在线观看视频| 国产精品精品久久久久久| 超碰97久久国产精品牛牛| 午夜精品一区二区在线观看的 | 国产精品欧美经典| 亚洲第一精品在线观看| 日韩一区二区三区免费观看| 精品美女视频在线观看免费软件| 欧美国产日韩一区二区| 欧美暴力调教| 精品在线不卡| 欧美激情一区| 性欧美1819| 26uuu亚洲| 国产大片aaa| 欧美一级黄色片| 日本在线免费中文字幕| 日韩美女福利视频| 欧美调教在线| 国产日韩欧美精品在线观看| 经典三级在线一区| av电影网站在线观看| 午夜精品久久久久| 亚洲成人77777| 麻豆乱码国产一区二区三区| 国产91在线精品| 日韩av大全| 亚洲免费网站| a天堂视频在线观看| 亚洲五码中文字幕| 超碰在线观看av| 欧美大胆a视频| 99精品在线免费观看| 婷婷五月色综合| 噜噜噜躁狠狠躁狠狠精品视频| www国产视频| 亚洲电影一级黄| 日本国产在线观看| 国产69精品久久久久9999| 2021年精品国产福利在线| 六月婷婷激情综合| 高清久久久久久| 日韩欧美亚洲国产| 精品国产伦一区二区三区免费| 丝袜美腿av在线| 成人免费看片网址| 亚洲激情av| 欧美大喷水吹潮合集在线观看| 亚洲精品成人天堂一二三| www.黄色片| 欧美激情亚洲综合一区| 97久久超碰| 免费看毛片的网址| 91在线码无精品| 中文字幕在线观看视频免费| 在线国产精品播放| www.成人在线视频| 宅男av一区二区三区| 国产精品一区一区三区| 久久国产一级片| 亚洲精品国产精品国自产在线| 五月天国产在线| 色综合电影网| 极品尤物av久久免费看| 欧美精品videos极品| 亚洲黄色免费三级| 日韩中文视频| 看全色黄大色大片| www.日韩大片| 国产成人无码专区| 久久亚洲综合国产精品99麻豆精品福利 | 日本少妇激三级做爰在线| 亚洲精品第1页| 日韩av地址| 国产精品三级久久久久久电影| 91欧美在线| 久草免费资源站| 欧美视频免费在线| 免费观看在线午夜影视| 国产欧美日本在线| 日本aⅴ亚洲精品中文乱码| 91成人福利视频| 亚洲精品小视频| 成人久久精品| 日韩av综合在线观看| 国产精品沙发午睡系列990531| av免费在线不卡| 奇米四色中文综合久久| 91亚洲自偷观看高清| 亚洲自拍偷拍精品| 欧美综合天天夜夜久久| 天堂成人av| 日韩精品久久一区| 高清久久久久久| 亚洲熟妇无码久久精品| 97视频在线观看免费高清完整版在线观看| 成人情趣视频|