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

說透IO多路復用模型

存儲 存儲架構
在實際開發過程中,實際上LT更易用一些,畢竟系統幫助我們做了大部分校驗通知工作,之前提到的SELECT和POLL,默認采用的也都是這個。但是需要注意的是,當有成千上萬個客戶端連接上來開始進行數據發送,由于LT的特性,內核會頻繁的處理通知操作,導致其相對于ET來說,比較的耗費系統資源,所以,隨著客戶端的增多,其性能也就越差。

作者:京東零售 石朝陽

在說IO多路復用模型之前,我們先來大致了解下Linux文件系統。在Linux系統中,不論是你的鼠標,鍵盤,還是打印機,甚至于連接到本機的socket client端,都是以文件描述符的形式存在于系統中,諸如此類,等等等等,所以可以這么說,一切皆文件。來看一下系統定義的文件描述符說明:

從上面的列表可以看到,文件描述符0,1,2都已經被系統占用了,當系統啟動的時候,這三個描述符就存在了。其中0代表標準輸入,1代表標準輸出,2代表錯誤輸出。當我們創建新的文件描述符的時候,就會在2的基礎上進行遞增。可以這么說,文件描述符是為了管理被打開的文件而創建的系統索引,他代表了文件的身份ID。對標windows的話,你可以認為和句柄類似,這樣就更容易理解一些。

由于網上對linux文件這塊的原理描述的文章已經非常多了,所以這里我不再做過多的贅述,感興趣的同學可以從Wikipedia翻閱一下。由于這塊內容比較復雜,不屬于本文普及的內容,建議讀者另行自研,這里我非常推薦馬士兵老師將linux文件系統這塊,講解的真的非常好。

select模型

此模型是IO多路復用的最早期使用的模型之一,距今已經幾十年了,但是現在依舊有不少應用還在采用此種方式,可見其長生不老。首先來看下其具體的定義(來源于man二類文檔):

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout);

這里解釋下其具體參數:

參數一:nfds,也即maxfd,最大的文件描述符遞增一。這里之所以傳最大描述符,為的就是在遍歷fd_set的時候,限定遍歷范圍。

參數二:readfds,可讀文件描述符集合。

參數三:writefds,可寫文件描述符集合。

參數四:errorfds,異常文件描述符集合。

參數五:timeout,超時時間。在這段時間內沒有檢測到描述符被觸發,則返回。

下面的宏處理,可以對fd_set集合(準確的說是bitmap,一個描述符有變更,則會在描述符對應的索引處置1)進行操作:

FD_CLR(inr fd,fd_set* set) 用來清除描述詞組set中相關fd 的位,即bitmap結構中索引值為fd的值置為0。

FD_ISSET(int fd,fd_set *set) 用來測試描述詞組set中相關fd 的位是否為真,即bitmap結構中某一位是否為1。

FD_SET(int fd,fd_set*set) 用來設置描述詞組set中相關fd的位,即將bitmap結構中某一位設置為1,索引值為fd。

FD_ZERO(fd_set *set) 用來清除描述詞組set的全部位,即將bitmap結構全部清零。

首先來看一段服務端采用了select模型的示例代碼:

//創建server端套接字,獲取文件描述符
int listenfd = socket(PF_INET,SOCK_STREAM,0);
if(listenfd < 0) return -1;
//綁定服務器
bind(listenfd,(struct sockaddr*)&address,sizeof(address));
//監聽服務器
listen(listenfd,5);
struct sockaddr_in client;
socklen_t addr_len = sizeof(client);
//接收客戶端連接
int connfd = accept(listenfd,(struct sockaddr*)&client,&addr_len);
//讀緩沖區
char buff[1024];
//讀文件操作符
fd_set read_fds;
while(1)
{
memset(buff,0,sizeof(buff));
//注意:每次調用select之前都要重新設置文件描述符connfd,因為文件描述符表會在內核中被修改
FD_ZERO(&read_fds);
FD_SET(connfd,&read_fds);
//注意:select會將用戶態中的文件描述符表放到內核中進行修改,內核修改完畢后再返回給用戶態,開銷較大
ret = select(connfd+1,&read_fds,NULL,NULL,NULL);
if(ret < 0)
{
printf("Fail to select!\n");
return -1;
}
//檢測文件描述符表中相關請求是否可讀
if(FD_ISSET(connfd, &read_fds))
{
ret = recv(connfd,buff,sizeof(buff)-1,0);
printf("receive %d bytes from client: %s \n",ret,buff);
}
}

上面的代碼我加了比較詳細的注釋了,大家應該很容易看明白,說白了大概流程其實如下:

首先,創建socket套接字,創建完畢后,會獲取到此套接字的文件描述符。

然后,bind到指定的地址進行監聽listen。這樣,服務端就在特定的端口啟動起來并進行監聽了。

之后,利用開啟accept方法來監聽客戶端的連接請求。一旦有客戶端連接,則將獲取到當前客戶端連接的connection文件描述符。

雙方建立連接之后,就可以進行數據互傳了。需要注意的是,在循環開始的時候,務必每次都要重新設置當前connection的文件描述符,是因為文件描描述符表在內核中被修改過,如果不重置,將會導致異常的情況。

重新設置文件描述符后,就可以利用select函數從文件描述符表中,來輪詢哪些文件描述符就緒了。此時系統會將用戶態的文件描述符表發送到內核態進行調整,即將準備就緒的文件描述符進行置位,然后再發送給用戶態的應用中來。

用戶通過FD_ISSET方法來輪詢文件描述符,如果數據可讀,則讀取數據即可。

舉個例子,假設此時連接上來了3個客戶端,connection的文件描述符分別為 4,8,12,那么其read_fds文件描述符表(bitmap結構)的大致結構為 00010001000100000....0,由于read_fds文件描述符的長度為1024位,所以最多允許1024個連接。

而在select的時候,涉及到用戶態和內核態的轉換,所以整體轉換方式如下:

所以,綜合起來,select整體還是比較高效和穩定的,但是呈現出來的問題也不少,這些問題進一步限制了其性能發揮:

  1. 文件描述符表為bitmap結構,且有長度為1024的限制。
  2. fdset無法做到重用,每次循環必須重新創建。
  3. 頻繁的用戶態和內核態拷貝,性能開銷較大。
  4. 需要對文件描述符表進行遍歷,O(n)的輪詢時間復雜度。

poll模型

考慮到select模型的幾個限制,后來進行了改進,這也就是poll模型,既然是select模型的改進版,那么肯定有其亮眼的地方,一起來看看吧。當然,這次我們依舊是先翻閱linux man二類文檔,因為這是官方的文檔,對其有著最為精準的定義。

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

其實,從運行機制上說來,poll所做的功能和select是基本上一樣的,都是等待并檢測一組文件描述符就緒,然后在進行后續的IO處理工作。只不過不同的是,select中,采用的是bitmap結構,長度限定在1024位的文件描述符表,而poll模型則采用的是pollfd結構的數組fds,也正是由于poll模型采用了數組結構,則不會有1024長度限制,使其能夠承受更高的并發。

pollfd結構內容如下:

struct pollfd {
int fd; /* 文件描述符 */
short events; /* 關心的事件 */
short revents; /* 實際返回的事件 */
};

從上面的結構可以看出,fd很明顯就是指文件描述符,也就是當客戶端連接上來后,fd會將生成的文件描述符保存到這里;而events則是指用戶想關注的事件;revents則是指實際返回的事件,是由系統內核填充并返回,如果當前的fd文件描述符有狀態變化,則revents的值就會有相應的變化。

events事件列表如下:

revents事件列表如下:

從列表中可以看出,revents是包含events的。接下來結合示例來看一下:

//創建server端套接字,獲取文件描述符
int listenfd = socket(PF_INET,SOCK_STREAM,0);
if(listenfd < 0) return -1;
//綁定服務器
bind(listenfd,(struct sockaddr*)&address,sizeof(address));
//監聽服務器
listen(listenfd,5);
struct pollfd pollfds[1];
socklen_t addr_len = sizeof(client);
//接收客戶端連接
int connfd = accept(listenfd,(struct sockaddr*)&client,&addr_len);
//放入fd數組
pollfds[0].fd = connfd;
pollfds[0].events = POLLIN;
//讀緩沖區
char buff[1024];
//讀文件操作符
fd_set read_fds;
while(1)
{
memset(buff,0,sizeof(buff));
/**
** SELECT模型專用
** 注意:每次調用select之前都要重新設置文件描述符connfd,因為文件描述符表會在內核中被修改
** FD_ZERO(&read_fds);
** FD_SET(connfd,&read_fds);
** 注意:select會將用戶態中的文件描述符表放到內核中進行修改,內核修改完畢后再返回給用戶態,開銷較大
** ret = select(connfd+1,&read_fds,NULL,NULL,NULL);
**/
ret = poll(pollfds, 1, 1000);
if(ret < 0)
{
printf("Fail to poll!\n");
return -1;
}
/**
** SELECT模型專用
** 檢測文件描述符表中相關請求是否可讀
** if(FD_ISSET(connfd, &read_fds))
** {
** ret = recv(connfd,buff,sizeof(buff)-1,0);
** printf("receive %d bytes from client: %s \n",ret,buff);
** }
**/
//檢測文件描述符數組中相關請求
if(pollfds[0].revents & POLLIN){
pollfds[0].revents = 0;
ret = recv(connfd,buff,sizeof(buff)-1,0);
printf("receive %d bytes from client: %s \n",ret,buff);
}
}

由于源碼中,我做了比較詳細的注釋,同時將和select模型不一樣的地方都列了出來,這里就不再詳細解釋了。總體說來,poll模型比select模型要好用一些,去掉了一些限制,但是仍然避免不了如下的問題:

  1. 用戶態和內核態仍需要頻繁切換,因為revents的賦值是在內核態進行的,然后再推送到用戶態,和select類似,整體開銷較大。
  2. 仍需要遍歷數組,時間復雜度為O(N)。

epoll模型

如果說select模型和poll模型是早期的產物,在性能上有諸多不盡人意之處,那么自linux 2.6之后新增的epoll模型,則徹底解決了性能問題,一舉使得單機承受百萬并發的課題變得極為容易。現在可以這么說,只需要一些簡單的設置更改,然后配合上epoll的性能,實現單機百萬并發輕而易舉。同時,由于epoll整體的優化,使得之前的幾個比較耗費性能的問題不再成為羈絆,所以也成為了linux平臺上進行網絡通訊的首選模型。

講解之前,還是linux man文檔鎮樓:linux man epoll 4類文檔 linux man epoll 7類文檔,倆文檔結合著讀,會對epoll有個大概的了解。和之前提到的select和poll不同的是,此二者皆屬于系統調用函數,但是epoll則不然,他是存在于內核中的數據結構,可以通過epoll_create,epoll_ctl及epoll_wait三個函數結合來對此數據結構進行操控。

說道epoll_create函數,其作用是在內核中創建一個epoll數據結構實例,然后將返回此實例在系統中的文件描述符。此epoll數據結構的組成其實是一個鏈表結構,我們稱之為interest list,里面會注冊連接上來的client的文件描述符。

其簡化工作機制如下:

說道epoll_ctl函數,其作用則是對epoll實例進行增刪改查操作。有些類似我們常用的CRUD操作。這個函數操作的對象其實就是epoll數據結構,當有新的client連接上來的時候,他會將此client注冊到epoll中的interest list中,此操作通過附加EPOLL_CTL_ADD標記來實現;當已有的client掉線或者主動下線的時候,他會將下線的client從epoll的interest list中移除,此操作通過附加EPOLL_CTL_DEL標記來實現;當有client的文件描述符有變更的時候,他會將events中的對應的文件描述符進行更新,此操作通過附加EPOLL_CTL_MOD來實現;當interest list中有client已經準備好了,可以進行IO操作的時候,他會將這些clients拿出來,然后放到一個新的ready list里面。

其簡化工作機制如下:

說道epoll_wait函數,其作用就是掃描ready list,處理準備就緒的client IO,其返回結果即為準備好進行IO的client的個數。通過遍歷這些準備好的client,就可以輕松進行IO處理了。

上面這三個函數是epoll操作的基本函數,但是,想要徹底理解epoll,則需要先了解這三塊內容,即:inode,鏈表,紅黑樹。

在linux內核中,針對當前打開的文件,有一個open file table,里面記錄的是所有打開的文件描述符信息;同時也有一個inode table,里面則記錄的是底層的文件描述符信息。這里假如文件描述符B fork了文件描述符A,雖然在open file table中,我們看新增了一個文件描述符B,但是實際上,在inode table中,A和B的底層是一模一樣的。這里,將inode table中的內容理解為windows中的文件屬性,會更加貼切和易懂。這樣存儲的好處就是,無論上層文件描述符怎么變化,由于epoll監控的數據永遠是inode table的底層數據,那么我就可以一直能夠監控到文件的各種變化信息,這也是epoll高效的基礎。更多詳細信息,請參閱這兩篇文章:Nonblocking IO & The method to epoll's madness.

簡化流程如下:

數據存儲這塊解決了,那么針對連接上來的客戶端socket,該用什么數據結構保存進來呢?這里用到了紅黑樹,由于客戶端socket會有頻繁的新增和刪除操作,而紅黑樹這塊時間復雜度僅僅為O(logN),還是挺高效的。有人會問為啥不用哈希表呢?當大量的連接頻繁的進行接入或者斷開的時候,擴容或者其他行為將會產生不少的rehash操作,而且還要考慮哈希沖突的情況。雖然查詢速度的確可以達到o(1),但是rehash或者哈希沖突是不可控的,所以基于這些考量,我認為紅黑樹占優一些。

客戶端socket怎么管理這塊解決了,接下來,當有socket有數據需要進行讀寫事件處理的時候,系統會將已經就緒的socket添加到雙向鏈表中,然后通過epoll_wait方法檢測的時候,其實檢查的就是這個雙向鏈表,由于鏈表中都是就緒的數據,所以避免了針對整個客戶端socket列表進行遍歷的情況,使得整體效率大大提升。 整體的操作流程為:

首先,利用epoll_create在內核中創建一個epoll對象。其實這個epoll對象,就是一個可以存儲客戶端連接的數據結構。

然后,客戶端socket連接上來,會通過epoll_ctl操作將結果添加到epoll對象的紅黑樹數據結構中。

然后,一旦有socket有事件發生,則會通過回調函數將其添加到ready list雙向鏈表中。

最后,epoll_wait會遍歷鏈表來處理已經準備好的socket,然后通過預先設置的水平觸發或者邊緣觸發來進行數據的感知操作。

從上面的細節可以看出,由于epoll內部監控的是底層的文件描述符信息,可以將變更的描述符直接加入到ready list,無需用戶將所有的描述符再進行傳入。同時由于epoll_wait掃描的是已經就緒的文件描述符,避免了很多無效的遍歷查詢,使得epoll的整體性能大大提升,可以說現在只要談論linux平臺的IO多路復用,epoll已經成為了不二之選。

水平觸發和邊緣觸發

上面說到了epoll,主要講解了client端怎么連進來,但是并未詳細的講解epoll_wait怎么被喚醒的,這里我將來詳細的講解一下。

水平觸發,意即Level Trigger,邊緣觸發,意即Edge Trigger,如果單從字面意思上理解,則不太容易,但是如果將硬件設計中的水平沿,上升沿,下降沿的概念引進來,則理解起來就容易多了。比如我們可以這樣認為:

如果將上圖中的方塊看做是buffer的話,那么理解起來則就更加容易了,比如針對水平觸發,buffer只要是一直有數據,則一直通知;而邊緣觸發,則buffer容量發生變化的時候,才會通知。雖然可以這樣簡單的理解,但是實際上,其細節處理部分,比圖示中展現的更加精細,這里來詳細的說一下。

邊緣觸發

針對讀操作,也就是當前fd處于EPOLLIN模式下,即可讀。此時意味著有新的數據到來,接收緩沖區可讀,以下buffer都指接收緩沖區:

  1. buffer由空變為非空,意即有數據進來的時候,此過程會觸發通知。

  1. buffer原本有些數據,這時候又有新數據進來的時候,數據變多,此過程會觸發通知。

  1. buffer中有數據,此時用戶對操作的fd注冊EPOLL_CTL_MOD事件的時候,會觸發通知。

針對寫操作,也就是當前fd處于EPOLLOUT模式下,即可寫。此時意味著緩沖區可以寫了,以下buffer都指發送緩沖區:

  1. buffer滿了,這時候發送出去一些數據,數據變少,此過程會觸發通知。

  1. buffer原本有些數據,這時候又發送出去一些數據,數據變少,此過程會觸發通知。

這里就是ET這種模式觸發的幾種情形,可以看出,基本上都是圍繞著接收緩沖區或者發送緩沖區的狀態變化來進行的。

晦澀難懂?不存在的,舉個栗子:

在服務端,我們開啟邊緣觸發模式,然后將buffer size設為10個字節,來看看具體的表現形式。

服務端開啟,客戶端連接,發送單字符A到服務端,輸出結果如下:

-->ET Mode: it was triggered once
get 1 bytes of content: A
-->wait to read!

可以看到,由于buffer從空到非空,邊緣觸發通知產生,之后在epoll_wait處阻塞,繼續等待后續事件。

這里我們變一下,輸入ABCDEFGHIJKLMNOPQ,可以看到,客戶端發送的字符長度超過了服務端buffer size,那么輸出結果將是怎么樣的呢?

-->ET Mode: it was triggered once
get 9 bytes of content: ABCDEFGHI
get 8 bytes of content: JKLMNOPQ
-->wait to read!

可以看到,這次發送,由于發送的長度大于buffer size,所以內容被折成兩段進行接收,由于用了邊緣觸發方式,buffer的情況是從空到非空,所以只會產生一次通知。

水平觸發

水平觸發則簡單多了,他包含了邊緣觸發的所有場景,簡而言之如下:

當接收緩沖區不為空的時候,有數據可讀,則讀事件會一直觸發。

當發送緩沖區未滿的時候,可以繼續寫入數據,則寫事件一直會觸發。

同樣的,為了使表達更清晰,我們也來舉個栗子,按照上述入輸入方式來進行。

服務端開啟,客戶端連接并發送單字符A,可以看到服務端輸出情況如下:

-->LT Mode: it was triggered once!
get 1 bytes of content: A

這個輸出結果,毋庸置疑,由于buffer中有數據,所以水平模式觸發,輸出了結果。

服務端開啟,客戶端連接并發送ABCDEFGHIJKLMNOPQ,可以看到服務端輸出情況如下:

-->LT Mode: it was triggered once!
get 9 bytes of content: ABCDEFGHI
-->LT Mode: it was triggered once!
get 8 bytes of content: JKLMNOPQ

從結果中,可以看出,由于buffer中數據讀取完畢后,還有未讀完的數據,所以水平模式會一直觸發,這也是為啥這里水平模式被觸發了兩次的原因。

有了這兩個栗子的比對,不知道聰明的你,get到二者的區別了嗎?

在實際開發過程中,實際上LT更易用一些,畢竟系統幫助我們做了大部分校驗通知工作,之前提到的SELECT和POLL,默認采用的也都是這個。但是需要注意的是,當有成千上萬個客戶端連接上來開始進行數據發送,由于LT的特性,內核會頻繁的處理通知操作,導致其相對于ET來說,比較的耗費系統資源,所以,隨著客戶端的增多,其性能也就越差。

而邊緣觸發,由于監控的是FD的狀態變化,所以整體的系統通知并沒有那么頻繁,高并發下整體的性能表現也要好很多。但是由于此模式下,用戶需要積極的處理好每一筆數據,帶來的維護代價也是相當大的,稍微不注意就有可能出錯。所以使用起來須要非常小心才行。

至于二者如何抉擇,諸位就仁者見仁智者見智吧。

行文到這里,關于epoll的講解基本上完畢了,大家從中是不是學到了很多干貨呢? 由于從netty研究到linux epoll底層,其難度非常大,可以用曲高和寡來形容,所以在這塊探索的文章是比較少的,很多東西需要自己照著man文檔和源碼一點一點的琢磨(linux源碼詳見eventpoll.c等)。這里我來糾正一下搜索引擎上,說epoll高性能是因為利用mmap技術實現了用戶態和內核態的內存共享,所以性能好,我前期被這個觀點誤導了好久,后來下來了linux源碼,翻了一下,并沒有在epoll中翻到mmap的技術點,所以這個觀點是錯誤的。這些錯誤觀點的文章,國內不少,國外也不少,希望大家能審慎抉擇,避免被錯誤帶偏。

所以,epoll高性能的根本就是,其高效的文件描述符處理方式加上頗具特性邊的緣觸發處理模式,以極少的內核態和用戶態的切換,實現了真正意義上的高并發。

責任編輯:武曉燕 來源: 今日頭條
相關推薦

2020-10-14 09:11:44

IO 多路復用實現機

2021-05-31 06:50:47

SelectPoll系統

2024-08-08 14:57:32

2020-10-13 07:51:03

五種IO模型

2023-11-07 08:19:35

IO多路復用磁盤、

2022-08-26 00:21:44

IO模型線程

2023-12-13 09:45:49

模型程序

2025-04-24 10:05:51

2023-03-01 14:32:31

redisIOEpoll

2024-09-26 16:01:52

2021-03-05 11:26:42

面試Java程序

2011-12-08 10:51:25

JavaNIO

2009-06-29 18:09:12

多路復用Oracle

2022-01-06 14:45:10

數據庫連接池IO

2023-05-08 00:06:45

Go語言機制

2023-12-06 07:16:31

Go語言語句

2025-06-06 00:33:00

2025-05-07 11:54:05

2022-09-12 06:33:15

Select多路復用

2025-04-10 03:00:00

點贊
收藏

51CTO技術棧公眾號

色综合视频一区二区三区44| 国产三级在线免费| 亚洲婷婷在线| 亚洲国产欧美精品| 欧美黑人又粗又大又爽免费| 亚洲天天影视| 成人激情免费网站| 国产99在线|中文| 午夜剧场免费在线观看| 国内精品偷拍| 欧美影视一区在线| 影音先锋成人资源网站| 婷婷在线观看视频| 美女在线视频一区| 国模视频一区二区三区| 日本少妇xxxxx| а√中文在线天堂精品| 欧美在线观看视频一区二区三区| 9191国产视频| 成人激情电影在线看| 国产精品综合二区| 国产精品极品美女粉嫩高清在线| 欧美片一区二区| 欧美日韩高清| 亚洲精品mp4| 色18美女社区| 性感美女一区二区在线观看| 亚洲永久免费av| 亚洲精品高清视频| 欧美亚洲日本| 成人永久aaa| 成人免费网站在线看| 亚洲婷婷综合网| 亚洲五月婷婷| 欧美精品在线第一页| 中文字幕第20页| 欧美久久香蕉| 日韩欧美国产三级电影视频| 日本肉体xxxx裸体xxx免费| 高清在线视频不卡| 亚洲精品免费播放| 亚洲一区二区在线看| 免费在线一级视频| 成人激情免费网站| 国产福利久久| 国产三区在线播放| 精品制服美女丁香| 国产精品欧美激情在线播放| 日本一区二区网站| 韩日在线一区| 欧美俄罗斯性视频| 国产极品国产极品| 亚洲午夜精品一区 二区 三区| 亚洲色图35p| 黄瓜视频污在线观看| 欧美黑人巨大videos精品| 精品国产乱码久久久久久蜜臀| 成人免费黄色av| 自拍偷拍亚洲| 3d成人h动漫网站入口| 久久人人爽av| 亚洲a成人v| 欧美精品99久久久**| 999在线观看| 一区二区三区| 欧美一区二区三区在线观看| 特级黄色片视频| 欧州一区二区三区| 欧美精品一区男女天堂| 加勒比精品视频| 亚洲+变态+欧美+另类+精品| 精品小视频在线| 亚洲码无人客一区二区三区| 天堂一区二区三区四区| 亚洲丝袜av一区| 中文字幕有码在线播放| 日韩毛片视频| 久久亚洲精品一区| 久一区二区三区| 亚洲精品看片| 国产精品九九久久久久久久| 在线视频1卡二卡三卡| 国产一区二区三区精品视频| αv一区二区三区| 神宫寺奈绪一区二区三区| xf在线a精品一区二区视频网站| 欧美日韩高清在线一区| 日本中文字幕在线看| 亚洲精品视频在线观看网站| 日本午夜激情视频| 你懂得影院夜精品a| 欧美人妇做爰xxxⅹ性高电影| 久久久久亚洲av无码麻豆| 日韩一二三区在线观看| 亚洲精品美女在线观看播放| 91资源在线播放| 亚洲女同中文字幕| 91精品国产高清| 中文字幕福利视频| 国产凹凸在线观看一区二区| 欧美精品与人动性物交免费看| 国产香蕉在线| 亚洲一区二区三区三| 日韩一级免费在线观看| 视频一区国产| 亚洲欧美日韩在线一区| 一区二区视频免费看| 亚洲一区日韩在线| 91在线直播亚洲| 人人九九精品| 亚洲精品中文字幕在线观看| 女人和拘做爰正片视频| 国产精品成人3p一区二区三区| 亚洲精品美女视频| a在线视频播放观看免费观看| 国产精品一页| 99久久综合狠狠综合久久止| 欧美91精品久久久久国产性生爱| 亚洲精品高清在线| 成年网站在线播放| 欧美变态挠脚心| 久久天天躁日日躁| 中文字幕在线播放日韩| 99久久精品情趣| 欧美高清中文字幕| 国产精品.xx视频.xxtv| 亚洲精品资源美女情侣酒店 | 国产精品久久久一本精品| 欧美精品卡一卡二| av在线国产精品| 有码中文亚洲精品| 亚洲欧美一区二区三区在线观看| 国产成人综合精品三级| 国产又大又长又粗又黄| 桃花岛成人影院| 亚洲国产精品久久| 久久久久亚洲天堂| 国产黄人亚洲片| 中国成人亚色综合网站 | 国产乱人伦真实精品视频| 亚洲 小说区 图片区 都市| 一区二区三区在线观看动漫| 中国黄色片一级| av一区二区在线播放| 日韩暖暖在线视频| 日本中文字幕电影在线观看| 午夜精品国产更新| 国产免费一区二区三区最新6| 欧美一区二区三区另类 | 久久天天躁狠狠躁夜夜躁2014| 国产精品sm调教免费专区| 国产亚洲一本大道中文在线| 亚洲精品无码久久久久久| 奇米影视777在线欧美电影观看| 国内精品在线一区| 四虎精品一区二区三区| 性做久久久久久免费观看| 亚洲午夜久久久久久久久| 国产精品www994| 国产伦精品一区二区三区照片91 | 丰满人妻一区二区三区免费视频 | 国产丝袜精品视频| 黄色污污网站在线观看| 国产午夜精品福利| www.久久久精品| 五月激情久久久| 亚洲自拍欧美另类| 青草视频在线免费直播| 精品国产1区二区| 国产综合精品视频| 国产日韩精品一区二区三区在线| 天天干在线影院| 久久大综合网| www.久久艹| 自拍偷拍亚洲视频| 中文国产成人精品久久一| 国产精品一区二区三区在线免费观看 | 综合一区在线| 国产伦精品一区二区三区| 亚洲欧洲高清| www欧美日韩| 黄色片一区二区| 在线看国产一区| tube国产麻豆| 99久久精品国产毛片| 国产l精品国产亚洲区久久| 日韩三级在线| 国产精品18毛片一区二区| 精品国产第一福利网站| 中文字幕日韩欧美精品在线观看| 精品女同一区二区三区| 欧美性猛交xxxx乱大交| 天天色天天综合| 成人av电影在线播放| 小泽玛利亚视频在线观看| 欧美1区视频| 热舞福利精品大尺度视频| 国内精品视频| 日本精品久久久久久久| av片哪里在线观看| 亚洲人成网站免费播放| 草逼视频免费看| 色狠狠色噜噜噜综合网| 精品少妇爆乳无码av无码专区| 久久精品欧美日韩| 日韩高清一二三区| 免费视频一区二区| 黄色国产一级视频| 亚洲91视频| 日韩av大全| 欧洲精品一区| 成人黄色在线免费观看| 992tv国产精品成人影院| 久久理论片午夜琪琪电影网| 丝袜美腿美女被狂躁在线观看| 亚洲成人a**站| aaa一区二区三区| 欧美视频第二页| 成人免费区一区二区三区| 亚洲乱码国产乱码精品精可以看| 亚洲精品国产91| av中文字幕一区| 黑人巨大猛交丰满少妇| 美日韩一区二区三区| 日韩精品无码一区二区三区免费| 国模大胆一区二区三区| 超碰成人在线免费观看| 成人三级视频| 欧美另类一区| 欧美黑人做爰爽爽爽| 国产精品初高中精品久久| 四虎精品在线观看| 国产日韩欧美成人| 蜜桃精品在线| 欧美在线观看网址综合| aa国产成人| 午夜精品在线视频| 国精产品一区一区三区mba下载| 久久精品久久精品亚洲人| www.国产精品.com| 一色桃子一区二区| 经典三级在线| 一区二区中文字幕| 成黄免费在线| 在线观看欧美www| yiren22亚洲综合伊人22| 国产亚洲一区精品| 成人免费一区二区三区视频网站| 亚洲午夜未删减在线观看 | 亚洲婷婷久久综合| 在线免费观看日本欧美| 中国a一片一级一片| 欧美性欧美巨大黑白大战| 黄色av一区二区| 欧美亚洲动漫精品| 中文字幕一区二区人妻痴汉电车| 欧美亚洲自拍偷拍| 一区二区美女视频| 日韩一区二区免费在线观看| 精品人妻一区二区三区麻豆91| 日韩一区二区三区在线| 亚洲av无码专区在线| 精品女同一区二区| 姝姝窝人体www聚色窝| 亚洲老头老太hd| 国产剧情在线观看| 最新国产成人av网站网址麻豆| 五月天婷婷在线视频| 欧美另类高清videos| 爱情岛亚洲播放路线| 69精品小视频| 日韩不卡视频在线观看| 91精品在线影院| 久久午夜影院| 日本一区二区三区视频在线观看 | 国语对白永久免费| 欧美午夜电影网| av手机免费看| 日韩av综合网| 香蕉视频在线免费看| 欧美伦理91i| 手机在线理论片| 国产精品青草久久久久福利99| 精品三级久久久| 精品午夜一区二区| 日韩精品永久网址| 日本一级黄视频| 久久精品盗摄| 欧美精品 - 色网| 99riav久久精品riav| 少妇视频在线播放| 亚洲国产综合在线| 91青青草视频| 日韩你懂的在线观看| 九色在线播放| 久久97精品久久久久久久不卡| av电影一区| 91九色在线视频| 日韩美女国产精品| 色乱码一区二区三区熟女 | 欧美亚洲国产视频| 欧美午夜三级| 久久99久久99精品蜜柚传媒| 国产精品91一区二区三区| av之家在线观看| 国产裸体歌舞团一区二区| 欧美图片第一页| 亚洲一区二区三区三| 一级视频在线播放| 亚洲精品在线观看www| 在线中文字幕第一页| 国产精品久久久久福利| 精品无人区一区二区| 9l视频自拍9l视频自拍| 日韩在线观看一区二区| 亚洲婷婷在线观看| 亚洲欧美日韩电影| 在线观看一二三区| 亚洲精品一区中文| 不卡一本毛片| 亚洲a级在线播放观看| 色乱码一区二区三区网站| 国产中文字幕免费观看| 国产成人亚洲精品狼色在线| 亚洲精品国产精品乱码在线观看| 懂色av一区二区三区| 欧美熟女一区二区| 精品自拍视频在线观看| 24小时成人在线视频| 日韩性感在线| 天堂av在线一区| 大地资源二中文在线影视观看| 亚洲一区二区三区四区五区中文| 99久久精品国产一区色| www.午夜精品| 欧洲美女精品免费观看视频| 亚洲国产一区二区精品视频| 久久一区激情| 精品无码一区二区三区| 五月激情综合婷婷| 欧美熟女一区二区| 97激碰免费视频| 激情小说亚洲图片| 国产素人在线观看| 99久久精品99国产精品| 日韩欧美不卡视频| 日韩av中文在线| 日韩av影片| 欧美精品久久| 久久综合伊人| 性猛交ⅹxxx富婆video| 欧美中文字幕一区二区三区亚洲| 懂色一区二区三区| 国产精品久久二区| 欧美激情黄色片| 污免费在线观看| 亚洲曰韩产成在线| 四虎永久在线观看| 日本精品视频在线观看| 欧洲乱码伦视频免费| 在线观看av网页| 亚洲色图制服诱惑| 亚洲AV无码精品色毛片浪潮| 久久免费视频这里只有精品| 奇米影视777在线欧美电影观看 | 日本欧洲国产一区二区| 日韩不卡一区二区| 91制片厂在线| 欧美大片免费久久精品三p| 丰乳肥臀在线| 欧洲精品一区色| 国产一区二区调教| 日韩欧美亚洲一区二区三区| 亚洲美女av黄| 黄色精品视频网站| 亚洲精品少妇一区二区| av福利精品导航| 波多野结衣一区二区在线| 日韩视频永久免费观看| 在线综合色站| 久久精品香蕉视频| 亚洲天堂精品视频| 特黄aaaaaaaaa真人毛片| 国产精品白嫩初高中害羞小美女| 欧美aaaaaaaaaaaa| 在线xxxxx| 欧美日韩在线播放三区四区| 性欧美videos高清hd4k| 久久久99爱| 国产在线视频不卡二| 永久免费看片在线播放| 日日骚av一区| 红杏一区二区三区| 亚州精品一二三区| 亚洲一区二区高清| 第三区美女视频在线| 99国产精品久久久久老师| 老司机精品导航| 激情视频在线播放| 中文字幕久久精品|