亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁(yè) > 開(kāi)發(fā) > PHP > 正文

php腳本運(yùn)行時(shí)的超時(shí)機(jī)制詳解

2024-05-04 23:43:06
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
在我們平常的開(kāi)發(fā)中,也許曾經(jīng)都遇到過(guò)PHP腳本運(yùn)行超時(shí)的情況,當(dāng)遇到這種情況我們經(jīng)常會(huì)通過(guò)使用 set_time_limit(非安全模式),或修改配置文件并重啟服務(wù)器,或者修改程序減少程序的執(zhí)行時(shí)間,使其在允許的范圍之內(nèi),以解決此問(wèn)題。
 

在做php開(kāi)發(fā)的時(shí)候,經(jīng)常會(huì)設(shè)置max_input_time、max_execution_time,用來(lái)控制腳本的超時(shí)時(shí)間。但卻從來(lái)沒(méi)有思考過(guò)背后的原理。

趁著這兩天有空,研究一下這個(gè)問(wèn)題。

超時(shí)配置

php的ini配置如何起作用,這是一個(gè)老生常談的話題了。

首先,我們?cè)趐hp.ini里進(jìn)行配置。當(dāng)php啟動(dòng)的時(shí)候(php_module_startup階段),會(huì)嘗試讀取ini文件并解析。解析過(guò)程簡(jiǎn)單來(lái)說(shuō),是分析ini文件,提取出其中合法的鍵值對(duì),并保存到configuration_hash表。

OK,然后php會(huì)進(jìn)一步調(diào)用zend_startup_extensions來(lái)啟動(dòng)各個(gè)模塊(包含php Core模塊,以及所有需要加載的擴(kuò)展)。各個(gè)模塊的啟動(dòng)函數(shù)中,會(huì)完成REGISTER_INI_ENTRIES動(dòng)作。REGISTER_INI_ENTRIES負(fù)責(zé)將模塊對(duì)應(yīng)的一些配置從configuration_hash表取出,然后調(diào)用處理函數(shù),最終將處理完的值存入模塊的globals變量。

max_input_time、max_execution_time這兩個(gè)配置屬于php Core模塊。對(duì)于php Core來(lái)說(shuō),REGISTER_INI_ENTRIES依然發(fā)生在php_module_startup中。同樣屬于php Core模塊的配置還有expose_php、display_errors、memory_limit等等...

示意圖如下:

---->php_module_startup----------->php_request_startup---->    |    |    |-->REGISTER_INI_ENTRIES    |    |    |-->zend_startup_extensions    |     |    |     |-->zm_startup_date    |     |     |-->REGISTER_INI_ENTRIES    |     |    |     |-->zm_startup_json    |     |     |-->REGISTER_INI_ENTRIES    |    |    |-->do otherthings

上面說(shuō)到對(duì)于不同的配置,REGISTER_INI_ENTRIES會(huì)調(diào)用不同的函數(shù)來(lái)處理。我們直接來(lái)看max_execution_time對(duì)應(yīng)的函數(shù):

static PHP_INI_MH(OnUpdateTimeout){  // php啟動(dòng)階段走這里  if (stage == PHP_INI_STAGE_STARTUP) {    // 將超時(shí)設(shè)置保存到EG(timeout_seconds)中    EG(timeout_seconds) = atoi(new_value);    return SUCCESS;  }   // php執(zhí)行過(guò)程中的ini set則走這里  zend_unset_timeout(TSRMLS_C);  EG(timeout_seconds) = atoi(new_value);  zend_set_timeout(EG(timeout_seconds), 0);  return SUCCESS;}

暫時(shí)只看上半截,因?yàn)槲覀兡壳爸恍桕P(guān)注php的啟動(dòng)階段,該函數(shù)行為很簡(jiǎn)單,將max_execution_time存入了EG(timeout_seconds)。

至于max_input_time,并沒(méi)有特殊的處理函數(shù),默認(rèn)是會(huì)將max_input_time存入存入PG(max_input_time)。

因此,當(dāng)REGISTER_INI_ENTRIES完成,發(fā)生的是:

max_execution_time ----> 存入EG(timeout_seconds)

max_input_time       ----> 存入PG(max_input_time)

請(qǐng)求超時(shí)控制

現(xiàn)在我們搞清楚php的啟動(dòng)階段發(fā)生了什么,繼續(xù)來(lái)看php在實(shí)際處理請(qǐng)求的時(shí)候,如何管理超時(shí)。

在php_request_startup函數(shù)中有如下代碼:

if (PG(max_input_time) == -1) {  zend_set_timeout(EG(timeout_seconds), 1);} else {  zend_set_timeout(PG(max_input_time), 1);}

php_request_startup的時(shí)機(jī)很講究。

以cgi為例,只有當(dāng)php已經(jīng)從CGI拿到了原始請(qǐng)求以及一些CGI的環(huán)境變量之后,php_request_startup才會(huì)被調(diào)用。上面這段代碼實(shí)際執(zhí)行的時(shí)候,由于請(qǐng)求已經(jīng)拿到,所以SG(request_info)處于準(zhǔn)備就緒狀態(tài),但是php中的$_GET,$_POST,$_FILE等超全局變量尚未生成。

從代碼上理解:

1、如果用戶將max_input_time配做-1,或沒(méi)有配置,那么腳本的生命周期就只受EG(timeout_seconds)約束。

2、否則,請(qǐng)求啟動(dòng)階段的超時(shí)控制,受PG(max_input_time)約束。

3、zend_set_timeout函數(shù)負(fù)責(zé)設(shè)置定時(shí)器。一旦指定時(shí)間過(guò)去,定時(shí)器會(huì)通知php進(jìn)程。zend_set_timeout下文會(huì)具體分析。

php_request_startup完成,則進(jìn)入php的實(shí)際執(zhí)行階段,即php_execute_script。在php_execute_script中可以看到:

// 設(shè)定執(zhí)行超時(shí)if (PG(max_input_time) != -1) {#ifdef PHP_WIN32  zend_unset_timeout(TSRMLS_C); // 關(guān)閉之前的定時(shí)器#endif  zend_set_timeout(INI_INT("max_execution_time"), 0);} // 進(jìn)入執(zhí)行retval = (zend_execute_scripts(ZEND_REQUIRE TSRMLS_CC, NULL, 3, prepend_file_p, primary_file, append_file_p) == SUCCESS);

OK,假如代碼執(zhí)行到這里,尚未發(fā)生max_input_time超時(shí),則會(huì)重新指定max_execution_time的超時(shí)。

同樣也是采取調(diào)用zend_set_timeout,并傳入max_execution_time。特別注意一下,windows下面的需要顯式調(diào)用zend_unset_timeout關(guān)閉原來(lái)的定時(shí)器,而linux下不需要。這是由于兩個(gè)平臺(tái)的定時(shí)器實(shí)現(xiàn)原理不同導(dǎo)致的,下文也會(huì)詳細(xì)展開(kāi)敘述。

最后用一張圖表示超時(shí)控制的流程,左側(cè)的case表明用戶既配置了max_input_time,又配置了max_execution_time。而右側(cè)的區(qū)別在于用戶僅僅配置了max_execution_time:

php腳本運(yùn)行時(shí)的超時(shí)機(jī)制詳解

zend_set_timeout

前文提到,zend_set_timeout函數(shù)用來(lái)設(shè)置定時(shí)器。具體來(lái)看下實(shí)現(xiàn):

void zend_set_timeout(long seconds, int reset_signals) /* {{{ */{  TSRMLS_FETCH();   // 賦值  EG(timeout_seconds) = seconds; #ifdef ZEND_WIN32  if(!seconds) {    return;  }     // 啟動(dòng)定時(shí)器線程  if (timeout_thread_initialized == 0 && InterlockedIncrement(&timeout_thread_initialized) == 1) {    /* We start up this process-wide thread here and not in zend_startup(), because if Zend     * is initialized inside a DllMain(), you're not supposed to start threads from it.     */    zend_init_timeout_thread();  }     // 向線程發(fā)送WM_REGISTER_ZEND_TIMEOUT消息  PostThreadMessage(timeout_thread_id, WM_REGISTER_ZEND_TIMEOUT, (WPARAM) GetCurrentThreadId(),                                  (LPARAM) seconds);#else   // linux平臺(tái)下  struct itimerval t_r;    /* timeout requested */  int signo;   if (seconds) {    t_r.it_value.tv_sec = seconds;    t_r.it_value.tv_usec = t_r.it_interval.tv_sec = t_r.it_interval.tv_usec = 0;     // 設(shè)置定時(shí)器,seconds秒后會(huì)發(fā)送SIGPROF信號(hào)    setitimer(ITIMER_PROF, &t_r, NULL);  }  signo = SIGPROF;   if (reset_signals) {    sigset_t sigset;     // 設(shè)置SIGPROF信號(hào)對(duì)應(yīng)的處理函數(shù)為zend_timeout    signal(signo, zend_timeout);         // 防屏蔽    sigemptyset(&sigset);    sigaddset(&sigset, signo);    sigprocmask(SIG_UNBLOCK, &sigset, NULL);  }#endif}

上述實(shí)現(xiàn)基本上可以完全分成兩種平臺(tái):

先看linux:

linux下的定時(shí)器要容易許多,調(diào)用setitimer函數(shù)就行,此外,zend_set_timeout還設(shè)定了SIGPROF信號(hào)的handler為zend_timeout。

注意,調(diào)用setitimer的時(shí)候,將it_interval設(shè)置成0,表明這個(gè)定時(shí)器只觸發(fā)一次,而不會(huì)每隔一段時(shí)間觸發(fā)一次。setitimer可以以三種方式計(jì)時(shí),php中采用的是ITIMER_PROF,它同時(shí)計(jì)算了用戶代碼和內(nèi)核代碼的執(zhí)行時(shí)間。一旦時(shí)間到了,會(huì)產(chǎn)生SIGPROF信號(hào)。

當(dāng)php進(jìn)程接收到SIGPROF信號(hào),不管當(dāng)前正在執(zhí)行什么,都會(huì)跳轉(zhuǎn)進(jìn)入到zend_timeout。zend_timeout才是實(shí)際處理超時(shí)的函數(shù)。

再看windows:

首先會(huì)啟動(dòng)一個(gè)子線程,該線程主要用于設(shè)置定時(shí)器,同時(shí)維護(hù)EG(timed_out)變量。

子線程一旦生成,主線程便會(huì)向子線程發(fā)送一條消息:WM_REGISTER_ZEND_TIMEOUT。子線程接收到WM_REGISTER_ZEND_TIMEOUT之后,產(chǎn)生一個(gè)定時(shí)器并開(kāi)始計(jì)時(shí)。同時(shí),子線程會(huì)設(shè)置EG(timed_out) = 0。這很重要!windows平臺(tái)下正是通過(guò)判斷EG(timed_out)是否為1,來(lái)決定是否超時(shí)。

如果定時(shí)器到時(shí)間了,子線程收到WM_TIMER消息,則取消定時(shí)器,并且設(shè)置EG(timed_out) = 1。

如果需要關(guān)閉定時(shí)器,則子線程會(huì)收到WM_UNREGISTER_ZEND_TIMEOUT消息。關(guān)閉定時(shí)器,并不會(huì)改變EG(timed_out)。

相關(guān)代碼還是很清晰的:

static LRESULT CALLBACK zend_timeout_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){  switch (message) {    case WM_DESTROY:      PostQuitMessage(0);      break;         // 生成一個(gè)定時(shí)器,開(kāi)始計(jì)時(shí)    case WM_REGISTER_ZEND_TIMEOUT:      /* wParam is the thread id pointer, lParam is the timeout amount in seconds */      if (lParam == 0) {        KillTimer(timeout_window, wParam);      } else {        SetTimer(timeout_window, wParam, lParam*1000, NULL);        EG(timed_out) = 0;      }      break;         // 關(guān)閉定時(shí)器    case WM_UNREGISTER_ZEND_TIMEOUT:      /* wParam is the thread id pointer */      KillTimer(timeout_window, wParam);      break;         // 超時(shí)了,也需關(guān)閉定時(shí)器    case WM_TIMER: {        KillTimer(timeout_window, wParam);        EG(timed_out) = 1;      }      break;    default:      return DefWindowProc(hWnd, message, wParam, lParam);  }  return 0;}

根據(jù)上文描述,最終都是需要跳轉(zhuǎn)到zend_timeout來(lái)處理超時(shí)的。那windows下如何進(jìn)入zend_timeout呢?

window下僅在execute函數(shù)中(zend_vm_execute.h剛開(kāi)始的地方),可以看到調(diào)用zend_timeout:

while (1) {  int ret;#ifdef ZEND_WIN32  if (EG(timed_out)) {  // windows下的超時(shí),執(zhí)行每條opcode之前都判斷是否需要調(diào)用zend_timeout    zend_timeout(0);  }#endif   if ((ret = OPLINE->handler(execute_data TSRMLS_CC)) > 0) {  ...  }}

上述代碼可以看到:

在windows下,每執(zhí)行完成一條opcode指令,就會(huì)進(jìn)行一次超時(shí)判斷。

因?yàn)橹骶€程執(zhí)行opcode的同時(shí),子線程可能已經(jīng)發(fā)生超時(shí),而windows并沒(méi)有什么機(jī)制可以讓主線程停止手頭的工作,直接跳入zend_timeout。所以只好利用子線程先將EG(timed_out)設(shè)置為1,然后主線程在等到當(dāng)前opcode執(zhí)行完成、進(jìn)入下一條opcode之前,判斷一下EG(timed_out)再調(diào)用zend_timeout。

因此準(zhǔn)確的講,windows的超時(shí),其實(shí)是有一點(diǎn)點(diǎn)延時(shí)的。至少在某一個(gè)opcode執(zhí)行的過(guò)程中,無(wú)法被打斷。當(dāng)然,正常情況下,單條opcode的執(zhí)行時(shí)間會(huì)很短。但是可以很容易人為構(gòu)造出一些很耗時(shí)的函數(shù),使得function call需要等待較長(zhǎng)時(shí)間。此時(shí),如果子線程判斷出超時(shí)了,則還需要經(jīng)過(guò)漫長(zhǎng)的等待,直到主線程完成該條opcode之后,才能調(diào)用zend_timeout。

zend_unset_timeout

void zend_unset_timeout(TSRMLS_D) /* {{{ */{#ifdef ZEND_WIN32     // 通過(guò)發(fā)送WM_UNREGISTER_ZEND_TIMEOUT消息來(lái)關(guān)閉定時(shí)器  if(timeout_thread_initialized) {    PostThreadMessage(timeout_thread_id, WM_UNREGISTER_ZEND_TIMEOUT, (WPARAM) GetCurrentThreadId(), (LPARAM) 0);  }#else  if (EG(timeout_seconds)) {    struct itimerval no_timeout;    no_timeout.it_value.tv_sec = no_timeout.it_value.tv_usec = no_timeout.it_interval.tv_sec = no_timeout.it_interval.tv_usec = 0;         // 全置0,相當(dāng)于關(guān)閉定時(shí)器    setitimer(ITIMER_PROF, &no_timeout, NULL);  }#endif}

zend_unset_timeout同樣分成兩種平臺(tái)的實(shí)現(xiàn)。

先看linux:

linux下的關(guān)閉定時(shí)器也很簡(jiǎn)單。只要將struct itimerval中的4個(gè)值都設(shè)置為0,就行了。

再看windows:

由于windows是利用一個(gè)獨(dú)立的線程來(lái)計(jì)時(shí)。因此,zend_unset_timeout會(huì)向該線程發(fā)送WM_UNREGISTER_ZEND_TIMEOUT消息。WM_UNREGISTER_ZEND_TIMEOUT對(duì)應(yīng)的動(dòng)作是去調(diào)用KillTimer來(lái)關(guān)閉定時(shí)器。注意,線程本身并不退出。

前文留下了一個(gè)問(wèn)題,在php_execute_script中,windows下面要顯示調(diào)用zend_unset_timeout來(lái)關(guān)閉定時(shí)器,而linux下不需要。因?yàn)閷?duì)于一個(gè)linux進(jìn)程來(lái)說(shuō),只能存在一個(gè)setitimer定時(shí)器。也就是說(shuō),重復(fù)調(diào)用setitimer,后面的定時(shí)器會(huì)直接覆蓋前面的。

zend_timeout

ZEND_API void zend_timeout(int dummy) /* {{{ */{  TSRMLS_FETCH();   if (zend_on_timeout) {    zend_on_timeout(EG(timeout_seconds) TSRMLS_CC);  }   zend_error(E_ERROR, "Maximum execution time of %d second%s exceeded", EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s");}

如前文所述,zend_timeout是實(shí)際處理超時(shí)的函數(shù)。它的實(shí)現(xiàn)也很簡(jiǎn)單。

如果有配置exit_on_timeout,則zend_on_timeout會(huì)嘗試調(diào)用sapi_terminate_process關(guān)閉sapi進(jìn)程。如果無(wú)需exit_on_timeout,則直接進(jìn)入zend_error進(jìn)行出錯(cuò)處理。大部分情況下,我們并不會(huì)設(shè)置exit_on_timeout,畢竟我們期望的是雖然一個(gè)請(qǐng)求超時(shí)了,但是進(jìn)程仍然保留下來(lái),服務(wù)下一個(gè)請(qǐng)求。

zend_error除了會(huì)打印錯(cuò)誤日志,還會(huì)利用longjump跳轉(zhuǎn)到boilout指定的棧幀,一般是zend_end_try或者zend_catch宏所在的地方。關(guān)于longjump,可以另起一個(gè)話題,本文就不具體敘述了。在php_execute_script里面,zend_error會(huì)使得程序跳轉(zhuǎn)到zend_end_try的位置然后繼續(xù)執(zhí)行。繼續(xù)執(zhí)行是指,會(huì)調(diào)用php_request_shutdown等函數(shù)來(lái)完成收尾工作。

直到這里,php腳本的超時(shí)機(jī)制算是講清楚了。

最后來(lái)看一個(gè)疑似php內(nèi)核的bug。

windows下max_input_time的bug

回憶一下,之前有提到windows下只有一個(gè)地方調(diào)用了zend_timeout,就是execute函數(shù)里,準(zhǔn)確講是每條opcode執(zhí)行之前。

那么,假如發(fā)生max_input_time類型的超時(shí),即使子線程將EG(timed_out)被置為1,也得延遲到execute中才能進(jìn)行超時(shí)處理。貌似一切正常。

而問(wèn)題的關(guān)鍵之處便在于,我們并不能保證主線程執(zhí)行到execute時(shí),EG(timed_out)任然為1。一旦進(jìn)入execute之前,EG(timed_out)被子線程修改成0,那么max_input_time類型的超時(shí)就永遠(yuǎn)不會(huì)被handle了。

為何EG(timed_out)會(huì)被子線程又修改為0呢?原因在于:php_execute_script中,調(diào)用了zend_set_timeout(INI_INT("max_execution_time"), 0)來(lái)設(shè)置定時(shí)器。

zend_set_timeout會(huì)向子線程發(fā)送WM_REGISTER_ZEND_TIMEOUT消息。子線程收到此消息,除了創(chuàng)建定時(shí)器之外,還會(huì)設(shè)置EG(timed_out) = 0(詳見(jiàn)上文截取的zend_timeout_WndProc代碼片段)。由于線程執(zhí)行的不確定性,因此不能夠判斷主線程執(zhí)行到execute的時(shí)候,子線程是否已接收到消息并設(shè)置EG(timed_out)為0。

php腳本運(yùn)行時(shí)的超時(shí)機(jī)制詳解

如圖所示,

如果execute中的判斷發(fā)生在紅線標(biāo)注的時(shí)間點(diǎn),則EG(timed_out)為1,execute會(huì)調(diào)用zend_timeout做超時(shí)處理。

如果execute中的判斷發(fā)生在藍(lán)線標(biāo)注的時(shí)間點(diǎn),則EG(timed_out)已被重置為0,max_input_time超時(shí)被徹底掩蓋。



注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到PHP教程頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
国产精品白丝一区二区三区| 国产a级黄色大片| 欧美日韩高清| 九九热这里只有精品6| 蜜臀av午夜精品久久| 最新成人av在线| 国产精品三级av| 毛片毛片毛片毛片毛片毛片毛片毛片毛片| 欧美三片在线视频观看| 成全视频全集| 欧美国产日本高清在线| 亚洲素人一区二区| 麻豆国产精品一区二区三区| 99这里有精品| 黄色片视频网站| 狠狠色丁香久久综合频道| 色又黄又爽网站www久久| 欧美日韩国产综合视频在线观看| 黄a大片av永久免费| 无码人妻av免费一区二区三区| 日韩精品一区二区三区中文精品| 色综合久久九月婷婷色综合| 亚洲国产剧情在线观看| 国产成人自拍视频在线观看| 久久久久久久中文字幕| 日韩精品在线视频免费观看| 成人超碰在线| xxxcom在线观看| 91久久大香伊蕉在人线| 亚洲精品传媒| 欧美 日韩 国产在线观看| 四虎影视在线观看2413| av在线播放成人| 可以看毛片的网址| 成人欧美一区二区三区小说| 亚洲精品一区二区三区网址| 欧美与亚洲与日本直播| av影院午夜一区| 有没有片在线看www| zzjj国产精品一区二区| 精品久久久久久久久久久久久久久| 丰满岳乱妇国产精品一区| 欧美日韩免费一区二区三区| 亚洲精品色午夜无码专区日韩| 欧美大胆a人体大胆做受| 色偷偷av一区二区三区| 91影院在线免费观看| 91美女片黄在线观看91美女| 日韩黄色免费网站| 国产一区二区三区不卡在线| 秋霞成人午夜鲁丝一区二区三区| 亚洲欧美日韩中文字幕一区二区三区| 紧缚捆绑精品一区二区| 欧美日本一区| 5566成人精品视频免费| 亚洲国产清纯| 国产成人综合欧美精品久久| 久久影院午夜精品| 色噜噜狠狠一区二区| 8x福利精品第一导航| 午夜av免费在线观看| 午夜精品视频一区二区三区在线看| 欧美一区二区三区四区在线观看地址| 91亚洲精品视频| 欧美videosex性极品hd| 日本午夜一区二区三区| 亚洲国产欧美另类| 中文字幕一区二区三区在线视频| 日韩精品专区在线影院观看| 午夜欧美精品| 国产亚洲欧美日韩在线观看一区二区| 可以看的av网址| jizzjizz日本护士视频| 精品免费国产一区二区| 欧美日本国产在线| 国产无遮挡又黄又爽免费网站| 国内精品久久久久伊人av| 好吊色视频在线观看| 五月天精品一区二区三区| 精品日韩在线播放| 国产探花在线精品| 美女脱光衣服与内衣内裤一区二区三区四区| 久久综合免费视频| 精品福利樱桃av导航| 尤物视频在线免费观看| 欧美在线网址| 99在线热播| 丝袜av一区| 91精品国产综合久久精品性色| 日韩一区二区三免费高清| 欧美性大战久久久久久久蜜臀| 免费看污黄网站在线观看| 先锋影音av资源站| 青草热久免费精品视频| 亚洲国产裸拍裸体视频在线观看乱了中文| 狠狠干 狠狠操| 国产资源在线一区| 国产69精品久久久久9999小说| 国产精品亚洲一区二区在线观看| 欧美日韩精品免费观看视完整| 国产999精品久久久久久绿帽| 亚洲另类在线制服丝袜| 免费黄色在线观看| 国产综合内射日韩久| 91av在线播放视频| 秋霞精品一区二区三区| 亚洲精选视频在线| 国产深喉视频一区二区| 青娱乐国产视频| 国产在线精品91| 国产精品亚洲综合色区韩国| 日本中文字幕一区| 艳妇乳肉豪妇荡乳av无码福利| 国产精品变态另类虐交| 影音先锋中文字幕在线视频| 91porn在线| 自拍偷拍亚洲在线| 免费在线看大片无需流量| 欧美日韩精品高清| 国产真实夫妇交换视频| 精品国产午夜福利| 国产免费av国片精品草莓男男| 亚洲狼人国产精品| 国产欧美精品在线| 日韩网站在线播放| 亚洲人在线视频| 区一区二区三区中文字幕| 中文一区二区完整视频在线观看| 亚洲免费不卡视频| 肉色超薄丝袜脚交| 亚洲欧美精品伊人久久| 51精品国产人成在线观看| 久久九九热免费视频| 美女网站在线观看| 国产一区二区视频在线观看| 国产又白又嫩又紧又爽18p| 蜜臀av在线观看| 99re66热这里只有精品8| 国产亚洲精品自在线观看| 久久中文字幕人妻| 亚洲电影免费观看| 日韩一区欧美小说| 在线视频观看91| 爆操欧美孕妇| 毛片av一区二区三区| 91九色国产ts另类人妖| www.18av.com| 奇米影视在线99精品| 日本中文字幕一区二区有码在线| av不卡高清| 欲求不满中文字幕| 五月激情综合婷婷| 成人欧美一区二区三区黑人免费| 一区二区高清视频在线观看| 国产欧美一区二区三区视频| 欧美成人午夜精品免费| 国模人体一区二区| 国产成人77亚洲精品www| 国产成人综合亚洲网站| 羞羞影视羞羞在线| 999亚洲国产精| 欧美三日本三级少妇三2023| 不卡av免费观看| 亚洲国产综合91精品麻豆| 免费观看欧美成人禁片| 亚洲夜间福利| 国产人妻精品一区二区三区不卡| 国产毛片在线看| 一区二区高清在线| av免费在线观看网址| 成人看片app| 黄瓜视频在线免费观看| 国产精品99久久久久久久久久久久| 国产精品日韩在线一区| 欧美自拍偷拍一区| a级大片免费看| 久久亚洲精品中文字幕| 亚洲高清毛片| 狠久久av成人天堂| 精品国产一区在线| 欧美日韩亚洲91| 欧美国产激情视频| 精品精品国产毛片在线看| 蜜桃精品一区二区三区| 久久久久久久久国产精品| 欧美极品一区二区三区| 免费视频网站在线观看入口| 在线免费看黄| 欧美日韩高清一区二区三区| 亚洲最新在线观看| 国产精品涩涩涩视频网站| 欧美一区二区三区在线观看免费| 亚洲成人一区二区在线观看| 亚洲欧美日本一区二区三区| 久久免费看少妇高潮v片特黄| 97色伦图片97综合影院| 欧美一级片在线| 蜜桃av鲁一鲁一鲁一鲁俄罗斯的| 91婷婷韩国| www.91香蕉视频| 国产男女在线观看| gay欧美网站| 偷偷www综合久久久久久久| 中文字幕亚洲自拍| 欧美一区二区在线免费播放| 中文字幕久久亚洲| 成年网站免费视频黄| 国产成人鲁鲁免费视频a| 精品久久综合| 性网站在线看| 国产一区二区三区不卡在线| 国产成人啪午夜精品网站男同| 精品国产电影一区| 欧美视频在线观看视频| 日韩欧美黄色动漫| 粉嫩一区二区三区在线观看| 99久久精品99国产精品| 欧美一级片黄色| 97国产精品人人爽人人做| 欧美成人精品不卡视频在线观看| 伊人av综合网| 97在线免费视频观看| 国产精品主播一区二区| 成人黄色免费短视频| 周于希免费高清在线观看| 亚洲第一影院| 国产三级在线免费观看| 亚洲黄页在线观看| 成人看片免费| 中文字幕av在线一区二区三区| 国产精品高清免费在线观看| 日韩中文字幕亚洲| 综合中文字幕| 国产乱码一区二区三区四区| 三级福利片在线观看| 日韩和欧美的一区| 国产亚洲成av人片在线观黄桃| 91精品国产一区二区人妖| 白浆爆出在线观看| 亚洲1卡2卡3卡4卡乱码精品| 国语精品中文字幕| 麻豆免费在线视频| 国产精品91在线| gogo亚洲高清大胆美女人体| 人人做人人澡人人爽欧美| 欧美日韩中文字幕在线| 亚洲精品日韩精品| 一区视频免费观看| 免费高清在线| 色综合久久久久久久久五月| 久久久亚洲国产| 羞羞色国产精品网站| 韩国av免费观看| 国产激情网址| 国产精品灌醉下药二区| 青青青青在线| 妺妺窝人体色WWW精品| 天天操夜夜草| 成人做爰69片免费| 中文字幕在线视频网站| 久久综合加勒比| 精品久久久久久综合日本欧美| 激情综合久久| 午夜老司机精品| 美女日韩在线中文字幕| 欧美精品一区二区蜜臀亚洲| 亚洲一区二区三区四区五区| 亚洲国产精品一区二区久久恐怖片| 和岳每晚弄的高潮嗷嗷叫视频| 免费在线观看av网址| 欧美深夜视频| 潘金莲一级黄色片| 免费观看国产视频| wwwww黄色| 欧美jiizzhd精品欧美| 日韩欧美999| 好吊色欧美一区二区三区| 九九亚洲精品| 天天影视天天精品| 午夜丝袜av电影| 综合久久久久久久| 好色视频app| 青娱乐在线视频观看| 欧美成人xxxx| 亚洲AV无码国产精品午夜字幕| 国产一区二区在线不卡| 婷婷激情图片久久| 日本动漫同人动漫在线观看| 全部孕妇毛片丰满孕妇孕交| 日本aⅴ免费视频一区二区三区| 欧美日韩一区二区三区在线视频| 精品视频一区二区在线观看| 国产精品免费观看视频| 国产中文字幕久久| 欧美亚洲国产成人| 欧美xfplay| 97国产成人高清在线观看| 99久久精品费精品国产风间由美| 精品国产av鲁一鲁一区| 精品176极品一区| 99ri国产在线| 夜夜操 天天操| 一区二区三区四区视频在线观看| 亚洲区综合中文字幕日日| 亚洲一区二区三区精品在线| 超碰在线中文| 四虎wwwcom| 六月丁香久久丫| 色欲狠狠躁天天躁无码中文字幕| 国产69视频在线观看| 欧美一级搡bbbb搡bbbb| 免费在线一区观看| 一级黄色片在线观看| 91插插插插插插插插| 国产黄色片免费观看| 欧美情侣性视频| 综合136福利视频在线| 一区二区三区四区蜜桃| 亚洲精品在线观看免费| 成人日韩在线| 国产美女在线一区| 日韩a在线看| 欧美一区二区视频17c| 美日韩一二三区| 成色在线视频| 国产精品伦一区| 一个色的综合| 丰满少妇被猛烈进入|