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

            Linux程序設(shè)計(jì)入門(mén)--消息管理


            前言:Linux下的進(jìn)程通信(IPC)
            Linux下的進(jìn)程通信(IPC)
            POSIX無(wú)名信號(hào)量
            System V信號(hào)量
            System V消息隊(duì)列
            System V共享內(nèi)存

            1。POSIX無(wú)名信號(hào)量 如果你學(xué)習(xí)過(guò)操作系統(tǒng),那么肯定熟悉PV操作了.PV操作是原子
            操作.也就是操作是不可以中斷的,在一定的時(shí)間內(nèi),只能夠有一個(gè)進(jìn)程的代碼在CPU上面
            執(zhí)行.在系統(tǒng)當(dāng)中,有時(shí)候?yàn)榱隧樌氖褂煤捅Wo(hù)共享資源,大家提出了信號(hào)的概念. 假設(shè)
            我們要使用一臺(tái)打印機(jī),如果在同一時(shí)刻有兩個(gè)進(jìn)程在向打印機(jī)輸出,那么最終的結(jié)果會(huì)
            是什么呢.為了處理這種情況,POSIX標(biāo)準(zhǔn)提出了有名信號(hào)量和無(wú)名信號(hào)量的概念,由于Li
            nux只實(shí)現(xiàn)了無(wú)名信號(hào)量,我們?cè)谶@里就只是介紹無(wú)名信號(hào)量了. 信號(hào)量的使用主要是用
            來(lái)保護(hù)共享資源,使的資源在一個(gè)時(shí)刻只有一個(gè)進(jìn)程所擁有.為此我們可以使用一個(gè)信號(hào)
            燈.當(dāng)信號(hào)燈的值為某個(gè)值的時(shí)候,就表明此時(shí)資源不可以使用.否則就表>示可以使用.
            為了提供效率,系統(tǒng)提供了下面幾個(gè)函數(shù)
            POSIX的無(wú)名信號(hào)量的函數(shù)有以下幾個(gè):
            1. #include <semaphore.h>    
            2. int sem_init(sem_t *sem,int pshared,unsigned int value);    
            3. int sem_destroy(sem_t *sem);    
            4. int sem_wait(sem_t *sem);    
            5. int sem_trywait(sem_t *sem);    
            6. int sem_post(sem_t *sem);    
            7. int sem_getvalue(sem_t *sem);    

            sem_init創(chuàng)建一個(gè)信號(hào)燈,并初始化其值為value.pshared決定了信號(hào)量能否在幾個(gè)進(jìn)程
            間共享.由于目前Linux還沒(méi)有實(shí)現(xiàn)進(jìn)程間共享信號(hào)燈,所以這個(gè)值只能夠取0. sem_dest
            roy是用來(lái)刪除信號(hào)燈的.sem_wait調(diào)用將阻塞進(jìn)程,直到信號(hào)燈的值大于0.這個(gè)函數(shù)返回
            的時(shí)候自動(dòng)的將信號(hào)燈的值的件一.sem_post和sem_wait相反,是將信號(hào)燈的內(nèi)容加一同
            時(shí)發(fā)出信號(hào)喚醒等待的進(jìn)程..sem_trywait和sem_wait相同,不過(guò)不阻塞的,當(dāng)信號(hào)燈的值
            為0的時(shí)候返回EAGAIN,表示以后重試.sem_getvalue得到信號(hào)燈的值.
            由于Linux不支持,我們沒(méi)有辦法用源程序解釋了.
            這幾個(gè)函數(shù)的使用相當(dāng)簡(jiǎn)單的.比如我們有一個(gè)程序要向一個(gè)系統(tǒng)打印機(jī)打印兩頁(yè).我們
            首先創(chuàng)建一個(gè)信號(hào)燈,并使其初始值為1,表示我們有一個(gè)資源可用.然后一個(gè)進(jìn)程調(diào)用se
            m_wait由于這個(gè)時(shí)候信號(hào)燈的值為1,所以這個(gè)函數(shù)返回,打印機(jī)開(kāi)始打印了,同時(shí)信號(hào)燈
            的值為0 了. 如果第二個(gè)進(jìn)程要打印,調(diào)用sem_wait時(shí)候,由于信號(hào)燈的值為0,資源不可
            用,于是被阻塞了.當(dāng)?shù)谝粋€(gè)進(jìn)程打印完成以后,調(diào)用sem_post信號(hào)燈的值為1了,這個(gè)時(shí)候
            系統(tǒng)通知第二個(gè)進(jìn)程,于是第二個(gè)進(jìn)程的sem_wait返回.第二個(gè)進(jìn)程開(kāi)始打印了.
            不過(guò)我們可以使用線(xiàn)程來(lái)解決這個(gè)問(wèn)題的.我們會(huì)在后面解釋什么是線(xiàn)程的.編譯包含上
            面這幾個(gè)函數(shù)的程序要加上 -lrt選賢,以連接librt.so庫(kù)
            2。System V信號(hào)量 為了解決上面哪個(gè)問(wèn)題,我們也可以使用System V信號(hào)量.很幸運(yùn)的
            是Linux實(shí)現(xiàn)了System V信號(hào)量.這樣我們就可以用實(shí)例來(lái)解釋了. System V信號(hào)量的函
            數(shù)主要有下面幾個(gè).
             
            1. #include <sys/types.h>    
            2. #include <sys/ipc.h>    
            3. #include <sys/sem.h>    
            4. key_t ftok(char *pathname,char proj);    
            5. int semget(key_t key,int nsems,int semflg);    
            6. int semctl(int semid,int semnum,int cmd,union semun arg);    
            7. int semop(int semid,struct sembuf *spos,int nspos);    
            8. struct sembuf {    
            9. short sem_num; /* 使用那一個(gè)信號(hào) */    
            10. short sem_op; /* 進(jìn)行什么操作 */    
            11. short sem_flg; /* 操作的標(biāo)志 */    
            12. };    

            ftok函數(shù)是根據(jù)pathname和proj來(lái)創(chuàng)建一個(gè)關(guān)鍵字.semget創(chuàng)建一個(gè)信號(hào)量.成功時(shí)返回
            信號(hào)的ID,key是一個(gè)關(guān)鍵字,可以是用ftok創(chuàng)建的也可以是IPC_PRIVATE表明由系統(tǒng)選用
            一個(gè)關(guān)鍵字. nsems表明我們創(chuàng)建的信號(hào)個(gè)數(shù).semflg是創(chuàng)建的權(quán)限標(biāo)志,和我們創(chuàng)建一個(gè)
            文件的標(biāo)志相同.
            semctl對(duì)信號(hào)量進(jìn)行一系列的控制.semid是要操作的信號(hào)標(biāo)志,semnum是信號(hào)的個(gè)數(shù),cm
            d是操作的命令.經(jīng)常用的兩個(gè)值是:SETVAL(設(shè)置信號(hào)量的值)和IPC_RMID(刪除信號(hào)燈).
            arg是一個(gè)給cmd的參數(shù).
            semop是對(duì)信號(hào)進(jìn)行操作的函數(shù).semid是信號(hào)標(biāo)志,spos是一個(gè)操作數(shù)組表明要進(jìn)行什么
            操作,nspos表明數(shù)組的個(gè)數(shù). 如果sem_op大于0,那么操作將sem_op加入到信號(hào)量的值中
            ,并喚醒等待信號(hào)增加的進(jìn)程. 如果為0,當(dāng)信號(hào)量的值是0的時(shí)候,函數(shù)返回,否則阻塞直
            到信號(hào)量的值為0. 如果小于0,函數(shù)判斷信號(hào)量的值加上這個(gè)負(fù)值.如果結(jié)果為0喚醒等待
            信號(hào)量為0的進(jìn)程,如果小與0函數(shù)阻塞.如果大于0,那么從信號(hào)量里面減去這個(gè)值并返回
            ..
            下面我們一以一個(gè)實(shí)例來(lái)說(shuō)明這幾個(gè)函數(shù)的使用方法.這個(gè)程序用標(biāo)準(zhǔn)錯(cuò)誤輸出來(lái)代替我
            們用的打印機(jī).
             
            1. #include <stdio.h>    
            2. #include <unistd.h>    
            3. #include <limits.h>    
            4. #include <errno.h>    
            5. #include <string.h>    
            6. #include <stdlib.h>    
            7. #include <sys/stat.h>    
            8. #include <sys/wait.h>    
            9. #include <sys/ipc.h>    
            10. #include <sys/sem.h>    
            11. #define PERMS S_IRUSR|S_IWUSR    
            12. void init_semaphore_struct(struct sembuf *sem,int semnum,    
            13. int semop,int semflg)    
            14. {    
            15. /* 初始話(huà)信號(hào)燈結(jié)構(gòu) */    
            16. sem->sem_num=semnum;    
            17. sem->sem_op=semop;    
            18. sem->sem_flg=semflg;    
            19. }    
            20. int del_semaphore(int semid)    
            21. {    
            22. /* 信號(hào)燈并不隨程序的結(jié)束而被刪除,如果我們沒(méi)刪除的話(huà)(將1改為0)   
            23. 可以用ipcs命令查看到信號(hào)燈,用ipcrm可以刪除信號(hào)燈的   
            24. */    
            25. #if 1    
            26. return semctl(semid,0,IPC_RMID);    
            27. #endif    
            28. }    
            29. int main(int argc,char **argv)    
            30. {    
            31. char buffer[MAX_CANON],*c;    
            32. int i,n;    
            33. int semid,semop_ret,status;    
            34. pid_t childpid;    
            35. struct sembuf semwait,semsignal;    
            36. if((argc!=2)||((n=atoi(argv[1]))<1))    
            37. {    
            38. fprintf(stderr,"Usage:%s number\n\a",argv[0]);    
            39. exit(1);    
            40. }    
            41. /* 使用IPC_PRIVATE 表示由系統(tǒng)選擇一個(gè)關(guān)鍵字來(lái)創(chuàng)建 */    
            42. /* 創(chuàng)建以后信號(hào)燈的初始值為0 */    
            43. if((semid=semget(IPC_PRIVATE,1,PERMS))==-1)    
            44. {    
            45. fprintf(stderr,"[%d]:Acess Semaphore Error:%s\n\a",    
            46. getpid(),strerror(errno));    
            47. exit(1);    
            48. }    
            49. /* semwait是要求資源的操作(-1) */    
            50. init_semaphore_struct(&semwait,0,-1,0);    
            51. /* semsignal是釋放資源的操作(+1) */    
            52. init_semaphore_struct(&semsignal,0,1,0);    
            53. /* 開(kāi)始的時(shí)候有一個(gè)系統(tǒng)資源(一個(gè)標(biāo)準(zhǔn)錯(cuò)誤輸出) */    
            54. if(semop(semid,&semsignal,1)==-1)    
            55. {    
            56. fprintf(stderr,"[%d]:Increment Semaphore Error:%s\n\a",    
            57. getpid(),strerror(errno));    
            58. if(del_semaphore(semid)==-1)    
            59. fprintf(stderr,"[%d]:Destroy Semaphore Error:%s\n\a",    
            60. getpid(),strerror(errno));    
            61. exit(1);    
            62. }    
            63. /* 創(chuàng)建一個(gè)進(jìn)程鏈 */    
            64. for(i=0;i<n;i++)    
            65. if(childpid=fork()) break;    
            66. sprintf(buffer,"[i=%d]-->[Process=%d]-->[Parent=%d]-->[Child=%d]\n",    
            67. i,getpid(),getppid(),childpid);    
            68. c=buffer;    
            69. /* 這里要求資源,進(jìn)入原子操作 */    
            70. while(((semop_ret=semop(semid,&semwait,1))==-1)&&(errno==EINTR));    
            71. if(semop_ret==-1)    
            72. {    
            73. fprintf(stderr,"[%d]:Decrement Semaphore Error:%s\n\a",    
            74. getpid(),strerror(errno));    
            75. }    
            76. else    
            77. {    
            78. while(*c!='\0')fputc(*c++,stderr);    
            79. /* 原子操作完成,趕快釋放資源 */    
            80. while(((semop_ret=semop(semid,&semsignal,1))==-1)&&(errno==EINTR));    
            81. if(semop_ret==-1)    
            82. fprintf(stderr,"[%d]:Increment Semaphore Error:%s\n\a",    
            83. getpid(),strerror(errno));    
            84. }    
            85. /* 不能夠在其他進(jìn)程反問(wèn)信號(hào)燈的時(shí)候,我們刪除了信號(hào)燈 */    
            86. while((wait(&status)==-1)&&(errno==EINTR));    
            87. /* 信號(hào)燈只能夠被刪除一次的 */    
            88. if(i==1)    
            89. if(del_semaphore(semid)==-1)    
            90. fprintf(stderr,"[%d]:Destroy Semaphore Error:%s\n\a",    
            91. getpid(),strerror(errno));    
            92. exit(0);    
            93. }    

            信號(hào)燈的主要用途是保護(hù)臨界資源(在一個(gè)時(shí)刻只被一個(gè)進(jìn)程所擁有).
            3。SystemV消息隊(duì)列 為了便于進(jìn)程之間通信,我們可以使用管道通信 SystemV也提供了
            一些函數(shù)來(lái)實(shí)現(xiàn)進(jìn)程的通信.這就是消息隊(duì)列.
             
            1. #include <sys/types.h>    
            2. #include <sys/ipc.h>    
            3. #include <sys/msg.h>    
            4. int msgget(key_t key,int msgflg);    
            5. int msgsnd(int msgid,struct msgbuf *msgp,int msgsz,int msgflg);    
            6. int msgrcv(int msgid,struct msgbuf *msgp,int msgsz,    
            7. long msgtype,int msgflg);    
            8. int msgctl(Int msgid,int cmd,struct msqid_ds *buf);    
            9.   
            10. struct msgbuf {    
            11. long msgtype; /* 消息類(lèi)型 */    
            12. ....... /* 其他數(shù)據(jù)類(lèi)型 */    
            13. }    

            msgget函數(shù)和semget一樣,返回一個(gè)消息隊(duì)列的標(biāo)志.msgctl和semctl是對(duì)消息進(jìn)行控制
            .. msgsnd和msgrcv函數(shù)是用來(lái)進(jìn)行消息通訊的.msgid是接受或者發(fā)送的消息隊(duì)列標(biāo)志.
            msgp是接受或者發(fā)送的內(nèi)容.msgsz是消息的大小. 結(jié)構(gòu)msgbuf包含的內(nèi)容是至少有一個(gè)
            為msgtype.其他的成分是用戶(hù)定義的.對(duì)于發(fā)送函數(shù)msgflg指出緩沖區(qū)用完時(shí)候的操作.
            接受函數(shù)指出無(wú)消息時(shí)候的處理.一般為0. 接收函數(shù)msgtype指出接收消息時(shí)候的操作.

            如果msgtype=0,接收消息隊(duì)列的第一個(gè)消息.大于0接收隊(duì)列中消息類(lèi)型等于這個(gè)值的第
            一個(gè)消息.小于0接收消息隊(duì)列中小于或者等于msgtype絕對(duì)值的所有消息中的最小一個(gè)消
            息. 我們以一個(gè)實(shí)例來(lái)解釋進(jìn)程通信.下面這個(gè)程序有server和client組成.先運(yùn)行服務(wù)
            端后運(yùn)行客戶(hù)端.
            服務(wù)端 server.c
             
            1. #include <stdio.h>    
            2. #include <string.h>    
            3. #include <stdlib.h>    
            4. #include <errno.h>    
            5. #include <unistd.h>    
            6. #include <sys/types.h>    
            7. #include <sys/ipc.h>    
            8. #include <sys/stat.h>    
            9. #include <sys/msg.h>    
            10. #define MSG_FILE "server.c"    
            11. #define BUFFER 255    
            12. #define PERM S_IRUSR|S_IWUSR    
            13. struct msgtype {    
            14. long mtype;    
            15. char buffer[BUFFER+1];    
            16. };    
            17. int main()    
            18. {    
            19. struct msgtype msg;    
            20. key_t key;    
            21. int msgid;    
            22. if((key=ftok(MSG_FILE,'a'))==-1)    
            23. {    
            24. fprintf(stderr,"Creat Key Error:%s\a\n",strerror(errno));    
            25. exit(1);    
            26. }    
            27. if((msgid=msgget(key,PERM|IPC_CREAT|IPC_EXCL))==-1)    
            28. {    
            29. fprintf(stderr,"Creat Message Error:%s\a\n",strerror(errno));    
            30. exit(1);    
            31. }    
            32. while(1)    
            33. {    
            34. msgrcv(msgid,&msg,sizeof(struct msgtype),1,0);    
            35. fprintf(stderr,"Server Receive:%s\n",msg.buffer);    
            36. msg.mtype=2;    
            37. msgsnd(msgid,&msg,sizeof(struct msgtype),0);    
            38. }    
            39. exit(0);    
            40. }    
            41. ----------------------------------------------------------------------------    

            客戶(hù)端(client.c)
             
            1. #include <stdio.h>    
            2. #include <string.h>    
            3. #include <stdlib.h>    
            4. #include <errno.h>    
            5. #include <sys/types.h>    
            6. #include <sys/ipc.h>    
            7. #include <sys/msg.h>    
            8. #include <sys/stat.h>    
            9. #define MSG_FILE "server.c"    
            10. #define BUFFER 255    
            11. #define PERM S_IRUSR|S_IWUSR    
            12. struct msgtype {    
            13. long mtype;    
            14. char buffer[BUFFER+1];    
            15. };    
            16. int main(int argc,char **argv)    
            17. {    
            18. struct msgtype msg;    
            19. key_t key;    
            20. int msgid;    
            21. if(argc!=2)    
            22. {    
            23. fprintf(stderr,"Usage:%s string\n\a",argv[0]);    
            24. exit(1);    
            25. }    
            26. if((key=ftok(MSG_FILE,'a'))==-1)    
            27. {    
            28. fprintf(stderr,"Creat Key Error:%s\a\n",strerror(errno));    
            29. exit(1);    
            30. }    
            31. if((msgid=msgget(key,PERM))==-1)    
            32. {    
            33. fprintf(stderr,"Creat Message Error:%s\a\n",strerror(errno));    
            34. exit(1);    
            35. }    
            36. msg.mtype=1;    
            37. strncpy(msg.buffer,argv[1],BUFFER);    
            38. msgsnd(msgid,&msg,sizeof(struct msgtype),0);    
            39. memset(&msg,'\0',sizeof(struct msgtype));    
            40. msgrcv(msgid,&msg,sizeof(struct msgtype),2,0);    
            41. fprintf(stderr,"Client receive:%s\n",msg.buffer);    
            42. exit(0);    
            43. }    

            注意服務(wù)端創(chuàng)建的消息隊(duì)列最后沒(méi)有刪除,我們要使用ipcrm命令來(lái)刪除的.
            4。SystemV共享內(nèi)存 還有一個(gè)進(jìn)程通信的方法是使用共享內(nèi)存.SystemV提供了以下幾個(gè)
            函數(shù)以實(shí)現(xiàn)共享內(nèi)存.
             
            1. #include <sys/types.h>    
            2. #include <sys/ipc.h>    
            3. #include <sys/shm.h>    
            4. int shmget(key_t key,int size,int shmflg);    
            5. void *shmat(int shmid,const void *shmaddr,int shmflg);    
            6. int shmdt(const void *shmaddr);    
            7. int shmctl(int shmid,int cmd,struct shmid_ds *buf);    

            shmget和shmctl沒(méi)有什么好解釋的.size是共享內(nèi)存的大小. shmat是用來(lái)連接共享內(nèi)存
            的.shmdt是用來(lái)斷開(kāi)共享內(nèi)存的.不要被共享內(nèi)存詞語(yǔ)嚇倒,共享內(nèi)存其實(shí)很容易實(shí)現(xiàn)和
            使用的.shmaddr,shmflg我們只要用0代替就可以了.在使用一個(gè)共享內(nèi)存之前我們調(diào)用s
            hmat得到共享內(nèi)存的開(kāi)始地址,使用結(jié)束以后我們使用shmdt斷開(kāi)這個(gè)內(nèi)存.
             
            1. #include <stdio.h>    
            2. #include <string.h>    
            3. #include <errno.h>    
            4. #include <unistd.h>    
            5. #include <sys/stat.h>    
            6. #include <sys/types.h>    
            7. #include <sys/ipc.h>    
            8. #include <sys/shm.h>    
            9. #define PERM S_IRUSR|S_IWUSR    
            10. int main(int argc,char **argv)    
            11. {    
            12. int shmid;    
            13. char *p_addr,*c_addr;    
            14. if(argc!=2)    
            15. {    
            16. fprintf(stderr,"Usage:%s\n\a",argv[0]);    
            17. exit(1);    
            18. }    
            19. if((shmid=shmget(IPC_PRIVATE,1024,PERM))==-1)    
            20. {    
            21. fprintf(stderr,"Create Share Memory Error:%s\n\a",strerror(errno));    
            22. exit(1);    
            23. }    
            24. if(fork())    
            25. {    
            26. p_addr=shmat(shmid,0,0);    
            27. memset(p_addr,'\0',1024);    
            28. strncpy(p_addr,argv[1],1024);    
            29. exit(0);    
            30. }    
            31. else    
            32. {    
            33. c_addr=shmat(shmid,0,0);    
            34. printf("Client get %s",c_addr);    
            35. exit(0);    
            36. }    
            37. }    

            這個(gè)程序是父進(jìn)程將參數(shù)寫(xiě)入到共享內(nèi)存,然后子進(jìn)程把內(nèi)容讀出來(lái).最后我們要使用ip
            crm釋放資源的.先用ipcs找出ID然后用ipcrm shm ID刪除.
            后記:
            進(jìn)程通信(IPC)是網(wǎng)絡(luò)程序的基礎(chǔ),在很多的網(wǎng)絡(luò)程序當(dāng)中會(huì)大量的使用進(jìn)程通信的概念
            和知識(shí).其實(shí)進(jìn)程通信是一件非常復(fù)雜的事情,我在這里只是簡(jiǎn)單的介紹了一下.如果你想
            學(xué)習(xí)進(jìn)程通信的詳細(xì)知識(shí),最好的辦法是自己不斷的寫(xiě)程序和看聯(lián)機(jī)手冊(cè).現(xiàn)在網(wǎng)絡(luò)上有
            了很多的知識(shí)可以去參考.可惜我看到的很多都是英文編寫(xiě)的.如果你找到了有中文的版
            本請(qǐng)盡快告訴我.謝謝!

            posted on 2008-04-16 09:11 RedLight 閱讀(320) 評(píng)論(0)  編輯 收藏 引用


            只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            <2008年4月>
            303112345
            6789101112
            13141516171819
            20212223242526
            27282930123
            45678910

            導(dǎo)航

            統(tǒng)計(jì)

            公告


            Name: Galen
            QQ: 88104725

            常用鏈接

            留言簿(3)

            隨筆分類(lèi)

            隨筆檔案

            相冊(cè)

            My Friend

            搜索

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            91精品观看91久久久久久| 久久精品成人国产午夜| 久久99精品国产| av色综合久久天堂av色综合在| 久久国产三级无码一区二区| 久久婷婷五月综合国产尤物app| 精品久久久一二三区| 国产精品熟女福利久久AV| 国产韩国精品一区二区三区久久 | 久久九九免费高清视频| 久久综合久久综合久久综合| 成人妇女免费播放久久久 | 久久久久国产精品人妻| 狠狠色丁香婷婷久久综合| 中文字幕亚洲综合久久菠萝蜜| 久久毛片免费看一区二区三区| 久久精品国产WWW456C0M| 亚洲国产成人精品无码久久久久久综合 | 久久强奷乱码老熟女网站| 久久久久九国产精品| 亚洲天堂久久久| 中文字幕精品久久| 午夜人妻久久久久久久久| 久久天堂AV综合合色蜜桃网 | 久久国产精品国语对白| 久久亚洲精品无码播放| 偷偷做久久久久网站| 久久天堂AV综合合色蜜桃网 | 狠狠色综合网站久久久久久久高清| 久久亚洲国产精品成人AV秋霞| 亚洲国产精品高清久久久| 精品久久久久久中文字幕人妻最新| 久久青青草原综合伊人| 手机看片久久高清国产日韩| 久久精品中文字幕一区| 国产精品视频久久久| 午夜精品久久影院蜜桃| 久久精品黄AA片一区二区三区| 伊人久久综合热线大杳蕉下载| 久久精品国产欧美日韩99热| 久久99久久99小草精品免视看|