青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

興海北路

---男兒仗劍自橫行
<2008年4月>
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

統計

  • 隨筆 - 85
  • 文章 - 0
  • 評論 - 17
  • 引用 - 0

常用鏈接

留言簿(6)

隨筆分類

隨筆檔案

收藏夾

全是知識啊

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

shell編程范例之進程的操作
by falcon<zhangjinw@gmail.com>
2008-02-21

    這一小節寫了很久,到現在才寫完。本來關注的內容比較多,包括程序開發過程的細節、ELF格式的分析、進程的內存映像等,后來搞得“雪球越滾越大”,甚至 脫離了shell編程關注的內容。所以呢,想了個小辦法,“大事化小,小事化了”,把涉及到的內容分成如下幾個部分:
    1、把VIM打造成源代碼編輯器(源代碼編輯過程:用VIM編輯代碼的一些技巧)
    2、GCC編譯的背后 第一部分:預處理和編譯 第二部分:匯編和鏈接(編譯過程:預處理、編譯、匯編、鏈接)
    3、程序執行的那一剎那 (執行過程:當我們從命令行輸入一個命令之后)
    4、進程的內存映像 (進程加載過程:程序在內存里是個什么樣子)
    5、動態符號鏈接的細節(動態鏈接過程:函數puts/printf的地址在哪里)
    6、代碼測試、調試與優化小結(程序開發過后:內存溢出了嗎?有緩沖區溢出?代碼覆蓋率如何測試呢?怎么調試匯編代碼?有哪些代碼優化技巧和方法呢?)
    7、    8、進程和進程的基本操作(本小節)
    呵呵,好多。終于可以一部分一部分地完成了,不會再有一種對著一個大蛋糕卻不知道如何下口的尷尬了。
    進程作為程序真正發揮作用時的“形態”,我們有必要對它的一些相關操作非常熟悉,這一節主要描述進程相關的概念和操作,將介紹包括程序、進程、作業等基本概念以及進程狀態查詢、進程通信等相關的基本操作等。

1、什么是程序,什么又是進程

    程序是指令的集合,而進程則是程序執行的基本單元。為了讓程序完成它的工作,我們必須讓程序運行起來成為進程,進而利用處理器資源,內存資源,進行各種I/O操作,從而完成某項指定的工作。
    在這個意思上說,程序是靜態的,而進程則是動態的。
    而進程有區別于程序的地方還有,進程除了包含程序文件中的指令數據意外,還需要在內核中有一個數據結構用以存放特定進程的相關屬性,以便內核更好的管理和調度進程,從而完成多進程協作的任務。因此,從這個意義上可以說“高于”程序,超出了程序指令本身。
    如果進行過多進程程序的開發,你又會發現,一個程序可能創建多個進程,通過多個進程的交互完成任務。在Linux下,多進程的創建通常是通過fork系統調用實現的。從這個意義上來說程序則”包含”了進程。
    另外一個需要明確的是,程序可以由多種不同的程序語言描述,包括C語言程序、匯編語言程序和最后編譯產生的機器指令等。
   
    下面我們簡單討論一下Linux下面如何通過shell進行進程的相關操作。

2、進程的創建

    通常在命令行鍵入某個程序文件名以后,一個進程就被創建了。例如,

Quote:

$ sleep 100 &            #讓sleep程序在后臺運行
[1] 9298
$ pidof sleep             #用pidof可以查看指定程序名的進程ID
9298
$ cat /proc/9298/maps    #查看進程的內存映像
08048000-0804b000 r-xp 00000000 08:01 977399     /bin/sleep
0804b000-0804c000 rw-p 00003000 08:01 977399     /bin/sleep
0804c000-0806d000 rw-p 0804c000 00:00 0          [heap]
b7c8b000-b7cca000 r--p 00000000 08:01 443354    
...
bfbd8000-bfbed000 rw-p bfbd8000 00:00 0          [stack]
ffffe000-fffff000 r-xp 00000000 00:00 0          [vdso]


    當一個程序被執行以后,程序被加載到內存中,成為了一個進程。上面顯示了該進程的內存映像(虛擬內存),包括程序指令、數據,以及一些用于存放程命令行參數、環境變量的棧空間,用于動態內存申請的堆空間都被分配好了。
    關于程序在命令行執行過程的細節,請參考《Linux命令行下程序執行的那一剎那》。

    實際上,創建一個進程,也就是說讓程序運行,還有其他的辦法,比如,通過一些配置讓系統啟動時自動啟動我們的程序(具體參考"man init"),或者是通過配置crond(或者at)讓它定時啟動我們的程序。除此之外,還有一個方式,那就是編寫shell腳本,把程序寫入一個腳本文 件,當執行腳本文件時,文件中的程序將被執行而成為進程。這些方式的細節就不介紹了,下面介紹如何查看進程的屬性。

    需要補充一點的是,在命令行下執行程序時,我們可以通過ulimit內置命令來設置進程可以利用的資源,比如進程可以打開的最大文件描述符個數,最大的棧空間,虛擬內存空間等。具體用法見"help ulimit"。

3、查看進程的屬性和狀態

    我們可以通過ps命令查看進程的相關屬性和狀態,這些信息包括進程所屬用戶,進程對應的程序,進程對cpu和內存的使用情況等信息。熟悉如何查看它們有助于我們進行相關的統計分析和進一步的操作。

Quote:

$ ps -ef #查看系統所有當前進程的屬性
$ ps -C init #查看命令中包含某個指定字符的程序對應的進程,進程ID是1,TTY為?表示和終端沒有關聯
  PID TTY          TIME CMD
    1 ?        00:00:01 init
$ ps -U falcon #選擇某個特定用戶啟動的進程
$ ps -e -o "%C %c"  #可以按照指定格式輸出指定內容,這里會輸出命令名和cpu使用率
$ ps -e -o "%C %c" | sort -u -k1 -r | head -5  #這樣則會打印cpu使用率最高的前4個程序
 7.5 firefox-bin
 1.1 Xorg
 0.8 scim-panel-gtk
 0.2 scim-bridge
$ ps -e -o "%z %c" | sort -n -k1 -r | head -5  #使用虛擬內存最大的5個進程
349588 firefox-bin
 96612 xfce4-terminal
 88840 xfdesktop
 76332 gedit
 58920 scim-panel-gtk


    由于系統所有進程之間都有“親緣”關系,所以可以通過pstree查看這種關系,
Quote:

$ pstree #打印系統進程調用樹,可以非常清楚地看到當前系統中所有活動進程之間的調用關系


    動態查看進程信息,  
Quote:

$ top


    該命令最大的特點是可以動態的查看進程的信息,當然,它還提供了一些有用的參數,比如-S可以按照累計執行時間的大小排序查看,也可以通過-u查看指定用戶啟動的進程等。

    感覺有上面幾個命令來查看進程的信息就差不多了,下面來討論一個有趣的問題:如何讓一個程序在同一時間只有一個在運行。
    這意味著當一個程序正在被執行時,它將不能再被啟動。那該怎么做呢?
    假如一份相同的程序被復制成了很多份,并且具有不同的文件名被放在不同的位置,這個將比較糟糕,所以我們考慮最簡單的情況,那就是這份程序在整個系統上是唯一的,而且名字也是唯一的。這樣的話,我們有哪些辦法來回答上面的問題呢?
    總的機理是:在這個程序的開頭檢查自己有沒有執行,如果執行了則停止否則繼續執行后續代碼。
    策略則是多樣的,由于前面的假設已經保證程序文件名和代碼的唯一性,所以
  • 通過ps命令打印找出當前的所有進程對應的程序名,逐個與自己的程序名比較,如果已經有,那么說明自己已經運行了。


    Code:

    [Ctrl+A Select All]


  • 每次運行時先在指定位置檢查是否存在一個保存自己進程ID的文件,如果不存在,那么繼續執行,如果存在,那么查看該進程ID是否正在運行,如果在,那么退出,否則往該文件重新寫的新的進程ID,并繼續。



    Code:

    [Ctrl+A Select All]


        更多實現策略自己盡情的發揮吧!

    4、調整進程的優先級

        在保證每個進程都能夠順利執行外,為了讓某些任務優先完成,那么系統在進行進程調度時就會采用一定的調度辦法,比如常見的有按照優先級的時間片輪轉的調度算法。這種情況下,我們可以通過renice調整正在運行的程序的優先級,例如,

    Quote:

    $ ps -e -o "%p %c %n" | grep xfs #打印的信息分別是進程ID,進程對應的程序名,優先級
     5089 xfs               0
    $ renice 1 -p 5089
    renice: 5089: setpriority: Operation not permitted
    $ sudo renice 1 -p 5089   #需要權限才行
    [sudo] password for falcon:
    5089: old priority 0, new priority 1
    $ ps -e -o "%p %c %n" | grep xfs  #再看看,優先級已經被調整過來了
     5089 xfs               1



    5、結束進程

        既然可以通過命令行執行程序,創建進程,那么也有辦法結束它。我們可以通過kill命令給用戶自己啟動的進程發送一定信號讓進程終止,當然“萬能”的root幾乎可以kill所有進程(除了init之外)。例如,

    Quote:

    $ sleep 50 &   #啟動一個進程
    [1] 11347
    $ kill 11347


        kill命令默認會發送終止信號(SIGTERM)給程序,讓程序退出,但是kill還可以發送其他的信號,這些信號的定義我們可以通過man 7 signal查看到,也可以通過kill -l列出來。
    Quote:

    $ man 7 signal
    $ kill -l
     1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL
     5) SIGTRAP      6) SIGABRT      7) SIGBUS       8) SIGFPE
     9) SIGKILL     10) SIGUSR1     11) SIGSEGV     12) SIGUSR2
    13) SIGPIPE     14) SIGALRM     15) SIGTERM     16) SIGSTKFLT
    17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
    21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU
    25) SIGXFSZ     26) SIGVTALRM   27) SIGPROF     28) SIGWINCH
    29) SIGIO       30) SIGPWR      31) SIGSYS      34) SIGRTMIN
    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3  38) SIGRTMIN+4
    39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
    43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12
    47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14
    51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10
    55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7  58) SIGRTMAX-6
    59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
    63) SIGRTMAX-1  64) SIGRTMAX


        例如,我們用kill命令發送SIGSTOP信號給某個程序,讓它暫停,然后發送SIGCONT信號讓它繼續運行。

    Quote:

    $ sleep 50 &
    [1] 11441
    $ jobs
    [1]+  Running                 sleep 50 &
    $ kill -s SIGSTOP 11441   #這個等同于我們對一個前臺進程執行CTRL+Z操作
    $ jobs
    [1]+  Stopped                 sleep 50
    $ kill -s SIGCONT 11441   #這個等同于之前我們使用bg %1操作讓一個后臺進程運行起來
    $ jobs
    [1]+  Running                 sleep 50 &
    $ kill %1                  #在當前會話(session)下,也可以通過作業號控制進程
    $ jobs
    [1]+  Terminated              sleep 50


        可見kill命令為我們提供了非常好的功能,不過kill命令只能根據進程的ID或者作業來控制進程,所以pkill和killall給我們提供了更多選擇,它們擴展了通過程序名甚至是進程的用戶名來控制進程的方法。更多用法請參考它們的手冊。

        當一個程序退出以后,如何判斷這個程序是正常退出還是異常退出呢?還記得Linux下,那個經典"hello,world"程序嗎?在代碼的最后總是有條 “return 0”語句。這個“return 0”實際上是為了讓程序員來檢查進程是否正常退出的。如果進程返回了一個其他的數值,那么我們可以肯定的說這個進程異常退出了,因為它都沒有執行到 “return 0”這條語句就退出了。
        那怎么檢查進程退出的狀態,即那個返回的數值呢?
        在shell程序中,我們可以檢查這個特殊的變量$?,它存放了上一條命令執行后的退出狀態。

    Quote:

    $ test1
    bash: test1: command not found
    $ echo $?
    127
    $ cat ./test.c | grep hello
    $ echo $?
    1
    $ cat ./test.c | grep hi
            printf("hi, myself!\n");
    $ echo $?
    0


        貌似返回0成為了一個潛規則,雖然沒有標準明確規定,不過當程序正常返回時,我們總是可以從$?中檢測到0,但是異常時,我們總是檢測到一個非0的值。這 就告訴我們在程序的最后我們最好是跟上一個exit 0以便任何人都可以通過檢測$?確定你的程序是否正常結束。如果有一天,有人偶爾用到你的程序,試圖檢查你的程序的退出狀態,而你卻在程序的末尾莫名的返 回了一個-1或者1,那么他將會很苦惱,會懷疑自己的程序哪個地方出了問題,檢查半天卻不知所措,因為他太信任你了,竟然從頭至尾都沒有懷疑你的編程習慣 可能會與眾不同。

    6、進程通信

        為了便于設計和實現,通常一個大型的任務都被劃分成較小的模塊。不同模塊之間啟動后成為進程,它們之間如何通信以便交互數據,協同工作呢?在《UNIX環 境高級編程》一書中提到很多方法,諸如管道(無名管道和有名管道)、信號(signal)、報文(Message)隊列(消息隊列)、共享內存 (mmap/munmap)、信號量(semaphore,主要是同步用,進程之間,進程的不同線程之間)、套接口(Socket,支持不同機器之間的進 程通信)等,而在shell編程里頭,我們通常直接用到的就有管道和信號等。下面主要介紹管道和信號機制在shell編程時候的一些用法。
       
       
  • 無名管道(pipe):

        在Linux下,你可以通過"|"連接兩個程序,這樣就可以用它來連接后一個程序的輸入和前一個程序的輸出,因此被形象地叫做個管道。在C語言里頭,創建 無名管道非常簡單方便,用pipe函數,傳入一個具有兩個元素的int型的數組就可以。這個數組實際上保存的是兩個文件描述符,父進程往第一個文件描述符 里頭寫入東西后,子進程可以從第一個文件描述符中讀出來。

        如果用多了命令行,這個管子"|"應該會經常用。比如我們在上面的演示中把ps命令的輸出作為grep命令的輸入,從而可以過濾掉一些我們感興趣的信息:

    Quote:

    $ ps -ef | grep init



        也許你會覺得這個“管子”好有魔法,竟然真地能夠鏈接兩個程序的輸入和輸出,它們到底是怎么實現的呢?實際上當我們輸入這樣一組命令的時候,當前解釋程序 會進行適當的解析,把前面一個進程的輸出關聯到管道的輸出文件描述符,把后面一個進程的輸入關聯到管道的輸入文件描述符,這個關聯過程通過輸入輸出重定向 函數dup(或者fcntl)來實現。

       
  • 有名管道(named pipe):

        有名管道實際上是一個文件(無名管道也像一個文件,雖然關系到兩個文件描述符,不過只能一邊讀另外一邊寫),不過這個文件比較特別,操作時要滿足先進先 出,而且,如果試圖讀一個沒有內容的有名管道,那么就會被阻塞,同樣地,如果試圖往一個有名管道里頭寫東西,而當前沒有程序試圖讀它,也會被阻塞。下面看 看效果。

    Quote:

    $ mkfifo fifo_test    #通過mkfifo命令可以創建一個有名管道
    $ echo "fewfefe" > fifo_test    #試圖往fifo_test文件中寫入內容,但是被阻塞,要另開一個終端繼續下面的操作
    $ cat fifo_test        #另開一個終端,記得,另開一個。試圖讀出fifo_test的內容
    fewfefe



        在這里echo和cat是兩個不同的程序,在這種情況下,通過echo和cat啟動的兩個進程之間并沒有父子關系。不過它們依然可以通過有名管道通信。這 樣一種通信方式非常適合某些情況:例如有這樣一個架構,這個架構由兩個應用程序構成,其中一個通過一個循環不斷讀取fifo_test中的內容,以便判 斷,它下一步要做什么。如果這個管道沒有內容,那么它就會被阻塞在那里,而不會死循環而耗費資源,另外一個則作為一個控制程序不斷地往fifo_test 中寫入一些控制信息,以便告訴之前的那個程序該做什么。下面寫一個非常簡單的例子。我們可以設計一些控制碼,然控制程序不斷的往fifo_test里頭寫 入,然后應用程序根據這些控制碼完成不同的動作。當然,也可以往fifo_test傳入除控制碼外的不同的數據。

    Quote:

    $ cat app.sh    #應用程序的代碼
    #!/bin/bash

    FIFO=fifo_test
    while :;
    do
                    CI=`cat $FIFO`  #CI --> Control Info
                    case $CI in
                                    0) echo "The CONTROL number is ZERO, do something ..."
                                            ;;
                                    1) echo "The CONTROL number is ONE, do something ..."
                                            ;;
                                    *) echo "The CONTROL number not recognized, do something else..."
                                            ;;
                    esac
    done
    $ cat control.sh    #控制程序的代碼
    #!/bin/bash

    FIFO=fifo_test
    CI=$1

    [ -z "$CI" ] && echo "the control info should not be empty" && exit

    echo $CI > $FIFO
    $ chmod +x app.sh control.sh    #修改這兩個程序的可執行權限,以便用戶可以執行它們
    $ ./app.sh            #在一個終端啟動這個應用程序,在通過./control.sh發送控制碼以后查看輸出
    The CONTROL number is ONE, do something ...    #發送1以后
    The CONTROL number is ZERO, do something ...    #發送0以后
    The CONTROL number not recognized, do something else...    #發送一個未知的控制碼以后
    $ ./control.sh 1            #在另外一個終端,發送控制信息,控制應用程序的工作
    $ ./control.sh 0            
    $ ./control.sh 4343



        這樣一種應用架構非常適合本地的多程序任務的設計,如果結合web cgi,那么也將適合遠程控制的要求。引入web cgi的唯一改變是,要把控制程序./control.sh放到web的cgi目錄下,并對它作一些修改,以使它符合CGI的規范,這些規范包括文檔輸出 格式的表示(在文件開頭需要輸出content-tpye: text/html以及一個空白行)和輸入參數的獲取(web輸入參數都存放在QUERY_STRING環境變量里頭)。因此一個非常簡單的CGI形式控 制程序將類似下面。



    Code:

    [Ctrl+A Select All]



        在實際使用的時候,請確保control.sh能夠訪問到fifo_test管道,并且有寫權限。這樣我們在瀏覽器上就可以這樣控制app.sh了。

    http://ipaddress_or_dns/cgi-bin/control.sh?0

        問號(?)后面的內容即QUERY_STRING,類似之前的$1。

        這樣一種應用對于遠程控制,特別是嵌入式系統的遠程控制很有實際意義。在去年的暑期課程上,我們就通過這樣一種方式來實現馬達的遠程控制。首先,我們實現 了一個簡單的應用程序以便控制馬達的轉動,包括轉速,方向等的控制。為了實現遠程控制,我們設計了一些控制碼,以便控制馬達轉動相關的不同屬性。

        在C語言中,如果要用有名管道,和shell下的類似,只不過在讀寫數據的時候用read,write調用,在創建fifo的時候用mkfifo函數調用。

       
  • 信號(Signal):

        信號是軟件中斷,在Linux下面用戶可以通過kill命令給某個進程發送一個特定的信號,也可以通過鍵盤發送一些信號,比如CTRL+C可能觸發 CGIINT信號,而CTRL+\可能觸發SGIQUIT信號等,除此之外,內核在某些情況下也會給進程發送信號,比如在訪問內存越界時產生 SGISEGV信號,當然,進程本身也可以通過kill,raise等函數給自己發送信號。對于Linux下支持的信號類型,大家可以通過"man 7 signal"或者"kill -l"查看到相關列表和說明。

        對于有些信號,進程會有默認的響應動作,而有些信號,進程可能直接會忽略,當然,用戶還可以對某些信號設定專門的處理函數。在shell程序中,我們可以 通過trap命令(shell的內置命令)來設定響應某個信號的動作(某個命令或者是你定義的某個函數),而在C語言里頭可以通過signal調用注冊某 個信號的處理函數。這里僅僅演示trap命令的用法。

    Quote:

    $ function signal_handler {    #定一個signal_handler的函數,>是按下換行符號自動出現的
    > echo "hello, world"
    > }
    $ trap signal_handle SIGINT    #執行該命令設定:當發生SIGINT信號時將打印hello。
    $ hello, world            #按下CTRL+C,可以看到屏幕上輸出了hello, world字符串



        類似地,如果設定信號0的響應動作,那么就可以用trap來模擬C語言程序中的atexit程序終止函數的登記,即通過trap signal_handler SIGQUIT設定的signal_handler函數將在程序退出的時候被執行。信號0是一個特別的信號,在POSIX.1中把信號編號0定義為空信 號,這將常被用來確定一個特定進程是否仍舊存在。當一個程序退出時會觸發該信號。

    Quote:

    $ cat sigexit.sh
    #!/bin/bash

    function signal_handler {
            echo "hello, world"
    }
    trap signal_handler 0
    $ chmod +x sigexit.sh
    $ ./sigexit.sh    #實際上在shell編程時,會用這種方式在程序退出時來做一些清理臨時文件的收尾工作
    hello, world

      

    7、作業和作業控制

        當我們為完成一些復雜的任務而將多個命令通過|,>,<, ;, (, )等組合在一起的時候,通常這樣個命令序列會啟動多個進程,它們之間通過管道等進行通信。而有些時候,我們在執行一個任務的同時,還有其他的任務需要處 理,那么就經常會在命令序列的最后加上一個&,或者在執行命令以后,按下CTRL+Z讓前一個命令暫停。以便做其他的任務。等做完其他一些任務以 后,再通過fg命令把后臺的任務切換到前臺。這樣一種控制過程通常被成為作業控制,而那些命令序列則被成為作業,這個作業可能涉及一個或者多個程序,一個 或者多個進程。下面演示一下幾個常用的作業控制操作。

    Quote:

    $ sleep 50 &      #讓程序在后臺運行,將打印[作業號]和進程號
    [1] 11137
    $ fg %1            #使用shell內置命令fg把作業1調到前臺運行,然后按下CTRL+Z讓該進程暫停
    sleep 50

    [1]+  Stopped                 sleep 50
    $ jobs            #查看當前作業情況,有一個作業停止
    [1]+  Stopped                 sleep 50
    $ sleep 100 &       #讓另外一個作業在后臺運行
    [2] 11138        
    $ jobs            #查看當前作業情況,一個正在運行,一個停止
    [1]+  Stopped                 sleep 50
    [2]-  Running                 sleep 100 &
    $ bg %1            #啟動停止的進程并讓它在后臺運行
    [2]+ sleep 50 &



        不過,要在命令行下使用作業控制,需要當前shell,內核終端驅動等對作業控制支持才行。

    參考資料

    <UNIX環境高級編程>相關章節

  • posted on 2008-03-14 15:34 隨意門 閱讀(1021) 評論(0)  編輯 收藏 引用

    青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
      <noscript id="pjuwb"></noscript>
            <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
              <dd id="pjuwb"></dd>
              <abbr id="pjuwb"></abbr>
              久久精品国产77777蜜臀| 欧美韩国一区| 亚洲一二三区在线| 亚洲国产日韩在线一区模特| 国产美女在线精品免费观看| 国产精品久久久一区二区三区| 欧美黄色网络| 欧美日韩一区二区三区在线观看免| 欧美大秀在线观看 | 亚洲欧美成人综合| 一级日韩一区在线观看| 一区二区三区不卡视频在线观看| 一区二区欧美日韩| 99国产精品国产精品久久| 亚洲三级视频| 9色国产精品| 久久久久女教师免费一区| 欧美性大战xxxxx久久久| 欧美午夜大胆人体| 91久久夜色精品国产九色| 午夜亚洲性色视频| 一区二区三区视频在线看| 欧美大片91| 国产一区二区三区高清在线观看| 亚洲成人资源网| 在线一区欧美| 亚洲人屁股眼子交8| 亚洲欧美日韩天堂| 欧美激情综合| 99精品国产高清一区二区| 国产一区99| 亚洲欧美日韩视频一区| 亚洲电影一级黄| 欧美在线播放一区| 国产精品igao视频网网址不卡日韩| 在线电影欧美日韩一区二区私密| 亚洲一区二区日本| 亚洲国产高清一区| 免费观看成人网| 亚洲精品极品| 9人人澡人人爽人人精品| 国产精品一二一区| 免费成人激情视频| 欧美日韩伊人| 久久久久久穴| 欧美国产另类| 欧美中文字幕精品| 韩国一区二区三区在线观看| 欧美日韩性生活视频| 羞羞色国产精品| 欧美在线视频导航| 一本不卡影院| 日韩一级黄色片| 亚洲第一在线综合在线| 亚洲精品在线视频观看| 国产视频精品xxxx| 亚洲视频网在线直播| 久久亚洲春色中文字幕| 亚洲精品视频免费| 久久久91精品国产一区二区精品| 在线视频亚洲| 欧美肥婆在线| 欧美99在线视频观看| 国产麻豆午夜三级精品| 这里只有精品视频| 一本色道久久综合亚洲精品不卡| 久久青青草综合| 欧美怡红院视频| 久久精品毛片| 久久天天综合| 在线不卡a资源高清| 欧美一区二区三区日韩视频| 亚洲三级视频| 欧美三区在线观看| 亚洲视频精选| 午夜精品国产精品大乳美女| 国产精品久久久久久久久久久久久 | 国产精品你懂得| 中文在线一区| 欧美中文在线免费| 亚洲国产日韩精品| 国产精品ⅴa在线观看h| 亚洲砖区区免费| 久久综合狠狠综合久久综合88 | 欧美中文字幕视频| 亚洲激情成人在线| 国产精品国产三级国产普通话蜜臀| 亚洲男人的天堂在线观看| 欧美区一区二| 亚洲欧美日韩国产成人| 欧美韩日视频| 久久久青草青青国产亚洲免观| 免费黄网站欧美| 校园春色国产精品| 亚洲美女中出| 国一区二区在线观看| 欧美日韩色一区| 男人的天堂亚洲在线| 午夜精品视频在线观看一区二区| 亚洲人www| 久久夜色精品国产亚洲aⅴ| 亚洲中午字幕| 亚洲一区二区在线播放| 亚洲精品影视| 9l国产精品久久久久麻豆| 亚洲黄色成人久久久| 在线精品国产欧美| 黄色成人片子| 1024亚洲| 亚洲国产精品毛片| 亚洲三级免费观看| 日韩视频在线你懂得| 亚洲巨乳在线| 亚洲一区视频| 久久综合国产精品| 91久久国产综合久久91精品网站| 快she精品国产999| 亚洲欧洲一区| 亚洲一区在线直播| 久久精品盗摄| 欧美电影在线观看| 国产精品日本欧美一区二区三区| 国产日韩精品入口| 亚洲国产成人高清精品| 午夜日韩在线观看| 久久精品国产亚洲一区二区三区 | 欧美日韩国产综合在线| 亚洲综合色视频| 欧美日韩一区二区视频在线 | 亚洲天堂成人在线视频| 久久成人精品一区二区三区| 久久久噜噜噜久久久| 日韩写真在线| 蜜臀av在线播放一区二区三区 | 欧美日本一道本| 激情小说另类小说亚洲欧美 | 久久精品一级爱片| 国产精品久久久久久久午夜 | 欧美日韩一区综合| 亚洲高清视频在线| 亚洲国产电影| 久久一区二区精品| 亚洲激情在线激情| 欧美激情1区2区3区| 理论片一区二区在线| 国产亚洲一区在线| 久久色中文字幕| 久久免费高清视频| 亚洲国产精品毛片| 99亚洲视频| 国产精品人人做人人爽| 性做久久久久久久久| 久久精品国产96久久久香蕉| 亚洲大片在线| 宅男在线国产精品| 亚洲国产欧美一区二区三区久久 | 91久久黄色| 美女网站在线免费欧美精品| 老色批av在线精品| 一个色综合导航| 亚洲激情女人| 卡通动漫国产精品| 欧美成人精品1314www| 在线观看欧美精品| 久久综合九色综合网站| 亚洲一区二区成人| 久久永久免费| 免费高清在线一区| 狠狠色狠狠色综合人人| 午夜精品久久久久99热蜜桃导演| 亚洲精品久久| 免费观看一级特黄欧美大片| 亚洲综合色网站| 欧美丝袜一区二区三区| 最新国产拍偷乱拍精品| 国产午夜一区二区三区| 99re6热在线精品视频播放速度| 亚洲高清成人| 久久aⅴ国产紧身牛仔裤| 久久精品综合| 黄色精品一区| 美脚丝袜一区二区三区在线观看| 久久综合福利| 亚洲国产精品毛片| 欧美黄色成人网| 日韩视频精品在线| 久久av一区| 亚洲精选在线观看| 国产精品国产三级国产aⅴ无密码| 美女精品一区| 中文在线不卡| 在线观看一区| 欧美日韩亚洲视频| 亚洲先锋成人| 免费欧美在线视频| 中文网丁香综合网| 国产免费亚洲高清| 男女激情视频一区| 在线中文字幕日韩| 久久精品91久久香蕉加勒比|