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

            C++ Programmer's Cookbook

            {C++ 基礎(chǔ)} {C++ 高級(jí)} {C#界面,C++核心算法} {設(shè)計(jì)模式} {C#基礎(chǔ)}

            windows核心編程--作業(yè)

            作業(yè): 作業(yè)可以看作是一組進(jìn)程的容器,把這些進(jìn)程當(dāng)作一個(gè)整體,對(duì)這個(gè)整體整個(gè)加入更多的限制.
                     
                      因?yàn)閃i n d o w s并不維護(hù)進(jìn)程之間的父/子關(guān)系。即使父進(jìn)程已經(jīng)終止運(yùn)行,子進(jìn)程仍然會(huì)繼續(xù)運(yùn)行。Microsoft Windoss 2000提供了一個(gè)新的作業(yè)內(nèi)核對(duì)象,使你能夠?qū)⑦M(jìn)程組合在一起,并且創(chuàng)建一個(gè)“沙框”,以便限制進(jìn)程能夠進(jìn)行的操作。最好將作業(yè)對(duì)象視為一個(gè)進(jìn)程的容器。但是,創(chuàng)建包含單個(gè)進(jìn)程的作業(yè)是有用的,因?yàn)檫@樣一來(lái),就可以對(duì)該進(jìn)程加上通常情況下不能加的限制。


            創(chuàng)建一個(gè)新作業(yè)內(nèi)核對(duì)象:
            HANDLE CreateJobObject( PSECURITY_ATTRIBUTES psa, PCTSTR pszName);

            與所有的內(nèi)核對(duì)象一樣,它的第一個(gè)參數(shù)將安全信息與新作業(yè)對(duì)象關(guān)聯(lián)起來(lái),并且告訴系統(tǒng),是否想要使返回的句柄成為可繼承的句柄。最后一個(gè)參數(shù)用于給作業(yè)對(duì)象命名,使它可以供另一個(gè)進(jìn)程通過(guò)下面所示的O p e n J o b O b j e c t函數(shù)進(jìn)行訪問(wèn)。

            HANDLE OpenJobObject( DWORD dwDesiredAccess,
               BOOL bInheritHandle, PCTSTR pszName);
            與平常一樣,如果知道你將不再需要訪問(wèn)代碼中的作業(yè)對(duì)象,那么就必須通過(guò)調(diào)用C l o s e H a n d l e來(lái)關(guān)閉它的句柄。

            應(yīng)該知道,關(guān)閉作業(yè)對(duì)象并不會(huì)迫使作業(yè)中的所有進(jìn)程終止運(yùn)行。該作業(yè)對(duì)象實(shí)際上做上了刪除標(biāo)記,只有當(dāng)作業(yè)中的所有進(jìn)程全部終止運(yùn)行之后,該作業(yè)對(duì)象才被自動(dòng)撤消。
            注意,關(guān)閉作業(yè)的句柄后,盡管該作業(yè)仍然存在,但是該作業(yè)將無(wú)法被所有進(jìn)程訪問(wèn)。


            將一個(gè)進(jìn)程放入一個(gè)作業(yè),以限制該進(jìn)程進(jìn)行某些操作的能力。 Windows 98 Windows 98不支持作業(yè)的操作。
            void StartRestrictedProcess()
            {
               //Create a job kernel object.
               HANDLE hjob = CreateJobObject(NULL, NULL);

               //Place some restrictions on processes in the job.
               //First,set some basic restrictions.
               JOBOBJECT_BASIC_LIMIT_INFORMATION jobli = { 0 };

               //The process always runs in the idle priority class.
               jobli.PriorityClass = IDLE_PRIORITY_CLASS;

               //The job cannot use more than 1 second of CPU time.
               jobli.PerJobUserTimeLimit.QuadPart = 10000000; 
               //1 sec in 100-ns intervals

               //These are the only 2 restrictions I want placed on the job (process).
               jobli.LimitFlags = JOB_OBJECT_LIMIT_PRIORITY_CLASS |
                  JOB_OBJECT_LIMIT_JOB_TIME;
                 
               SetInformationJobObject(hjob,
                  JobObjectBasicLimitInformation,
                  &jobli, sizeof(jobli));

               //Second, set some UI restrictions.
               JOBOBJECT_BASIC_UI_RESTRICTIONS jobuir;
               jobuir.UIRestrictionsClass = JOB_OBJECT_UILIMIT_NONE;    
               //A fancy zero

               //The process can't log off the system.
               jobuir.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_EXITWINDOWS;

               //The process can't access USER objects
               //(such as other windows) in the system.
               jobuir.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_HANDLES;

               SetInformationJobObject(hjob,JobObjectBasicUIRestrictions,
                  &jobuir, sizeof(jobuir));

               //Spawn the process that is to be in the job.
               //Note: You must first spawn the process and then place the process in
               //the job. This means that the process's thread must be initially
               //suspended so that it can't execute any code outside
               //of the job's restrictions.

               STARTUPINFO si = { sizeof(si) };
               PROCESS_INFORMATION pi;
               CreateProcess(NULL, "CMD", NULL, NULL, FALSE,
                  CREATE_SUSPENDED, NULL, NULL, &si, π);
               //Place the process in the job.
               //Note:if this process spawns any children,the children are
               //automatically part of the same job.
               AssignProcessToJobObject(hjob,pi.hProcess);

               //Now we can allow the child process's thread to execute code.
               ResumeThread(pi.hThread);
               CloseHandle(pi.hThread);

               //Wait for the process to terminate or for all the job's
               //allotted CPU time to be used.
               HANDLE h[2];
               h[0] = pi.hProcess;
               h[1] = hjob;
               DWORD dw = WaitForMultipleObjects(2,h,FALSE,INFINITE);
               switch( dw-WAIT_OBJECT_0 )
               {
                 case 0:
                    //The process has terminated
                    break;
                 case 1:
                    //All of the job's allotted CPU time was used
                    break;
                }

                //Clean up properly.
                CloseHandle(pi.hProcess);
                CloseHandle(hjob);
            }


            對(duì)作業(yè)進(jìn)程的限制
            進(jìn)程創(chuàng)建后,通常需要設(shè)置一個(gè)沙框(設(shè)置一些限制),以便限制作業(yè)中的進(jìn)程能夠進(jìn)行的操作。可以給一個(gè)作業(yè)加上若干不同類(lèi)型的限制:

            • 基本限制和擴(kuò)展基本限制,用于防止作業(yè)中的進(jìn)程壟斷系統(tǒng)的資源。

            • 基本的U I限制,用于防止作業(yè)中的進(jìn)程改變用戶(hù)界面。

            • 安全性限制,用于防止作業(yè)中的進(jìn)程訪問(wèn)保密資源(文件、注冊(cè)表子關(guān)鍵字等)。

            通過(guò)調(diào)用下面的代碼,可以給作業(yè)加上各種限制:

             

            BOOL SetInformationJobObject(
            HANDLE hJob,
            JOBOBJECTINFOCLASS JobObjectInformationClass,
            PVOID pJobObjectInformation,
            DWORD cbJobObjectInformationLength);
            第一個(gè)參數(shù)用于標(biāo)識(shí)要限制的作業(yè)。第二個(gè)參數(shù)是個(gè)枚舉類(lèi)型,用于指明要使用的限制類(lèi)型。第三個(gè)參數(shù)是包含限制設(shè)置值的數(shù)據(jù)結(jié)構(gòu)的地址,第四個(gè)參數(shù)用于指明該結(jié)構(gòu)的大小(用于確定版本)。

            可以做的限制有:(具體參數(shù)的意思參看windows核心編程)
            JOB_OBJECT_BASIC_LIMIT_INFORMATION結(jié)構(gòu)類(lèi)似下面的樣子: (基本限制)

            typedef struct _JOBOBJECT_BASIC_LIMIT_INFORMATION{    LARGE_INTEGER  PerProcessUserTimeLimit;    LARGE_INTEGER  PerJobUserTimeLimit;    DWORD          LimitFlags;    DWORD          MinimumWorkingSetSize;    DWORD          MaximumWorkingSetSize;    DWORD          ActiveProcessLimit;    DWORD_PTR      Affinity;    DWORD          PriorityClass;    DWORD          SchedulingClass;} JOBOBJECT_BASIC_LIMIT_INFORMATION,  *PJOBOBJECT_BASIC_LIMIT_INFORMATION;

            J O B O B J E C T _ E X T E N D E D _ L I M I T _ I N F O R M AT I O N結(jié)構(gòu)對(duì)作業(yè)設(shè)置: (擴(kuò)展限制)
            typedef struct _JOBOBJECT_EXTENDED_LIMIT_INFORMATION
            {
                JOBOBJECT_BASIC_LIMIT_INFORMATION   BasicLimitInformation;
                IO_COUNTERS                         oInfo;
                SIZE_T                              ProcessMemoryLimit;
                SIZE_T                              JobMemoryLimit;
                SIZE_T                              PeakProcessMemoryUsed;
                SIZE_T                              PeakJobMemoryUsed;
            } JOBOBJECT_EXTENDED_LIMIT_INFORMATION,  *PJOBOBJECT_EXTENDED_LIMIT_INFORMATION;

            J O B O B J E C T _ B A S I C _ U I _ R E S T R I C T I O NS結(jié)構(gòu)的樣子: (其他限制)
            typedef struct _JOBOBJECT_BASIC_UI_RESTRICTIONS
            {
                DWORD UIRestrictionsClass;
            } JOBOBJECT_BASIC_UI_RESTRICTIONS, *PJOBOBJECT_BASIC_UI_RESTRICTIONS;
            J O B O B J E C T _ S E C U R I T Y _ L I M I T _ I N F O R M AT I O N的結(jié)構(gòu)類(lèi)似下面的形式: (安全限制)
            typedef struct _JOBOBJECT_SECURITY_LIMIT_INFORMATION
            {
                DWORD              SecurityLimitFlags;
                HANDLE             JobToken;
                PTOKEN_GROUPS      SidsToDisable;
                PTOKEN_PRIVILEGES  PrivilegesToDelete;
                PTOKEN_GROUPS      RestrictedSids;
            } JOBOBJECT_SECURITY_LIMIT_INFORMATION, *PJOBOBJECT_SECURITY_LIMIT_INFORMATION;

            當(dāng)然,一旦給作業(yè)設(shè)置了限制條件,就可以查詢(xún)這些限制。通過(guò)調(diào)用下面的代碼,就可以進(jìn)行這一操作:

             

            BOOL QueryInformationJobObject(
            HANDLE hJob,
            JOBOBJECTINFOCLASS JobObjectInformationClass,
            PVOID pvJobObjectInformation,
            DWORD cbJobObjectInformationLength,
            PDWORD pdwReturnLength);
            你為該函數(shù)傳遞作業(yè)的句柄(就像你對(duì)SetInformationJobObject操作時(shí)那樣),這些句柄包括用于指明你想要的限制信息的枚舉類(lèi)型,函數(shù)要進(jìn)行初始化的數(shù)據(jù)結(jié)構(gòu)的地址,以及包含該結(jié)構(gòu)的數(shù)據(jù)塊的長(zhǎng)度。最后一個(gè)參數(shù)是pdwReturnLength,用于指向該函數(shù)填寫(xiě)的DWORD,它告訴你有多少字節(jié)放入了緩存。如果你愿意的話,可以(并且通常)為該參數(shù)傳遞N U L L。

            將進(jìn)程放入作業(yè):

            BOOL AssignProcessToJobObject(
               HANDLE hJob,
               HANDLE hProcess);
            該函數(shù)告訴系統(tǒng),將該進(jìn)程(由hProcess標(biāo)識(shí))視為現(xiàn)有作業(yè)(由h J o b標(biāo)識(shí))的一部分。
            注意,該函數(shù)只允許將尚未被賦予任何作業(yè)的進(jìn)程賦予一個(gè)作業(yè)。一旦進(jìn)程成為一個(gè)作業(yè)的組成部分,
            它就不能轉(zhuǎn)到另一個(gè)作業(yè),并且不能是無(wú)作業(yè)的進(jìn)程。另外,當(dāng)作為作業(yè)的一部分的進(jìn)程生成另一個(gè)進(jìn)程的時(shí)候,
            新進(jìn)程將自動(dòng)成為父作業(yè)的組成部分。注意:調(diào)用此函數(shù)后要調(diào)用ResumeThread();這樣,
            進(jìn)程的線程就可以在作業(yè)的限制下執(zhí)行代碼。終止作業(yè)中所有進(jìn)程的運(yùn)行
            若要撤消作業(yè)中的進(jìn)程,只需要調(diào)用下面的代碼:


            BOOL TerminateJobObject(
            HANDLE hJob,
            UINT uExitCode);
            這類(lèi)似為作業(yè)中的每個(gè)進(jìn)程調(diào)用TerminateProcess函數(shù),將它們的所有退出代碼設(shè)置為uExitCode。

            查詢(xún)作業(yè)統(tǒng)計(jì)信息
            Q u e r y I n f o r m a t i o n J o b O b j e c t函數(shù)來(lái)獲取對(duì)作業(yè)的當(dāng)前限制信息。也可以使用它來(lái)獲取關(guān)于作業(yè)的統(tǒng)計(jì)信息。通過(guò)傳入不同的參數(shù),可以查詢(xún)到不同的作業(yè)統(tǒng)計(jì)信息.
            例如,若要獲取基本的統(tǒng)計(jì)信息,可以調(diào)用Q u e r y I n f o r m a t i o n J o b O b j e c t,為第二個(gè)參數(shù)傳遞J o b O b j e c t B a s i c A c c o u n t i n g I n f o r m a t i o n ,并傳遞J O B O B J E C T _ B A S I C _ A C C O U N T I N G _ I N F O R M AT I O N結(jié)構(gòu)的地址:

            typedef struct _JOBOBJECT_BASIC_ACCOUNTING_INFORMATION{   LARGE_INTEGER TotalUserTime;   LARGE_INTEGER TotalKernelTime;   LARGE_INTEGER ThisPeriodTotalUserTime;   LARGE_INTEGER ThisPeriodTotalKernelTime;   DWORD TotalPageFaultCount;   DWORD TotalProcesses;   DWORD ActiveProcesses;   DWORD TotalTerminatedProcesses;} JOBOBJECT_BASIC_ACCOUNTING_INFORMATION, *PJOBOBJECT_BASIC_ACCOUNTING_INFORMATION;

             


            除了查詢(xún)這些基本統(tǒng)計(jì)信息外,可以進(jìn)行一次函數(shù)調(diào)用,以同時(shí)查詢(xún)基本統(tǒng)計(jì)信息和I/O統(tǒng)計(jì)信息。為此,必須為第二個(gè)參數(shù)傳遞J o b O b j e c t B a s i c A n d I o A c c o u n t i n g I n f o r m a t i o n ,并傳遞J O B O B J E C T _ B A S I C _ A N D _ I O _ A C C O U N T I N G _ I N F O R M AT I O N結(jié)構(gòu)的地址:

            typedef struct JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION
            {
               JOBOBJECT_BASIC_ACCOUNTING_INFORMATION BasicInfo;
               IO_COUNTERS IoInfo;
            } JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION;

            如你所見(jiàn),這個(gè)結(jié)構(gòu)只返回一個(gè)J O B O B J E C T _ B A S I C _ A C C O U N T I N G _ I N F O R M AT I O N結(jié)構(gòu)和I O _ C O U N T E R S結(jié)構(gòu):

             

            typedef struct _IO_COUNTERS
            {
               ULONGLONG ReadOperationCount;
               ULONGLONG WriteOperationCount;
               ULONGLONG OtherOperationCount;
               ULONGLONG ReadTransferCount;
               ULONGLONG WriteTransferCount;
               ULONGLONG OtherTransferCount;
            } IO_COUNTERS;

            另外,可以使用下面這個(gè)新的G e t P r o c e s s I o C o u n t e r s函數(shù),以便獲取不是這些作業(yè)中的進(jìn)程的這些信息:


            BOOL GetProcessIoCounters(
               HANDLE hProcess,
               PIO_COUNTERS pIoCounters);
            也可以隨時(shí)調(diào)用Q u e r y I n f o r m a t i o n J o b O b j e c t函數(shù),以便獲取當(dāng)前在作業(yè)中運(yùn)行的進(jìn)程的一組進(jìn)程I D。若要進(jìn)行這項(xiàng)操作,首先必須確定你想在作業(yè)中看到多少進(jìn)程,然后必須分配足夠的內(nèi)存塊,來(lái)放置這些進(jìn)程I D的數(shù)組,并指定J O B O B J E C T _ B A S I C _ P R O C E S S _ I D _ L I S T結(jié)構(gòu)的大小:


            typedef struct _JOBOBJECT_BASIC_PROCESS_ID_LIST
            {
            DWORD NumberOfAssignedProcesses;
            DWORD NumberOfProcessIdsInList;
            DWORD ProcessIdList[1];
            } JOBOBJECT_BASIC_PROCESS_ID_LIST,  *PJOBOBJECT_BASIC_PROCESS_ID_LIST;
            因此,若要獲得當(dāng)前作業(yè)中的一組進(jìn)程I D,必須執(zhí)行類(lèi)似下面的代碼:

            void EnumProcessIdsInJob(HANDLE hjob)
            {
                //I assume that there will never be more
                //than 10 processes in this job.
                #define MAX_PROCESS_IDS     10

                //Calculate the number of bytes needed for
                //structure  & process IDs.
                DWORD Cb = sizeof(JOBOBJECT_BASIC_PROCESS_ID_LIST) +
                   (MAX_PROCESS_IDS - 1) * sizeof(DWORD);

                //Allocate the block of memory.
                PJOBOBJECT_BASIC_PROCESS_ID_LIST pjobpil = _alloca(cb);

                //Tell the function the maximum number of processes
                //that we allocated space for.
                pjobpil->NumberOfAssignedProcesses = MAX_PROCESS_IDS;

                //Request the current set of process IDs.
                QueryInformationJobObject(hjob, JobObjectBasicProcessIdList,
                   pjobpil, cb, &cb);

                //Enumerate the process IDs.
                for(int x=0; x < pjobpil -> NumberOfProcessIdsInList; x++)
                {
                    //Use pjobpil->ProcessIdList[x]
                }

                //Since _alloca was used to allocate the memory,
                //we don't need to free it here.
            }

             

            作業(yè)通知信息

            如果關(guān)心的是分配的所有C P U時(shí)間是否已經(jīng)到期,那么可以非常容易地得到這個(gè)通知信息。當(dāng)作業(yè)中的進(jìn)程尚未用完分配的C P U時(shí)間時(shí),作業(yè)對(duì)象就得不到通知。一旦分配的所有C P U時(shí)間已經(jīng)用完, Wi n d o w s就強(qiáng)制撤消作業(yè)中的所有進(jìn)程,并將情況通知作業(yè)對(duì)象。通過(guò)調(diào)用Wa i t F o r S i n g l e O b j e c t (或類(lèi)似的函數(shù)),可以很容易跟蹤這個(gè)事件。有時(shí),可以在晚些時(shí)候調(diào)用S e t I n f o r m a t i o n J o b O b j e c t函數(shù),使作業(yè)對(duì)象恢復(fù)未通知狀態(tài),并為作業(yè)賦予更多的C P U時(shí)間。

            當(dāng)開(kāi)始對(duì)作業(yè)進(jìn)行操作時(shí),我覺(jué)得當(dāng)作業(yè)中沒(méi)有任何進(jìn)程運(yùn)行時(shí),應(yīng)該將這個(gè)事件通知作業(yè)對(duì)象。畢竟當(dāng)進(jìn)程和線程停止運(yùn)行時(shí),進(jìn)程和線程對(duì)象就會(huì)得到通知。因此,當(dāng)作業(yè)停止運(yùn)行時(shí)它也應(yīng)該得到通知。這樣,就能夠很容易確定作業(yè)何時(shí)結(jié)束運(yùn)行。但是, M i c r o s o f t選擇在分配的C P U時(shí)間到期時(shí)才向作業(yè)發(fā)出通知,因?yàn)檫@顯示了一個(gè)錯(cuò)誤條件。由于許多作業(yè)啟動(dòng)時(shí)有一個(gè)父進(jìn)程始終處于工作狀態(tài),直到它的所有子進(jìn)程運(yùn)行結(jié)束,因此只需要在父進(jìn)程的句柄上等待,就可以了解整個(gè)作業(yè)何時(shí)運(yùn)行結(jié)束。S t a r t R e s t r i c t e d P r o c e s s函數(shù)用于顯示分配給作業(yè)的C P U時(shí)間何時(shí)到期,或者作業(yè)中的進(jìn)程何時(shí)終止運(yùn)行。

            前面介紹了如何獲得某些簡(jiǎn)單的通知信息,但是尚未說(shuō)明如何獲得更高級(jí)的通知信息,如進(jìn)程創(chuàng)建/終止運(yùn)行等。如果想要得到這些通知信息,必須將更多的基礎(chǔ)結(jié)構(gòu)放入應(yīng)用程序。特別是,必須創(chuàng)建一個(gè)I / O完成端口內(nèi)核對(duì)象,并將作業(yè)對(duì)象或多個(gè)作業(yè)對(duì)象與完成端口關(guān)聯(lián)起來(lái)。然后,必須讓一個(gè)或多個(gè)線程在完成端口上等待作業(yè)通知的到來(lái),這樣它們才能得到處理。

            一旦創(chuàng)建了I / O完成端口,通過(guò)調(diào)用S e t I n f o r m a t i o n J o b O b j e c t函數(shù),就可以將作業(yè)與該端口關(guān)聯(lián)起來(lái),如下面的代碼所示:


             

            JOBOBJECT_ASSOCIATE_COMPLETION_PORT joacp;
            //Any value to uniquely identify this job
            joacp.CompletionKey = 1;      

            //Handle of completion port that receives notifications
            joacp.CompletionPort = hIOCP; 
            SetInformationJobObject(hJob,
               jobObjectAssociateCompletionPortInformation,
               &joacp, sizeof(jaocp));

            當(dāng)上面的代碼運(yùn)行時(shí),系統(tǒng)將監(jiān)視該作業(yè)的運(yùn)行,當(dāng)事件發(fā)生時(shí),它將事件送往I / O完成端口(順便說(shuō)一下,可以調(diào)用Q u e r y I n f o r m a t i o m J o b O b j e c t函數(shù)來(lái)檢索完成關(guān)鍵字和完成端口句柄。但是,這樣做的機(jī)會(huì)很少)。線程通過(guò)調(diào)用G e t Q u e u e d C o m p l e t i o n S t a t u s函數(shù)來(lái)監(jiān)控I / O完成端口:


            BOOL GetQueuedCompletionStatus(
               HANDLE hIOCP,
               PDWORD pNumBytesTransferred,
               PULONG_PTR pCompletionKey,
               POVERLAPPED *pOverlapped,
               DWORD dwMilliseconds);

            當(dāng)該函數(shù)返回一個(gè)作業(yè)事件通知時(shí),* p C o m p l e t i o n K e y包含了調(diào)用S e t I n f o r m a t i o n J o b O b j e c t時(shí)設(shè)置的完成關(guān)鍵字值,用于將作業(yè)與完成端口關(guān)聯(lián)起來(lái)。它使你能夠知道哪個(gè)作業(yè)存在一個(gè)事件。* p N u m B y t e s Tr a n s f e r r e d中的值用于指明發(fā)生了哪個(gè)事件。


             

            posted on 2006-09-13 09:15 夢(mèng)在天涯 閱讀(2204) 評(píng)論(1)  編輯 收藏 引用 所屬分類(lèi): Windows API

            評(píng)論

            # re: windows核心編程--作業(yè) 2013-10-10 20:14 panpan

            好文章  回復(fù)  更多評(píng)論   

            公告

            EMail:itech001#126.com

            導(dǎo)航

            統(tǒng)計(jì)

            • 隨筆 - 461
            • 文章 - 4
            • 評(píng)論 - 746
            • 引用 - 0

            常用鏈接

            隨筆分類(lèi)

            隨筆檔案

            收藏夾

            Blogs

            c#(csharp)

            C++(cpp)

            Enlish

            Forums(bbs)

            My self

            Often go

            Useful Webs

            Xml/Uml/html

            搜索

            •  

            積分與排名

            • 積分 - 1811117
            • 排名 - 5

            最新評(píng)論

            閱讀排行榜

            久久久久久久国产免费看| 久久综合久久综合久久| 久久久久久综合一区中文字幕| 久久久国产视频| 久久精品视频一| 久久精品久久久久观看99水蜜桃| 亚洲国产成人久久综合一区77| 伊人精品久久久久7777| 国内精品人妻无码久久久影院导航| 日产精品99久久久久久| 国产一区二区精品久久岳| 久久av高潮av无码av喷吹| 久久99国产一区二区三区| 亚洲成av人片不卡无码久久| 久久精品国产亚洲AV香蕉| 久久精品国产99久久久| 久久99精品国产麻豆宅宅| 久久国产香蕉视频| 欧美黑人激情性久久| 97久久超碰成人精品网站| 久久婷婷久久一区二区三区| 久久久久亚洲av成人无码电影| 亚洲国产成人久久综合野外| 久久精品国产亚洲AV香蕉| 91久久九九无码成人网站| 亚州日韩精品专区久久久| 色欲久久久天天天综合网| 国产精品99久久精品| 欧美亚洲国产精品久久久久| 99国产欧美久久久精品蜜芽| 久久人妻少妇嫩草AV无码蜜桃| 久久久一本精品99久久精品66| 成人国内精品久久久久影院VR| 久久婷婷五月综合成人D啪| 久久96国产精品久久久| 99久久精品免费看国产一区二区三区| 久久久久久免费一区二区三区| 亚洲精品乱码久久久久久蜜桃不卡| 久久久久亚洲精品无码网址 | 亚洲国产精品久久久久婷婷软件| 欧美亚洲日本久久精品|