欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

Step by Step:Linux C多線程編程入門(基本API

系統(tǒng) 2109 0

Step by Step:Linux C多線程編程入門(基本API及多線程的同步與互斥)

介紹:什么是線程,線程的優(yōu)點是什么

線程在Unix系統(tǒng)下,通常被稱為輕量級的進程,線程雖然不是進程,但卻可以看作是Unix進程的表親,同一進程中的多條線程將 共享該進程中的全部系統(tǒng)資源,如虛擬地址空間,文件描述符和信號處理等等 。但同一進程中的多個線程 有各自的調(diào)用棧(call stack),自己的寄存器環(huán)境(register context),自己的線程本地存儲(thread-local storage) 。 一個進程可以有很多線程,每條線程并行執(zhí)行不同的任務(wù)。

線程可以提高應(yīng)用程序在多核環(huán)境下處理諸如文件I/O或者socket I/O等會產(chǎn)生堵塞的情況的表現(xiàn)性能。在Unix系統(tǒng)中,一個進程包含很多東西,包括可執(zhí)行程序以及一大堆的諸如文件描述符地址空間等資源。在很多情況下,完成相關(guān)任務(wù)的不同代碼間需要交換數(shù)據(jù)。如果采用多進程的方式,那么通信就需要在用戶空間和內(nèi)核空間進行頻繁的切換,開銷很大。但是如果使用多線程的方式,因為可以使用共享的全局變量,所以線程間的通信(數(shù)據(jù)交換)變得非常高效。

Hello World(線程創(chuàng)建、結(jié)束、等待)

創(chuàng)建線程 pthread_create

線程創(chuàng)建函數(shù)包含四個變量,分別為: 1. 一個線程變量名,被創(chuàng)建線程的標識 2. 線程的屬性指針,缺省為NULL即可 3. 被創(chuàng)建線程的程序代碼 4. 程序代碼的參數(shù) For example: - pthread_t thrd1; - pthread_attr_t? attr; - void thread_function(void? argument); - char *some_argument;

pthread_create(&thrd1, NULL, (void *)&thread_function, (void *) &some_argument);

結(jié)束線程 pthread_exit

線程結(jié)束調(diào)用實例: pthread_exit(void *retval); ?//retval用于存放線程結(jié)束的退出狀態(tài)

線程等待 pthread_join

pthread_create調(diào)用成功以后,新線程和老線程誰先執(zhí)行,誰后執(zhí)行用戶是不知道的,這一塊取決與操作系統(tǒng)對線程的調(diào)度,如果我們需要等待指定線程結(jié)束,需要使用pthread_join函數(shù),這個函數(shù)實際上類似與多進程編程中的waitpid。 舉個例子,以下假設(shè) A 線程調(diào)用 pthread_join 試圖去操作B線程,該函數(shù)將A線程阻塞,直到B線程退出,當B線程退出以后,A線程會收集B線程的返回碼。 該函數(shù)包含兩個參數(shù):

  • pthread_t th //th是要等待結(jié)束的線程的標識
  • void **thread_return //指針thread_return指向的位置存放的是終止線程的返回狀態(tài)。

調(diào)用實例: pthread_join(thrd1, NULL);

example1:

        
           1
        
        
          /*
        
        
          ************************************************************************


        
        
           2
        
        
              > File Name: thread_hello_world.c 


        
        
           3
        
        
              > Author: couldtt(fyby)


        
        
           4
        
        
              > Mail:  fuyunbiyi@gmail.com


        
        
           5
        
        
              > Created Time: 2013年12月14日 星期六 11時48分50秒


        
        
           6
        
        
           ***********************************************************************
        
        
          */
        
        
           7
        
        
           8
        
         #include <stdio.h>


        
           9
        
         #include <stdlib.h>


        
          10
        
         #include <pthread.h>


        
          11
        
        
          12
        
        
          void
        
         print_message_function (
        
          void
        
         *
        
          ptr);


        
        
          13
        
        
          14
        
        
          int
        
        
           main()


        
        
          15
        
        
          {


        
        
          16
        
        
          int
        
        
           tmp1, tmp2;


        
        
          17
        
        
          void
        
         *
        
          retval;


        
        
          18
        
        
              pthread_t thread1, thread2;


        
        
          19
        
        
          char
        
         *message1 = 
        
          "
        
        
          thread1
        
        
          "
        
        
          ;


        
        
          20
        
        
          char
        
         *message2 = 
        
          "
        
        
          thread2
        
        
          "
        
        
          ;


        
        
          21
        
        
          22
        
        
          int
        
        
           ret_thrd1, ret_thrd2;


        
        
          23
        
        
          24
        
             ret_thrd1 = pthread_create(&thread1, NULL, (
        
          void
        
         *)&print_message_function, (
        
          void
        
         *
        
          ) message1);


        
        
          25
        
             ret_thrd2 = pthread_create(&thread2, NULL, (
        
          void
        
         *)&print_message_function, (
        
          void
        
         *
        
          ) message2);


        
        
          26
        
        
          27
        
        
          //
        
        
           線程創(chuàng)建成功,返回0,失敗返回失敗號
        
        
          28
        
        
          if
        
         (ret_thrd1 != 
        
          0
        
        
          ) {


        
        
          29
        
                 printf(
        
          "
        
        
          線程1創(chuàng)建失敗\n
        
        
          "
        
        
          );


        
        
          30
        
             } 
        
          else
        
        
           {


        
        
          31
        
                 printf(
        
          "
        
        
          線程1創(chuàng)建成功\n
        
        
          "
        
        
          );


        
        
          32
        
        
              }


        
        
          33
        
        
          34
        
        
          if
        
         (ret_thrd2 != 
        
          0
        
        
          ) {


        
        
          35
        
                 printf(
        
          "
        
        
          線程2創(chuàng)建失敗\n
        
        
          "
        
        
          );


        
        
          36
        
             } 
        
          else
        
        
           {


        
        
          37
        
                 printf(
        
          "
        
        
          線程2創(chuàng)建成功\n
        
        
          "
        
        
          );


        
        
          38
        
        
              }


        
        
          39
        
        
          40
        
        
          //
        
        
          同樣,pthread_join的返回值成功為0
        
        
          41
        
             tmp1 = pthread_join(thread1, &
        
          retval);


        
        
          42
        
             printf(
        
          "
        
        
          thread1 return value(retval) is %d\n
        
        
          "
        
        , (
        
          int
        
        
          )retval);


        
        
          43
        
             printf(
        
          "
        
        
          thread1 return value(tmp) is %d\n
        
        
          "
        
        
          , tmp1);


        
        
          44
        
        
          if
        
         (tmp1 != 
        
          0
        
        
          ) {


        
        
          45
        
                 printf(
        
          "
        
        
          cannot join with thread1\n
        
        
          "
        
        
          );


        
        
          46
        
        
              }


        
        
          47
        
             printf(
        
          "
        
        
          thread1 end\n
        
        
          "
        
        
          );


        
        
          48
        
        
          49
        
             tmp2 = pthread_join(thread1, &
        
          retval);


        
        
          50
        
             printf(
        
          "
        
        
          thread2 return value(retval) is %d\n
        
        
          "
        
        , (
        
          int
        
        
          )retval);


        
        
          51
        
             printf(
        
          "
        
        
          thread2 return value(tmp) is %d\n
        
        
          "
        
        
          , tmp1);


        
        
          52
        
        
          if
        
         (tmp2 != 
        
          0
        
        
          ) {


        
        
          53
        
                 printf(
        
          "
        
        
          cannot join with thread2\n
        
        
          "
        
        
          );


        
        
          54
        
        
              }


        
        
          55
        
             printf(
        
          "
        
        
          thread2 end\n
        
        
          "
        
        
          );


        
        
          56
        
        
          57
        
        
          }


        
        
          58
        
        
          59
        
        
          void
        
         print_message_function( 
        
          void
        
         *
        
          ptr ) {


        
        
          60
        
        
          int
        
         i = 
        
          0
        
        
          ;


        
        
          61
        
        
          for
        
         (i; i<
        
          5
        
        ; i++
        
          ) {


        
        
          62
        
                 printf(
        
          "
        
        
          %s:%d\n
        
        
          "
        
        , (
        
          char
        
         *
        
          )ptr, i);


        
        
          63
        
        
              }


        
        
          64
        
         }
      

?

編譯

gcc thread_hello_world.c -otest -lpthread ?一定要加上 -lpthread ,要不然會報錯,因為源代碼里引用了pthread.h里的東西,所以在gcc進行鏈接的時候,必須要找到這些庫的二進制實現(xiàn)代碼。

運行結(jié)果

?結(jié)果分析: 1.這段程序我運行了兩次,可以看到,兩次的運行結(jié)果是不一樣的,從而說明, 新線程和老線程誰先執(zhí)行,誰后執(zhí)行用戶是不知道的,這一塊取決與操作系統(tǒng)對線程的調(diào)度 。 2.另外,我們看到,在thread2的join結(jié)果出現(xiàn)了錯誤,打印出 cannot join with thread2 其實這個是個小錯誤,因為,我pthread_join傳進去的th是thread1,在上面的結(jié)果中,thread1早已經(jīng)結(jié)束了,所以我們再次等待thread1結(jié)束肯定會出現(xiàn)無法取到狀態(tài)的錯誤的。 3.pthread_join(thread1, &retval)確實等待了thread1的結(jié)束,我們看到,在 print_message_function 函數(shù)循環(huán)了5遍結(jié)束以后,才打印出thread1 end

這是一個非常簡單的例子,hello world級別的,只是用來演示Linux下C多線程的使用,在實際應(yīng)用中,由于多個線程往往會訪問共享的資源(典型的是訪問同一個全局變量),因此多個縣城間存在著競爭的關(guān)系,這就需要對多個線程進行同步,對其訪問的數(shù)據(jù)予以保護。

多線程的同步與互斥

方式一:鎖

  • 在主線程中初始化鎖為解鎖狀態(tài)
    • pthread_mutex_t mutex;
    • pthread_mutex_init(&mutex, NULL);
  • 在編譯時初始化鎖為解鎖狀態(tài)
    • 鎖初始化 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  • 訪問對象時的加鎖操作與解鎖操作
    • 加鎖 pthread_mutex_lock(&mutex)
    • 釋放鎖 pthread_mutex_unlock(&mutex)
不加鎖,數(shù)據(jù)不同步

我們先來看一個不加鎖,多個線程訪問同一段數(shù)據(jù)的程序。

        
           1
        
        
          /*
        
        
          ************************************************************************


        
        
           2
        
        
              > File Name: no_mutex.c


        
        
           3
        
        
              > Author: couldtt(fyby)


        
        
           4
        
        
              > Mail: fuyunbiyi@gmail.com


        
        
           5
        
        
              > Created Time: 2013年12月15日 星期日 17時52分24秒


        
        
           6
        
        
           ***********************************************************************
        
        
          */
        
        
           7
        
        
           8
        
         #include <stdio.h>


        
           9
        
         #include <stdlib.h>


        
          10
        
         #include <pthread.h>


        
          11
        
        
          12
        
        
          int
        
         sharedi = 
        
          0
        
        
          ;


        
        
          13
        
        
          void
        
         increse_num(
        
          void
        
        
          );


        
        
          14
        
        
          15
        
        
          int
        
        
           main(){


        
        
          16
        
        
          int
        
        
           ret;


        
        
          17
        
        
              pthread_t thrd1, thrd2, thrd3;


        
        
          18
        
        
          19
        
             ret = pthread_create(&thrd1, NULL, (
        
          void
        
         *
        
          )increse_num, NULL);


        
        
          20
        
             ret = pthread_create(&thrd2, NULL, (
        
          void
        
         *
        
          )increse_num, NULL);


        
        
          21
        
             ret = pthread_create(&thrd3, NULL, (
        
          void
        
         *
        
          )increse_num, NULL);


        
        
          22
        
        
          23
        
        
              pthread_join(thrd1, NULL);


        
        
          24
        
        
              pthread_join(thrd2, NULL);


        
        
          25
        
        
              pthread_join(thrd3, NULL);


        
        
          26
        
        
          27
        
             printf(
        
          "
        
        
          sharedi = %d\n
        
        
          "
        
        
          , sharedi);


        
        
          28
        
        
          29
        
        
          return
        
        
          0
        
        
          ;


        
        
          30
        
        
          31
        
        
          }


        
        
          32
        
        
          33
        
        
          void
        
         increse_num(
        
          void
        
        
          ) {


        
        
          34
        
        
          long
        
        
           i,tmp;


        
        
          35
        
        
          for
        
        (i=
        
          0
        
        ; i<=
        
          100000
        
        ; i++
        
          ) {


        
        
          36
        
                 tmp =
        
           sharedi;


        
        
          37
        
                 tmp = tmp + 
        
          1
        
        
          ;


        
        
          38
        
                 sharedi =
        
           tmp;


        
        
          39
        
        
              }


        
        
          40
        
         }
      

?

編譯

gcc no_mutex.c -onomutex -lpthread

運行分析

從上圖可知,我們no_mutex每次的運行結(jié)果都不一致,而且,運行結(jié)果也不符合我們的預(yù)期,出現(xiàn)了錯誤的結(jié)果。 原因就是三個線程競爭訪問全局變量sharedi,并且都沒有進行相應(yīng)的同步。

舉個例子,當線程thrd1訪問到sharedi的時候,sharedi的值是1000,然后線程thrd1將sharedi的值累加到了1001,可是線程thrd2取到sharedi的時候,sharedi的值是1000,這時候線程thrd2對sharedi的值進行加1操作,使其變成了1001,可是這個時候,sharedi的值已經(jīng)被線程thrd1加到1001了,然而,thrd2并不知道,所以又將sharedi的值賦為了1001,從而導(dǎo)致了結(jié)果的錯誤。

這樣,我們就需要一個線程互斥的機制,來保護sharedi這個變量,讓同一時刻,只有一個線程能夠訪問到這個變量,從而使它的值能夠保證正確的變化。

加鎖,數(shù)據(jù)同步

通過加鎖,保證sharedi變量在進行變更的時候,只有一個線程能夠取到,并在在該線程對其進行操作的時候,其它線程無法對其進行訪問。

        
           1
        
        
          /*
        
        
          ************************************************************************


        
        
           2
        
        
              > File Name: mutex.c 


        
        
           3
        
        
              > Author: couldtt(fyby)


        
        
           4
        
        
              > Mail: fuyunbiyi@gmail.com 


        
        
           5
        
        
              > Created Time: 2013年12月15日 星期日 17時52分24秒


        
        
           6
        
        
           ***********************************************************************
        
        
          */
        
        
           7
        
        
           8
        
         #include <stdio.h>


        
           9
        
         #include <stdlib.h>


        
          10
        
         #include <pthread.h>


        
          11
        
        
          12
        
        
          int
        
         sharedi = 
        
          0
        
        
          ;


        
        
          13
        
        
          void
        
         increse_num(
        
          void
        
        
          );


        
        
          14
        
        
          15
        
         pthread_mutex_t mutex =
        
           PTHREAD_MUTEX_INITIALIZER;


        
        
          16
        
        
          17
        
        
          int
        
        
           main(){


        
        
          18
        
        
          int
        
        
           ret;


        
        
          19
        
        
              pthread_t thrd1, thrd2, thrd3;


        
        
          20
        
        
          21
        
             ret = pthread_create(&thrd1, NULL, (
        
          void
        
         *
        
          )increse_num, NULL);


        
        
          22
        
             ret = pthread_create(&thrd2, NULL, (
        
          void
        
         *
        
          )increse_num, NULL);


        
        
          23
        
             ret = pthread_create(&thrd3, NULL, (
        
          void
        
         *
        
          )increse_num, NULL);


        
        
          24
        
        
          25
        
        
              pthread_join(thrd1, NULL);


        
        
          26
        
        
              pthread_join(thrd2, NULL);


        
        
          27
        
        
              pthread_join(thrd3, NULL);


        
        
          28
        
        
          29
        
             printf(
        
          "
        
        
          sharedi = %d\n
        
        
          "
        
        
          , sharedi);


        
        
          30
        
        
          31
        
        
          return
        
        
          0
        
        
          ;


        
        
          32
        
        
          33
        
        
          }


        
        
          34
        
        
          35
        
        
          void
        
         increse_num(
        
          void
        
        
          ) {


        
        
          36
        
        
          long
        
        
           i,tmp;


        
        
          37
        
        
          for
        
        (i=
        
          0
        
        ; i<=
        
          100000
        
        ; i++
        
          ) {


        
        
          38
        
        
          /*
        
        
          加鎖
        
        
          */
        
        
          39
        
        
          if
        
         (pthread_mutex_lock(&mutex) != 
        
          0
        
        
          ) {


        
        
          40
        
                    perror(
        
          "
        
        
          pthread_mutex_lock
        
        
          "
        
        
          );


        
        
          41
        
        
                     exit(EXIT_FAILURE);


        
        
          42
        
        
                  }


        
        
          43
        
                 tmp =
        
           sharedi;


        
        
          44
        
                 tmp = tmp + 
        
          1
        
        
          ;


        
        
          45
        
                 sharedi =
        
           tmp;


        
        
          46
        
        
          /*
        
        
          解鎖鎖
        
        
          */
        
        
          47
        
        
          if
        
         (pthread_mutex_unlock(&mutex) != 
        
          0
        
        
          ) {


        
        
          48
        
                     perror(
        
          "
        
        
          pthread_mutex_unlock
        
        
          "
        
        
          );


        
        
          49
        
        
                      exit(EXIT_FAILURE);


        
        
          50
        
        
                  }


        
        
          51
        
        
              }


        
        
          52
        
         }
      

?

結(jié)果分析

加鎖

這一次,我們的結(jié)果是正確的,鎖有效得保護了我們的數(shù)據(jù)安全。然而:

  1. 鎖保護的并不是我們的共享變量(或者說是共享內(nèi)存),對于共享的內(nèi)存而言,用戶是無法直接對其保護的,因為那是物理內(nèi)存,無法阻止其他程序的代碼訪問。事實上,鎖之所以對關(guān)鍵區(qū)域進行了保護,在本例中,是因為所有線程都遵循了一個規(guī)則,那就是在進入關(guān)鍵區(qū)域錢加 同一把 鎖,在退出關(guān)鍵區(qū)域錢釋放 同一把

  2. 我們從上述運行結(jié)果中可以看到,加鎖是會帶來額外的開銷的,加鎖的代碼其運行速度,明顯比不加鎖的要慢一些,所以,在使用鎖的時候,要合理,在不需要對關(guān)鍵區(qū)域進行保護的場景下,我們便不要畫蛇添足,為其加鎖了

方式二:信號量

鎖有一個很明顯的缺點,那就是它 只有兩種狀態(tài) :鎖定與不鎖定。

信號量本質(zhì)上是一個非負數(shù)的整數(shù)計數(shù)器,它也被用來控制對公共資源的訪問。當公共資源增加的時候,調(diào)用信號量增加函數(shù)sem_post()對其進行增加,當公共資源減少的時候,調(diào)用函數(shù)sem_wait()來減少信號量。其實,我們是可以把鎖當作一個0-1信號量的。

它們是在 /usr/include/semaphore.h 中進行定義的,信號量的數(shù)據(jù)結(jié)構(gòu)為sem_t, 本質(zhì)上,它是一個long型整數(shù)

相關(guān)函數(shù)

在使用semaphore之前,我們需要先引入頭文件 #include <semaphore.h>

  • 初始化信號量:? int sem_init(sem_t *sem, int pshared, unsigned int value);
    • 成功返回0,失敗返回-1
    • 參數(shù)
    • sem:指向信號量結(jié)構(gòu)的一個指針
    • pshared: 不是0的時候,該信號量在進程間共享,否則只能為當前進程的所有線程們共享
    • value:信號量的初始值
  • 信號量減1操作,當sem=0的時候該函數(shù)會堵塞? int sem_wait(sem_t *sem);
    • 成功返回0,失敗返回-1
    • 參數(shù)
    • sem:指向信號量的一個指針
  • 信號量加1操作? int sem_post(sem_t *sem);
    • 參數(shù)與返回同上
  • 銷毀信號量? int sem_destroy(sem_t *sem);
    • 參數(shù)與返回同上
代碼示例
        
           1
        
        
          /*
        
        
          ************************************************************************


        
        
           2
        
        
              > File Name: sem.c


        
        
           3
        
        
              > Author: couldtt(fyby)


        
        
           4
        
        
              > Mail: fuyunbiyi@gmail.com 


        
        
           5
        
        
              > Created Time: 2013年12月15日 星期日 19時25分08秒


        
        
           6
        
        
           ***********************************************************************
        
        
          */
        
        
           7
        
        
           8
        
         #include <stdio.h>


        
           9
        
         #include <unistd.h>


        
          10
        
         #include <pthread.h>


        
          11
        
         #include <semaphore.h>


        
          12
        
        
          13
        
        
          #define
        
         MAXSIZE 10


        
          14
        
        
          15
        
        
          int
        
        
           stack[MAXSIZE];


        
        
          16
        
        
          int
        
         size = 
        
          0
        
        
          ;


        
        
          17
        
        
          sem_t sem;


        
        
          18
        
        
          19
        
        
          //
        
        
           生產(chǎn)者
        
        
          20
        
        
          void
        
         provide_data(
        
          void
        
        
          ) {


        
        
          21
        
        
          int
        
        
           i;


        
        
          22
        
        
          for
        
         (i=
        
          0
        
        ; i< MAXSIZE; i++
        
          ) {


        
        
          23
        
                 stack[i] =
        
           i;


        
        
          24
        
                 sem_post(&sem); 
        
          //
        
        
          為信號量加1
        
        
          25
        
        
              }


        
        
          26
        
        
          }


        
        
          27
        
        
          28
        
        
          //
        
        
           消費者
        
        
          29
        
        
          void
        
         handle_data(
        
          void
        
        
          ) {


        
        
          30
        
        
          int
        
        
           i;


        
        
          31
        
        
          while
        
        ((i = size++) <
        
           MAXSIZE) {


        
        
          32
        
                 sem_wait(&
        
          sem);


        
        
          33
        
                 printf(
        
          "
        
        
          乘法: %d X %d = %d\n
        
        
          "
        
        , stack[i], stack[i], stack[i]*
        
          stack[i]);


        
        
          34
        
                 sleep(
        
          1
        
        
          );


        
        
          35
        
        
              }


        
        
          36
        
        
          }


        
        
          37
        
        
          38
        
        
          int
        
         main(
        
          void
        
        
          ) {


        
        
          39
        
        
          40
        
        
              pthread_t provider, handler;


        
        
          41
        
        
          42
        
             sem_init(&sem, 
        
          0
        
        , 
        
          0
        
        ); 
        
          //
        
        
          信號量初始化
        
        
          43
        
             pthread_create(&provider, NULL, (
        
          void
        
         *
        
          )handle_data, NULL);


        
        
          44
        
             pthread_create(&handler, NULL, (
        
          void
        
         *
        
          )provide_data, NULL);


        
        
          45
        
        
              pthread_join(provider, NULL);


        
        
          46
        
        
              pthread_join(handler, NULL);


        
        
          47
        
             sem_destroy(&sem); 
        
          //
        
        
          銷毀信號量
        
        
          48
        
        
          49
        
        
          return
        
        
          0
        
        
          ;


        
        
          50
        
         }
      

?

運行結(jié)果:

因為信號量機制的存在,所以代碼在handle_data的時候,如果sem_wait(&sem)時,sem為0,那么代碼會堵塞在sem_wait上面,從而避免了在stack中訪問錯誤的index而使整個程序崩潰。

參考資料

?
?

Step by Step:Linux C多線程編程入門(基本API及多線程的同步與互斥)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 夜夜爽夜夜叫夜夜高潮漏水 | 香蕉视频在线观看视频 | 亚洲 偷拍 色播 | 久久一本久综合久久爱 | 日本久久久久久 | 国产精品视频免费 | 又大又粗进出白浆直流动态图 | 亚洲人成网站看在线播放 | 亚洲欧美日韩中文字幕在线不卡 | www.久久久 | 一区二区三区四区在线视频 | 亚洲精品国产a久久久久久 亚洲国产精品第一页 | 琪琪五月天综合婷婷 | 国产123| 亚洲欧美激情另类 | 苏晓晖个人简介军衔 | 波多野结衣在线高清视频 | 色狠狠色狠狠综合一区 | 亚洲v日本v欧美v综合v | 中文字幕精品一区久久久久 | 人人爱天天做夜夜爽88 | 婷婷精品 | 日韩在线精品视频 | 日韩美女av在线 | 综合精品一区 | 亚洲免费在线看 | 久草视频精品 | 偷偷狠狠的日日高清完整视频 | 日韩中文字幕网站 | 亚洲日本欧美 | 亚洲高清在线 | 天天干干干 | 国产亚洲精品久久精品录音 | 久久草在线视频免费 | 久久亚洲最大成人网4438 | 亚洲精品aⅴ | 亚洲综合久久1区2区3区 | 欧美经典成人在观看线视频 | 国产亚洲欧美在线人成aaaa | 亚洲欧美国产视频 | 久久精品国产99久久久古代 |