久久福利_99r_国产日韩在线视频_直接看av的网站_中文欧美日韩_久久一

您的位置:首頁技術文章
文章詳情頁

UNIX 共享內存應用中的問題及解決方法

瀏覽:2日期:2024-06-14 08:04:26

簡介

共享內存是一種非常重要且常用的進程間通信方式,相對于其它IPC機制,因其速度最快、效率最高,被廣泛應用于各類軟件產品及應用開發中。System V IPC 為Unix平臺上的共享內存應用制定了統一的API標準,從而為在UNIX/Linux平臺上進行跨平臺開發提供了極大的便利;開發人員基于一套基本相同的源代碼,便可開發出同時支持AIX、Solaris、HP-UX、Linux等平臺的產品。

然而,各個平臺對System V 標準的API在實現上各有差異,由此對相關應用開發帶來影響,甚至引入難以調試的問題。本文將結合作者在Tivoli產品開發中的實際經驗,對這些平臺相關的問題,以及具有共性的問題,逐一進行分析,并提出解決方法。

1. System V共享內存概述

System V 進程間通信(IPC)包括3種機制:消息隊列、信號量、共享內存。消息隊列和信號量均是內核空間的系統對象,經由它們的數據需要在內核和用戶空間進行額外的數據拷貝;而共享內存和訪問它的所有應用程序均同處于用戶空間,應用進程可以通過地址映射的方式直接讀寫內存,從而獲得非常高的通信效率。

System V 為共享內存定義了下列API接口函數:

# include <sys/types.h># include <sys/ipc.h># include <sys/shm.h>key_t ftok(const char *pathname, int proj_id);int shmget(key_t key, int size, int shmflg);void* shmat(int shmid, const void *shmaddr, int shmflg);int shmdt(void *shmaddr);int shmctl(int shmid, int cmd, struct shmid_ds *buf);

ftok函數用于生成一個鍵值:key_t key,該鍵值將作為共享內存對象的唯一性標識符,并提供給為shmget函數作為其輸入參數;ftok 函數的輸入參數包括一個文件(或目錄)路徑名:pathname,以及一個額外的數字:proj_id,其中pathname所指定的文件(或目錄)要求必須已經存在,且proj_id不可為0;shmget函數用于創建(或者獲?。┮粋€由key鍵值指定的共享內存對象,返回該對象的系統標識符:shmid;shmat函數用于建立調用進程與由標識符shmid指定的共享內存對象之間的連接;shmdt函數用于斷開調用進程與共享內存對象之間的連接;shmctl函數用于對已創建的共享內存對象進行查詢、設值、刪除等操作;

2. ftok的陷阱

根據pathname指定的文件(或目錄)名稱,以及proj_id參數指定的數字,ftok函數為IPC對象生成一個唯一性的鍵值。在實際應用中,很容易產生的一個理解是,在proj_id相同的情況下,只要文件(或目錄)名稱不變,就可以確保ftok返回始終一致的鍵值。然而,這個理解并非完全正確,有可能給應用開發埋下很隱晦的陷阱。因為ftok的實現存在這樣的風險,即在訪問同一共享內存的多個進程先后調用ftok函數的時間段中,如果pathname指定的文件(或目錄)被刪除且重新創建,則文件系統會賦予這個同名文件(或目錄)新的i節點信息,于是這些進程所調用的ftok雖然都能正常返回,但得到的鍵值卻并不能保證相同。由此可能造成的后果是,原本這些進程意圖訪問一個相同的共享內存對象,然而由于它們各自得到的鍵值不同,實際上進程指向的共享內存不再一致;如果這些共享內存都得到創建,則在整個應用運行的過程中表面上不會報出任何錯誤,然而通過一個共享內存對象進行數據傳輸的目的將無法實現。

AIX、Solaris、HP-UX均明確指出,key文件被刪除并重建后,不保證通過ftok得到的鍵值不變,比如AIX上ftok的man幫助信息即聲明:

Attention: If the Path parameter of the ftok subroutine names a file that has been removed while keys still refer to it, the ftok subroutine returns an error. If that file is then re-created, the ftok subroutine will probably return a key different from the original one.

Linux沒有提供類似的明確聲明,但我們可以通過下面的簡單例程test01.c,得到相同的印證:

#include <stdio.h>#include <sys/ipc.h>void main(int argc, char* argv[]){if (argc !=2 ) {printf("Usage: %s KeyFilen e.g. %s /tmp/mykeyfilen", argv[0], argv[0]);return;}printf("Key generated by ftok: 0x%xn", ftok(argv[1], 1));}

將上述例程在Red Hat Enterprise Linux AS release 4平臺上編程成可執行程序test01,并且通過touch命令在 /tmp目錄下創建一個新文件mykeyfile,然后為該文件生成鍵值:

# touch /tmp/mykeyfile# ./test01 /tmp/mykeyfileKey generated by ftok: 0x101000b

然后,將/tmp/mykeyfile刪除,并且通過vi命令重新創建該文件,再次生成鍵值:

# ./test01 /tmp/mykeyfileKey generated by ftok: 0x1010017

我們可以看到,雖然文件名稱都是 /tmp/mykeyfile,并未改變,但由于中間發生了文件刪除并重新創建的操作,前后兩次所得到的鍵值已經不再相同。

避免此類問題最根本的方法,就是采取措施保證pathname所指定的文件(或目錄)在共享內存的使用期間不被刪除,不要使用有可能被刪除的文件;或者干脆直接指定鍵值,而不借助ftok來獲取鍵值。

3. AIX中shmat的問題

AIX系統中,System V各類進程間通信機制在使用中均存在限制。區別于其它UNIX操作系統對IPC機制的資源配置方式,AIX使用了不同的方法;在AIX中定義了 IPC 機制的上限, 且是不可配置的。就共享內存機制而言,在4.2.1及以上版本的AIX系統上,存在下列限制:

對于64位進程,同一進程可連接最多268435456個共享內存段;

對于32位進程,同一進程可連接最多11個共享內存段,除非使用擴展的shmat;

上述限制對于64位應用不會帶來麻煩,因為可供連接的數量已經足夠大了;但對于32位應用,卻很容易帶來意外的問題,因為最大的連接數量只有11個。在某些事件觸發的多線程應用中,新的線程不斷地為進行事件處理而被創建,這些線程如果都需要去連接特定的共享內存,則極有可能造成該進程連接的共享內存數量超過11個,事實上同時擁有幾十個甚至上百個處理線程的應用并不少見。一旦超個這個限制值,則所有后續的處理線程都將無法正常工作,從而導致應用運行失敗。

下面的例程test02.c演示了這個問題,為了精簡代碼,它反復連接的是同一個共享內存對象;實際上,無論所連接的共享內存對象是否相同,該限制制約的是連接次數:

#include <stdio.h>#include <errno.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/shm.h>#define MAX_ATTACH_NUM 15void main(int argc, char* argv[]){key_t  mem_key;longmem_id;void*  mem_addr[MAX_ATTACH_NUM];int i;if ( ( mem_key = ftok("/tmp/mykeyfile", 1) ) == (key_t)(-1) ) {printf("Failed to generate shared memory access key, ERRNO=%dn",errno);goto MOD_EXIT;}if ( ( mem_id = shmget(mem_key, 256, IPC_CREAT) ) == (-1) ) {printf("Failed to obtain shared memory ID, ERRNO=%dn", errno);goto MOD_EXIT;}for ( i=1; i<=MAX_ATTACH_NUM; i++ ) {if ( ( mem_addr[i] = (void *)shmat(mem_id, 0, 0) ) == (void *)(-1) )printf("Failed to attach shared memory, times [%02d], errno:%dn", i,errno);elseprintf("Successfully attached shared memory, times [%02d]n", i);}MOD_EXIT:shmctl(mem_id, IPC_RMID, NULL);}

在AIX系統上,我們將其編譯為test02,并運行,可以看到如下輸出:

Successfully attached shared memory, times [01]Successfully attached shared memory, times [02]Successfully attached shared memory, times [03]Successfully attached shared memory, times [04]Successfully attached shared memory, times [05]Successfully attached shared memory, times [06]Successfully attached shared memory, times [07]Successfully attached shared memory, times [08]Successfully attached shared memory, times [09]Successfully attached shared memory, times [10]Successfully attached shared memory, times [11]Failed to attach shared memory, times [12], errno:24Failed to attach shared memory, times [13], errno:24Failed to attach shared memory, times [14], errno:24Failed to attach shared memory, times [15], errno:24

說明超出11個連接之后,所有后續的共享內存連接都將無法建立。錯誤碼24的定義是EMFILE,AIX給予的解釋是:

The number of shared memory segments attached to the calling process exceeds the system-imposed limit。

解決這個問題的方法是,使用擴展的shmat;具體而言就是,在運行相關應用之前(確切地說,是在共享內存被創建之前),首先在shell中設置EXTSHM環境變量,通過它擴展shmat,對于源代碼本身無需作任何修改:

export EXTSHM=ON

值得注意的是,雖然設置環境變量,在程序中也可通過setenv函數來做到,比如在程序的開始,加入下列代碼:

setenv("EXTSHM", "ON", 1);

但實踐證明這樣的方法在解決這個問題上是無效的;也就是說唯一可行的辦法,就是在shell中設置EXTSHM環境變量,而非在程序中。

在AIX上配置32位DB2實例時,也要求確保將環境變量 EXTSHM 設為 ON,這是運行 Warehouse Manager 和 Query Patroller 之前必需的操作:

export EXTSHM=ONdb2set DB2ENVLIST=EXTSHMdb2start

其原因即來自我們剛剛介紹的AIX中32位應用連接共享內存時,存在最大連接數限制。這個問題同樣普遍存在于AIX平臺上Oracle等軟件產品中。

4. HP-UX中shmget和shmat的問題

4.1 32位和64位應用兼容問題

在HP-UX平臺上,如果同時運行32位應用和64位應用,而且它們訪問的是一個相同的共享內存區,則會遇到兼容性問題。

在HP-UX中,應用程序設置IPC_CREAT標志調用shmget,所創建的共享內存區,只可被同類型的應用所訪問;即32位應用程序所創建的共享內存區只可被其它的32位應用程序訪問,同樣地,64位應用程序所創建的共享內存區只可被其它的64位應用程序訪問。

如果,32位應用企圖訪問一個由64位應用創建的共享內存區,則會在調用shmget時失敗,得到EINVAL錯誤碼,其解釋是:

A shared memory identifIEr exists for key but is in 64-bit address space and the process performing the request has been compiled as a 32-bit executable.

解決這一問題的方法是,當64位應用創建共享內存時,合并IPC_CREAT標志,同時給定IPC_SHARE32標志:

shmget(mem_key, size, 0666 | IPC_CREAT | IPC_SHARE32)

對于32位應用,沒有設定IPC_SHARE32標志的要求,但設置該標志并不會帶來任何問題,也就是說無論應用程序將被編譯為32位還是64位模式,都可采用如上相同的代碼;并且由此解決32位應用和64位應用在共享內存訪問上的兼容性問題。

4.2 對同一共享內存的連接數限制

在HP-UX上,應用進程對同一個共享內存區的連接次數被限制為最多1次;區別于上面第3節所介紹的AIX上的連接數限制,HP-UX并未對指向不同共享內存區的連接數設置上限,也就是說,運行在HP-UX上的應用進程可以同時連接很多個不同的共享內存區,但對于同一個共享內存區,最多只允許連接1次;否則,shmat調用將失敗,返回錯誤碼EINVAL,在shmat的man幫助中,對該錯誤碼有下列解釋:

shmid is not a valid shared memory identifier, (possibly because the shared memory segment was already removed using shmctl(2) with IPC_RMID), or the calling process is already attached to shmid.

這個限制會對多線程應用帶來無法避免的問題,只要一個應用進程中有超過1個以上的線程企圖連接同一個共享內存區,則都將以失敗而告終。

解決這個問題,需要修改應用程序設計,使應用進程具備對同一共享內存的多線程訪問能力。相對于前述問題的解決方法,解決這個問題的方法要復雜一些。

作為可供參考的方法之一,以下介紹的邏輯可以很好地解決這個問題:

基本思路是,對于每一個共享內存區,應用進程首次連接上之后,將其鍵值(ftok的返回值)、系統標識符(shmid,shmget調用的返回值)和訪問地址(即shmat調用的返回值)保存下來,以這個進程的全局數組或者鏈表的形式留下記錄。在任何對共享內存的連接操作之前,程序都將先行檢索這個記錄列表,根據鍵值和標志符去匹配希望訪問的共享內存,如果找到匹配記錄,則從記錄中直接讀取訪問地址,而無需再次調用shmat函數,從而解決這一問題;如果沒有找到匹配目標,則調用shmat建立連接,并且為新連接上來的共享內存添加一個新記錄。

記錄條目的數據結構,可定義為如下形式:

typedef struct _Shared_Memory_Record{key_tmem_key;// key generated by ftok()intmem_id;// id returned by shmget()void*mem_addr;// access address returned by shmat()intnattach;// times of attachment} Shared_Memory_Record;

其中,nattach成員的作用是,記錄當前對該共享內存區的連接數目;每一次打開共享內存的操作都將對其進行遞增,而每一次關閉共享內存的操作將其遞減,直到nattach的數值降到0,則對該共享內存區調用shmdt進行真正的斷開連接。

打開共享內存的邏輯流程可參考如下圖一:

圖一

關閉共享內存的邏輯流程可參考如下圖二:

圖二

5. Solaris中的shmdt函數原型問題

Solaris系統中的shmdt調用,在原型上與System V標準有所不同,

Default int shmdt(char *shmaddr);

即形參shmaddr的數據類型在Solaris上是char *,而System V定義的是void * 類型;實際上Solaris上shmdt調用遵循的函數原型規范是SVID-v4之前的標準;以Linux系統為例,libc4和libc5 采用的是char * 類型的形參,而遵循SVID-v4及后續標準的glibc2及其更新版本,均改為采用void * 類型的形參。

如果仍在代碼中采用System V的標準原型,就會在Solaris上編譯代碼時造成編譯錯誤;比如:

Error: Formal argument 1 of type char* in call to shmdt(char*)is being passed void*.

解決方法是,引入一個條件編譯宏,在編譯平臺是Solaris時,采用char * 類型的形參,而對其它平臺,均仍采用System V標準的void * 類型形參,比如:

#ifdef _SOLARIS_SHARED_MEMORYshmdt((char *)mem_addr);#else shmdt((void *)mem_addr);#endif

6. 通過shmctl刪除共享內存的風險

當進程斷開與共享內存區的連接后,一般通過如下代碼刪除該共享內存:

shmctl(mem_id, IPC_RMID, NULL);

從HP-UX上shmctl函數的man幫助,我們可以看到對IPC_RMID操作的說明:

IPC_RMID Remove the shared memory identifier specified by shmid from the system and destroy the shared memory segment and data structure associated with it. If the segment is attached to one or more processes, then the segment key is changed to IPC_PRIVATE and the segment is marked removed. The segment disappears when the last attached process detaches it.

其它UNIX平臺也有類似的說明。關于shmctl的IPC_RMID操作,其使用特點可簡述如下:

如果共享內存已經與所有訪問它的進程斷開了連接,則調用IPC_RMID子命令后,系統將立即刪除共享內存的標識符,并刪除該共享內存區,以及所有相關的數據結構;

如果仍有別的進程與該共享內存保持連接,則調用IPC_RMID子命令后,該共享內存并不會被立即從系統中刪除,而是被設置為IPC_PRIVATE狀態,并被標記為"已被刪除";直到已有連接全部斷開,該共享內存才會最終從系統中消失。

于是,存在這樣的一種狀態:

N個進程(進程1至進程N)已經與某共享內存區連接;

進程1已完成對此共享內存的操作,斷開連接后,調用shmctl的IPC_RMID子命令,企圖刪除該共享內存;

由于進程2至進程N仍保持與該共享內存的連接,因此在它們全部斷開連接之前,這個共享內存區毫無疑問地會依然存在。

此時,如果有其它的進程(比如第N+1號進程)想建立對這個共享內存的連接,是否能夠成功呢?

類似的狀態,在Windows上同樣存在,只是程序借助的API有所不同,比如通過CreateFileMapping函數創建共享內存,通過MapViewOfFile函數建立連接,通過UnmapViewOfFile函數斷開連接,通過CloseHandle函數刪除共享內存等。在Windows上,對此問題的回答是肯定的;也就是說,只要共享內存依然存在,則進程總是可以建立對它的連接,而無論之前是否有進程對其執行過刪除操作。

然而,對于包括AIX、Solaris、HP-UX等在內的UNIX平臺,答案卻是否定的!這也正是本節所討論的使用shmctl中的風險所在;通過以下test03.P1.c和test03.P2.c兩個例程,我們可以很直觀地得到答案:

test03.P1.c: 創建共享內存,并建立連接,保持10秒后(在此期間,test03.P2將反復連接、并刪除該共享內存),斷開連接,并最后再次嘗試連接以驗證該共享內存是否已被真正刪除;

test03.P2.c: 反復連接由test03.P1創建的共享內存,并在期間通過shmctl的IPC_RMID 子命令刪除該共享內存,以觀察共享內存被執行刪除操作之后,在被徹底銷毀之前是否還能接受連接;

/******* test03.P1.c ********/#include <stdio.h>#include <unistd.h>#include <errno.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/shm.h>int main(int argc, char* argv[]){key_t  mem_key;long mem_id;void* mem_addr;intisAttached = 0;mem_key = ftok("/tmp/mykeyfile", 1);mem_id = shmget(mem_key, 256, IPC_CREAT);if ( ( mem_addr = (void *)shmat(mem_id, 0, 0) ) == (void *)(-1) ) printf("%s, Failed to attach shared memory, errno:%dn", argv[0], errno);else {isAttached = 1;printf("%s, +.Successfully attached shared memoryn", argv[0]);  }/* sleep 10 seconds, to wait test03.P2 to run */sleep(10);if (isAttached) {// Attention: the following line should be "shmdt((char *)mem_addr);" ifon Solarisshmdt((void *)mem_addr);printf("%s, -.Successfully detached shared memoryn", argv[0]);}/* try to attach the shared memory which has been removed! */if ( ( mem_addr = (void *)shmat(mem_id, 0, 0) ) == (void *)(-1) )printf("%s, Failed to attach the removed shared memory, errno:%dn",argv[0], errno); return 0;}/******* test03.P2.c ********/#include <stdio.h>#include <errno.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/shm.h>int main(int argc, char* argv[]){key_t mem_key;  long  mem_id;void*  mem_addr;inti, isAttached;mem_key = ftok("/tmp/mykeyfile", 1);mem_id = shmget(mem_key, 0, 0);// repeated attaching & detachingfor (i=1; i<10; i++) {isAttached = 0;if ( ( mem_addr = (void *)shmat(mem_id, 0, 0) ) == (void *)(-1) )printf("%s, Failed to attach shared memory, times [%02d],errno:%dn", argv[0], i, errno);  else {  isAttached = 1; printf("%s, +.Successfully attached shared memory, times[%02d]n",argv[0], i);}  if (isAttached) { // Attention: the following line should be "shmdt((char*)mem_addr);", if on Solarisshmdt((void *)mem_addr);  printf("%s, -.Successfully detached, times [%02d]n", argv[0], i);  }// purposely remove the shared memory at times [5]if (i==5) {shmctl(mem_id, IPC_RMID, NULL);printf("%s, *.Remove executed, times [%02d], errno=%dn",argv[0], i, errno);}}return 0;}

上述程序均可在AIX、HP-UX、Linux平臺上編譯通過;在Solaris平臺上只需按注釋提示的要求,將shmdt的參數強制為char *類型也可編譯通過(第5節中已介紹過)。

將test03.P1.c、test03.P2.c各自編譯為可執行程序test03.P1、test03.P2,并通過下面的shell腳本:runtest,運行它們:

#!/bin/sh./test03.P1&sleep 2./test03.P2

在Linux平臺(Red Hat 8.0)上的運行結果如下:

[root@localhost tmp]# ./runtest./test03.P1, +.Successfully attached shared memory./test03.P2, +.Successfully attached shared memory, times [01]./test03.P2, -.Successfully detached, times [01]./test03.P2, +.Successfully attached shared memory, times [02]./test03.P2, -.Successfully detached, times [02]./test03.P2, +.Successfully attached shared memory, times [03]./test03.P2, -.Successfully detached, times [03]./test03.P2, +.Successfully attached shared memory, times [04]./test03.P2, -.Successfully detached, times [04]./test03.P2, +.Successfully attached shared memory, times [05]./test03.P2, -.Successfully detached, times [05]./test03.P2, *.Remove executed, times [05], errno=0./test03.P2, +.Successfully attached shared memory, times [06]./test03.P2, -.Successfully detached, times [06]./test03.P2, +.Successfully attached shared memory, times [07]./test03.P2, -.Successfully detached, times [07]./test03.P2, +.Successfully attached shared memory, times [08]./test03.P2, -.Successfully detached, times [08]./test03.P2, +.Successfully attached shared memory, times [09]./test03.P2, -.Successfully detached, times [09][root@localhost tmp]# ./test03.P1, -.Successfully detached shared memory./test03.P1, Failed to attach the removed shared memory, errno:22

根據運行結果,我們可以看到,在Linux平臺上,即便對共享內存執行了刪除操作(在第5次連接之后,test03.P2進程調用了shmctl的IPC_RMID刪除操作),只要該共享內存依然存在(test03.P1進程保持著連接,因此共享內存不會被立即刪除),則它仍然是可連接的(test03.P2進程的第6到第9次連接均是成功的)。

然而,在AIX、HP-UX、Solaris平臺上的運行結果卻不同于Linux:

# ./runtest./test03.P1, +.Successfully attached shared memory./test03.P2, +.Successfully attached shared memory, times [01]./test03.P2, -.Successfully detached, times [01]./test03.P2, +.Successfully attached shared memory, times [02]./test03.P2, -.Successfully detached, times [02]./test03.P2, +.Successfully attached shared memory, times [03]./test03.P2, -.Successfully detached, times [03]./test03.P2, +.Successfully attached shared memory, times [04]./test03.P2, -.Successfully detached, times [04]./test03.P2, +.Successfully attached shared memory, times [05]./test03.P2, -.Successfully detached, times [05]./test03.P2, *.Remove executed, times [05], errno=0./test03.P2, Failed to attach shared memory, times [06], errno:22./test03.P2, Failed to attach shared memory, times [07], errno:22./test03.P2, Failed to attach shared memory, times [08], errno:22./test03.P2, Failed to attach shared memory, times [09], errno:22# ./test03.P1, -.Successfully detached shared memory./test03.P1, Failed to attach the removed shared memory, errno:22

根據結果,可以發現,test03.P2進程的第6到第9次連接都是失敗的,也就說明,在AIX、HP-UX、Solaris平臺上一旦通過shmctl對共享內存進行了刪除操作,則該共享內存將不能再接受任何新的連接,即使它依然存在于系統中!

而且,上面的運行結果,也證明了,對共享內存進行了刪除操作之后,當已有的連接全部斷開,該共享內存將被系統自動銷毀(運行結果的最后一行,說明該共享內存已經不存在了)。

本節的目的在于說明,在AIX、HP-UX、Solaris平臺上調用shmctl的IPC_RMID刪除操作,是存在潛在風險的,需要足夠的謹慎。

如果,可以確知,在刪除之后不可能再有新的連接,則執行刪除操作是安全的;

否則,在刪除操作之后如仍有新的連接發生,則這些連接都將失??!

7. 結論

對共享內存的操作,往往是產品或者應用中數據傳輸的基礎,對其可靠性和性能至關重要;而且作為底層的IPC機制,相關代碼具有不易調試的特點,由其造成的問題往往關鍵卻不容易解決。

本文從應用實現的角度上,對在UNIX/Linux平臺上使用共享內存可能會遇到的問題,進行了全面的介紹和分析,并給出了解決方法或建議,可供相關的應用開發人員參考。

標簽: Unix系統
主站蜘蛛池模板: 欧美 亚洲 一区 | 中文字幕日韩欧美一区二区三区 | 国产一区二区三区免费在线观看 | 91午夜激情| 久久99国产精品免费网站 | 欧美日本亚洲 | 久草视频在线播放 | 中文字幕黄色 | 成人免费视频网 | 亚洲午夜精品 | 4h影视| 欧美成人一级 | 99精品视频在线 | jav成人av免费播放 | 色偷偷噜噜噜亚洲男人 | 91精品国产免费 | 狠狠狠干| 国产乱码精品一区二区三区忘忧草 | 精品一区二区久久久久久久网站 | 成人欧美一区二区三区白人 | 人人干操 | www.久草.com| 午夜午夜精品一区二区三区文 | 精品一区二区三区免费毛片爱 | 中文字幕国产在线视频 | 亚洲欧洲一区二区 | 日韩精品一91爱爱 | 老汉色影院 | www.亚洲成人网 | 三区影院 | 偷拍呻吟高潮91 | 午夜羞羞 | 99re在线 | 欧美欧美欧美 | 国产 日韩 欧美 中文 在线播放 | www久久精品 | 可以看的毛片网站 | 国产精品日日做人人爱 | 国产一级特黄视频 | 久久免费99精品久久久久久 | 人人看超碰 | 波多野结衣一区在线观看 | 免费av大全| 日韩欧美在线观看视频网站 | 91午夜精品 | 色婷婷一区二区三区 | 日韩视频在线观看一区二区 | 日韩一级二级三级 | 日本中文字幕一区 | 久久精品一 | 日本午夜视频 | 亚洲精品国产乱码在线看蜜月 | 可以在线观看的黄色 | 日本五月婷婷 | 福利视频网站 | 最近中文字幕在线视频1 | 性做久久久久久久免费看 | 国产黄色播放 | 国产精品日韩欧美一区二区三区 | 日韩大尺度在线观看 | 精品久久久av | 日本理论片好看理论片 | www.狠狠干 | 日韩一区二区在线观看 | 超碰3| 国产精彩视频 | 久久在线视频 | 理论片87福利理论电影 | 欧美久久久久久久 | 日本免费www| 精品欧美一区二区三区久久久 | 天天干在线影院 | 久久久艹 | 色综合久久久久 | 国产在线91 | 欧美日韩中文在线观看 | 亚洲视频自拍 | 亚洲免费资源 | 国产日韩高清在线 | 日日干夜夜干 | 国产欧美在线 | 色综合天天| 久久精品一区二区三区四区毛片 | 免费高潮视频95在线观看网站 | 久久91精品 | av一级毛片 | 国产高清精 | 久久久久久久中文 | 精品国产综合 | 国产一区二区欧美 | 久久精品国产一区二区电影 | 美女扒开内裤让男人桶 | 国产精品久久嫩一区二区免费 | 欧美精品区 | 青草视频在线免费观看 | 国产成人精品亚洲日本在线观看 | 久久中文字幕一区 | 色小妹三区 | 四虎成人在线视频 | 国产浪潮av色综合久久超碰 | 欧洲精品一区二区 | 日韩在线观看 | 黄色免费观看 | 国产最新精品视频 | 特黄色一级片 | 国产精品色婷婷久久58 | 午夜影院a | 欧美激情久久久 | 日本a在线 | 欧美一区第一页 | 精品成人免费一区二区在线播放 | 精品免费一区 | a视频在线免费观看 | 九九综合九九 | 亚洲欧洲在线观看 | 羞视频在线观看 | 日韩在线中文字幕 | 久在线 | 日本不卡高字幕在线2019 | 免费v片| 久久国产精品一区二区 | 欧美中文字幕在线观看 | 久久国产传媒 | 欧美激情一区 | 99精品一级欧美片免费播放 | 国产精品主播 | 一区二区三区国产精品 | 亚洲人成网站999久久久综合 | 欧美日韩亚洲国内综合网 | 精品国产色| 欧美精品一区二区三区蜜臀 | 国产精品25p | 国产精品久久久久久久久免费桃花 | 亚洲二区在线播放 | 精品国产黄色片 | 成人在线视频免费观看 | 欧洲妇女成人淫片aaa视频 | 色呦呦网站在线观看 | 鲁管视频| 成人亚洲黄色 | 日韩精品一区二区三区在线观看 | 国产精品丝袜视频 | 女同久久| 国产一级黄色大片 | 日韩中文字幕在线 | 亚洲成人在线观看视频 | 国产精品乱码一区二区三区 | 欧美二区精品 | 国产欧美在线一区二区 | 国产a√ | 精品一区二区三区免费毛片爱 | 五月婷婷色 | 波多野结衣 一区二区 | 99视频| 亚洲免费一区 | 视频一区 国产精品 | 欧美午夜精品久久久久免费视 | 国产激情91久久精品导航 | 在线一区二区三区做爰视频网站 | 国产精品久久久久久久久久久久久 | 亚洲成人免费网址 | 91在线免费观看 | 成人精品视频 | 中国一级特黄毛片大片 | 日韩在线视频一区 | 国产精品久久久久久吹潮 | 国产精品美女久久久久久久久久久 | 国产一区二区三区免费观看 | 亚洲视频一区在线 | 一区二区久久 | 黄p在线看| 国产视频一视频二 | 国产在线中文字幕 | 日日摸天天爽天天爽视频 | a级毛片免费高清视频 | 91精彩视频在线观看 | 看毛片网站 | 久草网站| 中文字幕精品一区 | 欧美午夜视频 | 天天干干干干 | 我要看a级毛片 | 午夜精品久久久久久久久 | 日韩欧美高清视频 | 一级片在线免费看 | 亚洲国产欧美在线 | 精品久久久久国产 | 一区二区日本 | 国产精品久久久麻豆 | 精品一区二区三区免费毛片爱 | 亚洲一区国产精品 | 国产精品久久久久久亚洲调教 | 日韩成人高清视频 | 精品一区二区久久久久久久网站 | 狠狠ri| 日本黄色片免费看 | 国产精品久久久久久妇女6080 | 国产精品久久久久久久久免费桃花 | 欧美精产国品一二三区 | 中文字幕高清av | 成人黄页在线观看 | 欧美激情综合色综合啪啪五月 | 久久高清亚洲 | 91精品久久久久久综合五月天 | 国内精品视频一区二区三区 | 91精品国产综合久久福利软件 | 色综合久久88色综合天天 | 91综合网| 91精品一区二区 | 国产激情偷乱视频一区二区三区 | 色人久久 | 久久久久久99精品 | 亚洲色图p | 美女天堂| 看羞羞视频免费 | 国产2区| 欧美狠狠操 | 国产98色在线 | 日韩 | 国产一级毛片在线视频 | 成人一区二区三区在线观看 | 黄视频入口| 亚洲精品午夜国产va久久成人 | 久久国产一区二区 | 久久精品免费观看视频 | 久久久久久精 | 国产美女网站 | 一区久久| 91电影在线看 | av黄色一级片 | 天堂一区二区三区 | 在线观看av网站永久 | 91精品国产综合久久久久久丝袜 | 亚洲精品成人a8198a | 国产99久久久久久免费看农村 | 亚洲一区久久久 | 欧美日韩视频一区二区 | 97在线观看| 欧美日韩一区二区在线 | 亚洲aaaaaa特级 | 在线 亚洲 欧美 | 在线视频 欧美日韩 | 久久99国产精品久久99大师 | 色婷婷国产精品久久包臀 | 欧美啪| 黄色大片网站在线观看 | 精品自拍视频 | 亚洲欧美另类在线 | 日本三级做a全过程在线观看 | 国产精品99久久久久久宅男 | 91精品国产综合久久福利软件 | 91午夜伦伦电影理论片 | 亚洲久视频 | 先锋av资源在线 | 国产大片黄色 | 色伊人网| 日韩av资源站| 福利片在线观看 | 亚洲综合在线一区 | 日韩成人一区二区 | 一区二区三区四区视频 | 日韩专区视频 | 久热精品在线视频 | 美国一级毛片a | 日韩在线视频免费看 | 亚洲成年人网站在线观看 | 一区在线视频观看 | 中文字幕一页二页 | 懂色一区二区三区av片 | 亚洲网站视频 | 99精品国产在热久久 | 91精品福利 | 日韩三级电影免费观看 | 天天插天天操天天干 | 亚洲精品在线视频 | 中文字幕乱码亚洲精品一区 | 国产精品久久久一区二区 | www久久九| 天天操天天舔 | 日韩中文在线视频 | 精品96久久久久久中文字幕无 | 黄色精品视频 | 午夜午夜精品一区二区三区文 | 欧美色视 | 浴室洗澡偷拍一区二区 | 国产高清精品一区二区三区 | 日韩精品专区在线影院重磅 | 伊人网网站 | 亚洲精品久久久久久久久久久久久 | 伊人短视频 | 亚洲一区日韩 | 天堂资源网 | 国产精品久久久久久久久久久新郎 | 美女午夜影院 | 午夜在线 | 国产在线中文字幕 | 成人三级av | 欧美精品在线不卡 | 欧美精品一区二区三区免费视频 | 亚洲女人天堂成人av在线 | 日本久久精品视频 | 亚洲+变态+欧美+另类+精品 | 一区二区三区久久 | 一区久久| 国产精品美女视频一区二区三区 | 不卡在线 | 中文成人无字幕乱码精品 | 日韩一级视频 | 免费高潮视频95在线观看网站 | 日本福利视频网 | 精品一区二区视频 | 综合伊人| 91亚洲精品在线观看 | 中文字幕久久精品 | 国产精品1区2区 | 久久精品99国产精品亚洲最刺激 | 一区二区三区四区免费观看 | 成年免费观看视频 | 亚洲特级 | 成人a在线 | 91亚洲高清 | 男人天堂视频在线观看 | 免费黄色在线看 | 伊人久操 | 九九热这里只有精品6 | 黄网在线 | 久久综合九色综合欧美狠狠 | 久久国产精品久久精品 | 色爱综合| 久久99国产一区二区三区 | 美女久久久久 | 国产视频综合在线 | 午夜视频网 | 亚洲一区播放 | 在线99视频| 亚洲免费一区二区 | 2018天天操夜夜操 | 日本a网 | 特级毛片在线 | 欧美aaa大片| 国产v日产∨综合v精品视频 | 久久久久久久一区 | 中文字幕av一区二区三区免费看 | 午夜影院免费 | 男女羞羞视频免费在线观看 | 国产成人精 | www,99热| 日韩免费高清视频 | 81精品国产乱码久久久久久 | 在线欧美色| 国产高清一区二区三区 | 国产日韩欧美视频 | 天天久久 | 成人免费crm在线观看 | 久久久精品国产 | 欧美lesbianxxxxhd视频社区 | 欧美一区二区在线 | 日韩亚洲在线 | 国产精品视频 | 精品91久久久 | 国产精品久久久久久久久久 | 99re在线观看 | 国产aaa毛片 | 欧美在线观看一区 | 亚洲综合久久网 | 日韩一区免费在线观看 | 九一在线观看 | 天天拍天天干天天操 | 欧美成人精品一区二区三区在线看 | 欧美久久精品一级c片 | 精品国产影院 | 国产小视频在线观看 | 精品视频一区二区三区在线观看 | 亚洲精品成人 | 成人水多啪啪片 | 久久久久亚洲精品国产 | 久久99国产精品 | 亚洲码欧美码一区二区三区 | 日韩aaa视频| 亚洲国产成人在线 | 久久av一区二区三区亚洲 | 国产不卡在线视频 | www.五月婷| 亚洲色图一区二区三区 | 玖玖免费 | 波多野结衣中文字幕在线视频 | 1000部精品久久久久久久久 | 亚洲高清视频一区 | 91精品久久久久久久久久入口 | 午夜视频网站 | 亚洲精品99 | 久久精品首页 | 欧美视频在线播放 | 日本精品一区二区三区在线观看视频 | 国产乱码精品一区二区三区中文 | 成人影院欧美黄色 | 激情久久久 | 草樱av | 欧美一区二区三区在线 | 成人精品一区 | 久久丁香 | 99久久久久国产精品免费 | 成人国产在线 | 在线观看国产视频 | 欧美视频精品在线 | 天天舔天天干 | av一二三四 | 国产精品成人国产乱一区 | 96自拍视频 | 久久最新网址 | 日韩精品在线视频 | 国产高清在线精品一区二区三区 | 国产精品视频久久 | 亚洲va中文字幕 | 国产色| 一区二区视频 | 久久久在线视频 | 久久久性色精品国产免费观看 | 成人小视频在线观看 | 国产在线精品视频 | 欧美视频区 | 成人午夜视频在线观看 | 色综合视频 | 狠狠躁夜夜躁人人爽视频 | 欧美日韩一区二区三区在线观看 | 天天久久综合网 | 天天影视综合 | 国产精品美女久久久久久久久久久 | 狠狠人人 | 国产精品亚洲一区二区三区在线 | 亚洲自拍一区在线 | 久久久久九九九九 | 国产成人免费视频网站高清观看视频 | www91在线观看 | 91免费在线视频 | 精品国产区 | 日韩在线精品强乱中文字幕 | 国产精品久久久 | 一区二区在线影院 | 国产性猛交xxxx免费看久久 | 国产精品久久国产精品99 gif | 欧美黄色网 | 免费观看一区二区三区毛片 | 午夜天 | 一级a性色生活片久久毛片明星 | 色视频网站在线观看 | 欧美性一区二区 | 亚洲91 | 亚洲区国产区 | 啪啪的网站 | 国产精品国产a级 | 伊人午夜 | 国产美女久久久 | 欧美成人黑人xx视频免费观看 | 91精品国产综合久久福利软件 | 久久久www | 日韩免费一区 | 国产成人精品免高潮在线观看 | 精品久| 伊人av在线免费观看 | 国产日韩欧美视频 | 一级a毛片 | 日本成人中文字幕 | 免费观看羞羞视频网站 | 一区视频 | 欧美日韩激情 | sis色中色| 精品久久久久一区二区国产 | 午夜久久久 | 国产精品自产拍在线观看 | 一级全黄少妇性色生活片免费 | 国产精品久久久久久久久免费桃花 | 午夜免费视频 | 日韩精品 | 在线成人国产 | 日比视频网站 | 日韩高清一区 | 黄色一级免费看 | 奇米av | 麻豆精品一区二区 | 日本不卡一区二区 | 亚洲欧美国产精品久久 | 精品国产污网站污在线观看15 | 欧美日韩国产一区二区 | 日韩免费视频中文字幕 | 久久人人爽人人爽人人片亚洲 | 91久久国产 | 国产精品色在线网站 | 日韩欧美在线观看一区二区三区 | 欧美日韩91| 免费国产在线视频 | 最新中文字幕在线 | 色av色av色av | 久热av在线 | 亚洲成人精品av | 日本免费一区二区三区 | 欧美日韩精品久久久 | 免费看的毛片 | 日韩欧美国产精品综合嫩v 亚洲欧美日韩在线 | 日本福利网站 | 视频一区二区三区在线播放 | 中文字幕日韩一区二区 | www久久99 | 黄色一级免费观看 | 91激情视频 | 欧洲精品一区 | 国产亚洲精品久 | 国产高清精品一区二区三区 | 4hu网站| 一区二区免费在线播放 | 午夜精品久久久久久久99黑人 | 欧美精品1区2区 | 久久久久久国产精品 | 国产精品成人国产乱一区 | 天天影视网色香欲综合网无拦截 | 久久爱综合网 | 国产精品毛片一区二区三区 | 欧美成年网站 | 日韩精品中文字幕在线观看 | 黄篇网址 | 欧美一级艳情片免费观看 | 久久久久久国产精品 | 国产亚洲一区二区精品 | 国产精品久久国产精品 | 欧美精品色网 | 盗摄精品av一区二区三区 | 亚洲精品一区二区三区 | 亚洲精品99| 国产人成精品一区二区三 | 免费国产一区 | 麻豆国产一区二区三区四区 | 桃色视频在线播放 | 久久精品这里热有精品 | 精品在线看 | 欧美福利在线观看 | 中文字幕一区在线 | 福利亚洲| 日韩国产精品视频 | 亚洲午夜精品a | 午夜视频网 | 九九热在线视频免费观看 | 久久久精| 久久黄色网 | 成人免费aaa| 黄色天堂在线观看 | 北条麻妃国产九九九精品小说 | av天天干| 久久国产精品精品国产 | 成人在线看片 | 小草av| 午夜精品久久久久久久久 | 亚洲国产精品久久久久秋霞蜜臀 | 国产高清免费视频 | 久久美女视频 | 欧美精三区欧美精三区 | 日韩久久久久久 | 黄色在线观看网址 | 亚洲777 | 国产精品国产成人国产三级 | 欧美极品视频 | 国产精品久久久久久久午夜 | 一级毛片电影 | 日韩一级| 欧美一区永久视频免费观看 | 中文字幕一二三 | 精品久久久久久亚洲精品 | 自拍偷拍欧美 | 毛片入口 | 天天看天天爽 | 99久久精品一区二区 | 一区二区在线 | 欧美乱轮 | 天天操天天碰 | 欧美啪啪一区二区 | 亚洲一区二区三区欧美 | 欧美一区二区三区黄 | 久久综合久久综合久久 | 中文字幕一区二区三区四区 | 欧美日韩亚洲国产 | 欧美一区二区另类 | 日韩中文字幕在线观看 | 国产成人av网站 | 四虎影视免费在线观看 | 久久久精品国产 | 精品一区二区三区久久 | 国产男女爽爽爽免费视频 | 国产精品久久久久久久午夜 | 综合久久99 | 中国大陆高清aⅴ毛片 | 久久中文字幕一区 | 午夜在线视频 | xxxx性欧美| 色婷婷在线视频 | 久久国产高清 | 亚洲综合在线一区 | 欧美精品xx | 国产在线观看一区二区 | 日韩午夜影院 | 国产成人精品电影 | 三区在线 | 男人的天堂久久精品 | 亚洲a在线播放 | 国产精品三级久久久久久电影 | 麻豆视频国产 | 国产不卡在线视频 | 91精品国产91久久久久久蜜臀 | 欧美一区二区三 | 欧美日韩在线免费观看 | 欧美肉体xxxx肉交高潮 | 中文字幕一区二区三区在线视频 | 中文字幕高清视频 | 一本大道久久a久久精二百 亚洲欧美高清 | 亚洲综合色视频在线观看 | 国产日本韩国在线 | 欧美日韩国产影院 | 国产精品99久久久久 |