• <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>

            Khan's Notebook GCC/GNU/Linux Delphi/Window Java/Anywhere

            路漫漫,長(zhǎng)修遠(yuǎn),我們不能沒(méi)有錢
            隨筆 - 173, 文章 - 0, 評(píng)論 - 257, 引用 - 0
            數(shù)據(jù)加載中……

            System V信號(hào)燈(節(jié)選自u(píng)nix網(wǎng)絡(luò)編程卷2-進(jìn)程間通信)

            System V信號(hào)燈(節(jié)選自u(píng)nix網(wǎng)絡(luò)編程卷2-進(jìn)程間通信)

            System V信號(hào)燈通過(guò)定義如下概念增加了另外一級(jí)復(fù)雜度:
                計(jì)數(shù)信號(hào)燈集(set of counting semaphores): 一個(gè)或者多個(gè)信號(hào)燈(構(gòu)成一個(gè)集合),其中每個(gè)都
            是計(jì)算信號(hào)燈. 每個(gè)集合的信號(hào)燈數(shù)存在一個(gè)限制, 一般在25個(gè)的數(shù)量級(jí)上. 當(dāng)我們談?wù)?System V
            信號(hào)燈"時(shí), 所指的是計(jì)數(shù)信號(hào)燈集. 當(dāng)我們談?wù)?Posix 信號(hào)燈"時(shí), 所指的是單個(gè)計(jì)數(shù)信號(hào)燈.

                對(duì)于系統(tǒng)中的每個(gè)信號(hào)燈集, 內(nèi)核維護(hù)一個(gè)如下的信息結(jié)構(gòu), 它定義在<sys/sem.h>頭文件中:
              struct semid_ds{
                struct ipc_perm sem_perm;   //operation permission struct
                struct sem      *sem_base;  //ptr to array of semaphores in set
                ushort          sem_nsems;  //of semaphores in set
                time_t          sem_otime;  //time of last semop()
                time_t          sem_ctime;  //time of creation or last IPC_SET
              };

                其中的ipc_perm結(jié)構(gòu)描述對(duì)于當(dāng)前這個(gè)特定的信號(hào)燈的訪問(wèn)權(quán)限.
              struct ipc_perm{
                uid_t   uid;  // owner's effective user id
                gid_t   gid;  // owner's effective group id
                uid_t   cuid; // creator's effective user id
                gid_t   cgid; // creator's effective group id
                mode_t  mode; // access modes
                ulong   seq;  // slot usage sequence number
                key_t   key;  // key
              };

                sem結(jié)構(gòu)是內(nèi)核用于維護(hù)某個(gè)給定信號(hào)燈的一組值的內(nèi)部數(shù)據(jù)結(jié)構(gòu).一個(gè)信號(hào)燈集的每個(gè)成員由如
            下結(jié)構(gòu)描述:
              struct sem{
                ushort_t      semval;   //semaphore value, nonnegative
                short         sempid;   //PID of last successful semop(), SETVAL, SETALL
                ushort_t      semncnt;  //awalting semval > current value
                ushort_t      semzcnt;  //awalting semval =0
              };
                注意sem_base含有指向某個(gè)sem_base含有指向某個(gè)sem結(jié)構(gòu)數(shù)組的指針, 當(dāng)前信號(hào)燈集中的每個(gè)信
            號(hào)燈對(duì)應(yīng)其中一個(gè)數(shù)組元素.
                除了維護(hù)一個(gè)信號(hào)燈集中每個(gè)信號(hào)燈的實(shí)際值之外, 內(nèi)核還給該集合中每個(gè)信號(hào)燈維護(hù)另外三個(gè)
            信息, 對(duì)其值執(zhí)行最后一次操作的進(jìn)程的pid, 等待其值增長(zhǎng)的進(jìn)程數(shù)計(jì)數(shù)以及等待其值變?yōu)?的pid計(jì)
            數(shù).

            ///////////////////////////////////////////////////////////

                              semget 函數(shù)

              semget函數(shù)創(chuàng)建一個(gè)信號(hào)燈集或訪問(wèn)一個(gè)已存在的信號(hào)燈集
            #include <sys/sem.h>
            int semget(key_t key, int nsems, int oflag);
            @return int 成功時(shí)返回非負(fù)數(shù)標(biāo)識(shí)符, 出錯(cuò)時(shí)返回-1

                返回值是一個(gè)稱為信號(hào)燈標(biāo)識(shí)符(semaphore identifier)的整數(shù), semop和semctl函數(shù)將使用它.
                指定key為IPC_PRIVATE保證創(chuàng)建一個(gè)唯一的IPC對(duì)象. 沒(méi)有一對(duì)pahtname和id的組合會(huì)導(dǎo)致ftok產(chǎn)
            生IPC_PRIVATE這個(gè)鍵值.
                nsems 指定集合中的信號(hào)燈數(shù). 如果我們不創(chuàng)建一個(gè)新信號(hào)燈集, 而只是訪問(wèn)一個(gè)已存在的信號(hào)
            燈集合, 那就可以指定該參數(shù)為0, 一旦創(chuàng)建完畢, 就不能改變其中的信號(hào)燈值.
                oflag SEM_R和SEM_A常值的組合. 其中R代表read, A代表alter. 他們還可以與
            IPC_CREAT|IPC_EXCL按位或.
                設(shè)置oflag參數(shù)的IPC_CREAT位但不設(shè)置它的IPC_EXCL位時(shí), 如果所指定的IPC對(duì)象不存在, 那就創(chuàng)
            建一個(gè)新對(duì)象, 否則返回該對(duì)象.
                同時(shí)設(shè)置oflag的IPC_CREAT和IPC_EXCL位時(shí), 如果所指定鍵的IPC對(duì)象不存在, 那么就創(chuàng)建一個(gè)新
            的對(duì)象, 否則, 返回一個(gè)EEXIST錯(cuò)誤, 因?yàn)樵搶?duì)象已存在.
                設(shè)置IPC_EXCL位, 但不設(shè)置IPC_CREAT位是沒(méi)有意義的.
                當(dāng)實(shí)際操作為創(chuàng)建一個(gè)新的信號(hào)燈集時(shí), 相應(yīng)的semid_ds結(jié)構(gòu)的以下成員將被初始化:
                .sem_perm結(jié)構(gòu)中的uid和cuid成員被置為調(diào)用進(jìn)程的有效uid, gid和cgid成員被置為調(diào)用進(jìn)程的

            有效gid
                .oflag參數(shù)中的讀寫權(quán)限位存入sem_perm.mode
                .sem_otime 被置為0. sem_ctime則被置為當(dāng)前時(shí)間.
                .sem_nsems 被置為nsems參數(shù)的值
                .與該集合中每個(gè)信號(hào)燈關(guān)聯(lián)的哥哥sem結(jié)構(gòu)并不初始化. 這些結(jié)構(gòu)是在SETVAL或SETALL命令調(diào)用

            semctl時(shí)初始化的.
                System V信號(hào)燈設(shè)計(jì)中, 創(chuàng)建一個(gè)信號(hào)燈集(semget)并將它初始化(semctl)需兩次函數(shù)調(diào)用是一
            個(gè)致命的缺陷. 一個(gè)不完備的解決方案是: 在調(diào)用semget時(shí)指定IPC_CREATE|IPC_EXCL標(biāo)志, 只有一個(gè)
            進(jìn)程(首先調(diào)用semget的那個(gè)進(jìn)程)創(chuàng)建所需信號(hào)燈. 該進(jìn)程隨后初始化該信號(hào)燈, 其他進(jìn)程會(huì)收到來(lái)
            自semget的一個(gè)EEXIST錯(cuò)誤, 于是再次調(diào)用semget, 不過(guò)這次調(diào)用既不指定IPC_CREATE, 也不指定
            IPC_EXCL.

                然而競(jìng)爭(zhēng)狀態(tài)依然存在, 假設(shè)有倆個(gè)進(jìn)程幾乎同時(shí)嘗試創(chuàng)建并初始化一個(gè)只有單成員信號(hào)燈集,
            兩者都執(zhí)行如下幾行標(biāo)了號(hào)的代碼:
            1   oflag = IPC_CREAT | IPC_EXCL | SVSEM_MODE;
            2   if( (semid = semget(key, 1, oflag))>=0 ) { // success, we are the first, so initialze
            3     arg.val=1;
            4     semctl(semid, 0, SETVAL, arg);
            5   } else if(errno == EEXIST){
                  //already exists, just open
            6     semid = semget(key, 1, SVSEM_MODE);
            7   } else
            8     err_sys("semget error");
            9   semop(semid, ....);  // decrement the semaphore by 1

            那么如下情況可能發(fā)生:
             1.第一個(gè)進(jìn)程執(zhí)行1-3行, 然后被內(nèi)核阻止執(zhí)行.
             2.內(nèi)核啟動(dòng)第二個(gè)進(jìn)程, 執(zhí)行1 2 5 6 9行

                盡管成功創(chuàng)建該信號(hào)燈的第一個(gè)進(jìn)程將是初始化該信號(hào)燈的唯一進(jìn)程, 但是由于它完成創(chuàng)建和初
            始化操作需要兩個(gè)步驟, 因此, 內(nèi)核有可能在倆步驟之間把上下文切換到另一個(gè)進(jìn)程. 這個(gè)新切換來(lái)
            運(yùn)行的進(jìn)程可以隨后使用該信號(hào)燈(第9行), 但是該信號(hào)燈的值尚未由第一個(gè)進(jìn)程初始化, 當(dāng)?shù)诙€(gè)進(jìn)
            程執(zhí)行第9行時(shí), 該信號(hào)燈的值是不確定的.
                幸運(yùn)的是存在繞過(guò)這個(gè)競(jìng)爭(zhēng)狀態(tài)的方法. 當(dāng)semget創(chuàng)建一個(gè)新的信號(hào)燈集時(shí), 其semid_ds結(jié)構(gòu)的
            sem_otime成員保證被置為0. (System V手冊(cè), XPG3和Unix98標(biāo)準(zhǔn)也這么說(shuō)) 該成員只是在semop調(diào)用
            成功時(shí)才被置為當(dāng)前值. 因此, 上面的例子中的第二個(gè)進(jìn)程成功的再次調(diào)用semget(第6行)后, 必須以
            ICP_STAT命令調(diào)用semctl. 然后等待sem_otime變?yōu)榉橇阒? 到時(shí)就可以判定該信號(hào)燈已被初始化, 而
            且對(duì)他初始化的那個(gè)進(jìn)程已經(jīng)成功調(diào)用semop. 這意味著創(chuàng)建該信號(hào)燈的那個(gè)進(jìn)程必須初始化它的值,
            而且必須在任何其他進(jìn)程可以使用該信號(hào)燈之前調(diào)用semop.

            #include "unpipc.h"
            #include "semaphore.h"
            #include <stdarg.h>
            #define  MAX_TRIES 10

            union semun {
              int              val;       /* for SETVAL */
              struct semid_ds  *buf;      /* for IPC_STAT and IPC_SET */
              unsigned short   *array;    /* for GETALL and SETALL */
            };

            sem_t* sem_open( const char *pathname, int oflag, ...){
              int i, fd, semflag, semid, save_errno;
              key_t            key;
              mode_t           mode;
              va_list          ap
              sem_t            *sem;
              union semun      arg;
              unsigned int     value;
              struct semid_ds  seminfo;
              struct sembuf    initop;
             
              // no mode for sem_open() w/out O_CREAT; guess
              semflag = SVSEM_MODE;
              semid  = -1;
              if(oflag & CREAT){
                va_start(ap, oflag); // init ap to final named argument
                mode = va_arg(ap, va_mode_t);
                value = va_arg(ap, unsigned int);
                va_end(ap);

                // convert to key that will identify System V semaphore
                if( (fd = open(pathname, oflag, mode)) == -1 )
                  return(SEM_FAILED);
                close(fd);

                if( (key = ftok(pathname, 0)) ==(key_t)-1 )
                  return(SEM_FAILED);
                
                semflag = IPC_CREATE | (mode & 0777);
                if(oflag & O_EXCL)
                  semflag = semflag | IPC_EXCL;

                //create the System V semaphore with IPC_EXCL
                if( (semid = semget(key, 1, semflag|IPC_EXCL)) >= 0 ){
                  //success, we are the first so initialize to 0
                  arg.val = 0;
                  if( semctl(semid, 0, SETVAL, arg) == -1)
                    goto err;
                    // then increment by value set sem_otime nonzore
                  if(value > SEMVMX){
                    errno = EINVAL;
                    got err;
                  }
                  initop.sem_num = 0;
                  initop.sem_op = value;
                  initop.sem_flag = 0;
                  if( semop(semid, &initop, 1) == -1 )
                    goto err;
                  goto finish;
                } else if( errno != EEXIST || (semflag & IPC_EXCL) != 0 )
                  goto err;
                  // else fall through
              }
              .....
            }
            // sem_open函數(shù), 前半部分[my_pxsem_svsem/sem_open.c]


            /////////////////////////////////////////////////////
                         semop 函數(shù)

                使用semget打開(kāi)一個(gè)信號(hào)燈集后, 對(duì)其中一個(gè)或多個(gè)信號(hào)燈的操作就使用semop函數(shù)來(lái)執(zhí)行
            #include <sys/sem.h>
            int semop(int semid, struct sembuf *opsptr, size_t nops);
            @return int 成功時(shí)返回0, 出錯(cuò)時(shí)返回-1

              opsstr指向一個(gè)如下結(jié)構(gòu)的數(shù)組:
              struct sembuf{
                short sem_num;  // semaphore number : 0, 1..., nsems-1
                short sem_op;   // semaphore operation <0,0>0
                short sem_flg;  // operation flags: 0, IPC_NOWAIT, SEM_UNDO
              }

              nops 指出由opsptr指向的sembuf結(jié)構(gòu)數(shù)組中元素的數(shù)目. 該數(shù)組中的每個(gè)元素給目標(biāo)信號(hào)燈集中某
            個(gè)特定的信號(hào)燈指定一個(gè)操作. 這個(gè)特定的信號(hào)燈由sembuf.sem_num指定, 0代表第一個(gè)元素, 1代表
            第二個(gè)元素, 依次類推, 一直到nsems-1, 其中nsems是目標(biāo)信號(hào)燈集中成員信號(hào)燈的數(shù)目(創(chuàng)建時(shí)
            semget的第二個(gè)參數(shù)).
                我們僅僅保證sembuf結(jié)構(gòu)含有所給出的三個(gè)成員. 它可能還含有其他成員, 而哥哥成員并不保證
            以我們給出的順序排序. 這意味著我們不能靜態(tài)初始化這種結(jié)構(gòu), 例如:
              struct sembuf ops = {0, 1, SEM_UNDO}; //error
                而是必須使用運(yùn)行時(shí)初始化的方法, 給每個(gè)成員賦值.
                傳遞給semop函數(shù)的操作數(shù)組由內(nèi)核保證原子的執(zhí)行, 內(nèi)核或者完成所有指定操作, 或者什么操作
            都不做.
                每個(gè)特定的操作是由sem_op的值確定的, 它可以是負(fù)數(shù), 0 或者正數(shù), 在稍后的討論中, 我們將
            使用如下術(shù)語(yǔ):
              .semval : 信號(hào)燈的當(dāng)前值
              .semncnt: 等待semval變?yōu)榇笥谄洚?dāng)前值的線程數(shù)
              .semzcnt: 等待semval變?yōu)?的線程數(shù)
              .semadj : 所指定信號(hào)燈針對(duì)調(diào)用進(jìn)程的調(diào)整值. 只有在對(duì)應(yīng)本操作的sembuf結(jié)構(gòu)的sem_flg成員中
            指定SEM_UNDO標(biāo)志后, semadj才會(huì)更新. 這是一個(gè)概念性的變量, 它由內(nèi)核為再其某個(gè)信號(hào)燈操作中
            指定了SEM_UNDO標(biāo)志的每個(gè)進(jìn)程維護(hù);具有semadj這個(gè)名字的結(jié)構(gòu)成員不必存在(調(diào)用進(jìn)程終止時(shí),
            semadj加到相應(yīng)信號(hào)燈的semval上, 要是調(diào)用進(jìn)程對(duì)某個(gè)信號(hào)燈的全部操作都指定SEM_UNDO標(biāo)志, 那
            么該進(jìn)程終止后, 該信號(hào)燈的值就會(huì)變得像根本沒(méi)有運(yùn)行過(guò)進(jìn)程一樣, 這就是UNDO的本意)
              .使得一個(gè)給定信號(hào)燈操作非阻塞的方法是, 再對(duì)應(yīng)的sembuf.sem_flg成員中指定IPC_NOWAIT標(biāo)志.

            指定了該標(biāo)志的情況下, 如果不把調(diào)用線程投入睡眠, 就完成不了這個(gè)給定操作, 那么semop將返回一
            個(gè)EAGAIN錯(cuò)誤.
              .當(dāng)一個(gè)線程被投入睡眠以等待某個(gè)信號(hào)燈操作的完成時(shí)(我們將看到該線程既可等待這個(gè)信號(hào)燈值
            變?yōu)?, 也可等待它變?yōu)榇笥?), 如果它捕獲了一個(gè)信號(hào), 那么其信號(hào)處理程序的返回將中斷引起睡眠
            的semop函數(shù), 該函數(shù)于是返回了一個(gè)EINTR錯(cuò)誤, semop是需被捕獲的信號(hào)中斷的慢系統(tǒng)調(diào)用(slow
            system call).
              .當(dāng)一個(gè)線程被投入睡眠以等待某個(gè)信號(hào)燈操作的完成時(shí), 如果該信號(hào)燈被另外某個(gè)線程或進(jìn)程從進(jìn)
            程從系統(tǒng)中刪除, 那么引起睡眠的semop函數(shù)將返回一個(gè)EIDRM錯(cuò)誤, 表示identifier removed(標(biāo)識(shí)符
            已刪除)"

                現(xiàn)在描述semop的操作, 它基于每個(gè)具體指定的sem_op操作的三個(gè)可能值: 正數(shù), 0, 負(fù)數(shù).
              1.如果sem_op是正數(shù), 其值就加到semval上, 這對(duì)應(yīng)于釋放由某個(gè)信號(hào)燈控制的資源
                如果指定了SEM_UNDO標(biāo)志, 那就從相應(yīng)信號(hào)燈的semadj值中減掉sem_op的值
              2.如果sem_op是0, 那么調(diào)用者希望等待到semval變?yōu)?. 如果semval已經(jīng)是0, 那就立即返回
                如果semval不為0, 相應(yīng)信號(hào)燈的semzcnt值就加1, 調(diào)用線程則阻塞到semval變?yōu)?(到那時(shí), 相應(yīng)

            信號(hào)燈的semzcnt值再減1). 前面已經(jīng)提到, 如果指定了IPC_NOWAIT標(biāo)志, 調(diào)用線程就不會(huì)被投入睡眠
            . 如果某個(gè)被捕獲的信號(hào)中斷了引起睡眠的semop函數(shù), 或者相應(yīng)的信號(hào)燈被刪除, 那么該函數(shù)將過(guò)早
            的返回一個(gè)錯(cuò)誤.
              3.如果sem_op是負(fù)數(shù), 那么調(diào)用者希望等待semval變?yōu)榇笥诨虻扔趕em_op的絕對(duì)值.這對(duì)應(yīng)于分配資
            源.
                如果semval大于或等于sem_op的絕對(duì)值, 那就從semval中減掉sem_op的絕對(duì)值.
                如果指定了SEM_UNDO標(biāo)志, 那么sem_op的絕對(duì)值就加到相應(yīng)信號(hào)燈的semadj值上.
                如果semval小于sem_op的絕對(duì)值, 相應(yīng)信號(hào)燈的semncnt值就加1, 調(diào)用線程則被阻塞到semval變
            為大于或等于sem_op的絕對(duì)值. 到那時(shí),該線程將被解阻塞, semval中減掉sem_op的絕對(duì)值, 相應(yīng)信號(hào)
            燈的semncnt值將減1. 如果指定了SEM_UNDO標(biāo)志, 那么sem_op的絕對(duì)值將加到相應(yīng)信號(hào)燈的semadj值
            上. 前面已經(jīng)提到, 如果指定了IPC_NOWAIT標(biāo)志, 調(diào)用線程就不會(huì)投入睡眠. 另外, 如果某個(gè)被捕獲
            的信號(hào)中斷了引起睡眠的sem_op函數(shù), 或者相應(yīng)的信號(hào)燈被刪除, 那么該函數(shù)將過(guò)早的返回一個(gè)錯(cuò)誤.


            /////////////////////////////////////////////////////
                            semctl 函數(shù)

                semctl函數(shù)對(duì)一個(gè)信號(hào)燈執(zhí)行各種控制操作.

            #include <sys/sem.h>
            int semctl( int semid, int semnum, int cmd, .../* union semun arg*/ );
            @return int 成功時(shí)為非負(fù)值, 出錯(cuò)時(shí)為-1

              semid  標(biāo)識(shí)需控制其操作的信號(hào)燈集
              semnum 標(biāo)示該信號(hào)燈集中某個(gè)成員(0, 1, ....nsems-1). semnum值僅用于GETVAL,

            SETVAL,GETNCNT,GETZCNT,SETPID命令
              第四個(gè)參數(shù)為可選, 取決于第三個(gè)參數(shù)cmd(參見(jiàn)下面給出的聯(lián)合中的注釋).
            union semun {
              int              val;       /* used for SETVAL only*/
              struct semid_ds  *buf;      /* used for IPC_STAT and IPC_SET */
              unsigned short   *array;    /* used for GETALL and SETALL */
            };
                這個(gè)union并沒(méi)有出現(xiàn)再任何系統(tǒng)頭文件中, 因而必須由應(yīng)用程序聲明.它是以值傳遞的, 而不是
            以引用傳遞. 也就是說(shuō)作為參數(shù)的是這個(gè)union的值, 而不是指向它的指針.
                (不幸的是, 有些系統(tǒng)(FreeBSD和Linux)在<sys/sem.h>頭文件中定義了這個(gè)union, 從而造成編寫
            可移植性代碼的困難. 盡管由這個(gè)系統(tǒng)頭文件來(lái)聲明union semun確實(shí)有足夠的理由, Unix 98還是聲
            稱它必須由應(yīng)用程序顯式聲明).

                System V支持下列cmd值, 除非另外聲明, 否則返回值為0表示成功, 返回值為-1 表示失敗.

              GETVAL   把semval的當(dāng)前值作為函數(shù)返回值返回, 既然信號(hào)燈絕不會(huì)是負(fù)數(shù)(semval被聲明為
            unsigned short), 因此成功的返回值總是非負(fù)數(shù).

              SETVAL   把semval值設(shè)置為arg.val. 如果操作成功, 那么相應(yīng)信號(hào)燈在所在進(jìn)程中的調(diào)整值
            (semadj)將被置為0;

              GETPID   把sempid的當(dāng)前值作為函數(shù)返回值返回.
              GETNCNT  把semncnt的當(dāng)前值作為函數(shù)返回值返回.
              GETZCNT  把semzcnt的當(dāng)前值作為函數(shù)返回值返回.

              GETALL   返回指定信號(hào)燈集中每個(gè)成員的semval值. 這些值通過(guò)arg.arry指針?lè)祷? 函數(shù)本身的返
            回值為0, 注意, 調(diào)用者必須分配足夠容納所指定信號(hào)燈集的所有成員的semval值的一個(gè)unsigned
            short[], 然后把a(bǔ)rg.array設(shè)置成指向這個(gè)數(shù)組.

              SETALL   設(shè)置所指定信號(hào)燈集中每個(gè)成員的semval值. 這些值是通過(guò)arg.array數(shù)組指定的
              IPC_RMID 把由semid指定的信號(hào)燈集從系統(tǒng)中刪除掉.

              IPC_SET  設(shè)置所指定信號(hào)燈集的semid_ds結(jié)構(gòu)中的以下三個(gè)成員: sem_perm.uid, sem_perm.gid,
            sem_perm.mode, 這些值由arg.buf參數(shù)指向的結(jié)構(gòu)中的相應(yīng)成員. semid_ds.sem_ctime也被設(shè)置成當(dāng)
            前值.

              IPC_STAT (通過(guò)arg.buf參數(shù)) 返回所指定信號(hào)燈集的當(dāng)前semid_ds結(jié)構(gòu). 注意, 調(diào)用者必須首先分
            配一個(gè)semid_ds結(jié)構(gòu), 并把a(bǔ)rg.buf設(shè)置成指向這個(gè)結(jié)構(gòu).



            posted on 2009-11-27 00:57 Khan 閱讀(1935) 評(píng)論(0)  編輯 收藏 引用 所屬分類: GCC/G++

            久久亚洲日韩精品一区二区三区| 精品国产乱码久久久久久1区2区 | 久久黄视频| 久久精品一区二区影院| 亚洲国产婷婷香蕉久久久久久| 久久丫精品国产亚洲av| 性做久久久久久免费观看| 人妻无码αv中文字幕久久 | 亚洲午夜久久久精品影院 | 久久亚洲精品视频| 久久亚洲国产成人影院| 岛国搬运www久久| 亚洲精品高清国产一线久久| 久久久久久亚洲精品不卡| 久久婷婷五月综合色高清| 三级片免费观看久久| 色综合久久综合网观看| 丁香色欲久久久久久综合网| 久久性精品| 国产国产成人久久精品| 九九99精品久久久久久| 久久婷婷五月综合国产尤物app| 久久精品不卡| 久久无码av三级| 蜜桃麻豆www久久| 国产69精品久久久久777| 精产国品久久一二三产区区别| 久久青青草原精品国产软件| 久久99国产一区二区三区| 久久久久AV综合网成人| 久久久噜噜噜www成人网| 精品一二三区久久aaa片| 久久精品久久久久观看99水蜜桃| 色综合合久久天天给综看| 久久久久亚洲精品天堂久久久久久| 91亚洲国产成人久久精品| 国产高清美女一级a毛片久久w | 久久se精品一区精品二区国产| 久久中文娱乐网| 国产亚洲精久久久久久无码AV| 国产成人久久777777|