亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

        嵌入式C語言中的面向?qū)ο笈c多線程編程

        2017-05-12 09:41:13茅勝榮肖家文喬東海

        茅勝榮,肖家文,喬東海

        (蘇州大學(xué) 電子信息學(xué)院,蘇州 215006)

        嵌入式C語言中的面向?qū)ο笈c多線程編程

        茅勝榮,肖家文,喬東海

        (蘇州大學(xué) 電子信息學(xué)院,蘇州 215006)

        面向?qū)ο笈c多線程編程的誕生大大提高了軟件開發(fā)的效率,降低了開發(fā)復(fù)雜應(yīng)用的難度,但在一些小型的嵌入式系統(tǒng)中很難得到應(yīng)用,其中最重要的限制因素就是微控制器的代碼空間有限,使得適用于計算機的軟件架構(gòu)不適合嵌入式設(shè)備。本文將介紹一種能夠使用在嵌入式場合的面向?qū)ο笈c多線程的編程機制,通過構(gòu)造特殊的宏定義來模擬面向?qū)ο蠛投嗑€程編程的軟件環(huán)境,開銷小,效率高。以此為基礎(chǔ)進行二次開發(fā)的軟件代碼可讀性和移植性更好,可以加快嵌入式軟件的更新與迭代。

        嵌入式系統(tǒng);C語言;面向?qū)ο?;多線程

        引 言

        C語言編譯器沒有提供面向?qū)ο蟮脑С?,因此也沒有專門的關(guān)鍵字來表達類、繼承等概念,但是面向?qū)ο笏枷肱c語言本身無關(guān),本文使用C語言以LiteOOC(Lite Object-Oriented C)為名實現(xiàn)了一套面向?qū)ο髾C制,通過宏定義巧妙地表達了封裝、繼承和多態(tài)的思想。本文將詳細介紹LiteOOC的底層實現(xiàn)原理。

        現(xiàn)代操作系統(tǒng)的重要特點之一是支持多線程編程,但是在沒有底層操作系統(tǒng)支持的嵌入式軟件中,一般的做法是使用一個大循環(huán),例如單片機中的while(1)或者Arduino中的loop()函數(shù),通過輪詢的方式來執(zhí)行不同的任務(wù)。但任務(wù)之間的同步與互斥難以實現(xiàn),并且代碼可讀性不高。而移植操作系統(tǒng)不但使工作變得復(fù)雜,還會增加對Flash和RAM資源的消耗,不適合一些資源稀缺的應(yīng)用。本文將介紹一個低開銷的并發(fā)程序設(shè)計機制——Protothreads,它利用宏定義為C語言模擬了一種無堆棧的輕量級線程環(huán)境。

        1 LiteOOC介紹

        使用C語言來進行面向?qū)ο缶幊绦枰鉀Q兩大問題,一是如何表達面向?qū)ο笾械幕疽兀绶庋b、繼承和多態(tài);二是如何妥善管理內(nèi)存,當程序中的對象之間有組合、聚合等關(guān)系時,如果沒有一個有效的內(nèi)存管理方法,就很容易造成內(nèi)存泄露或者內(nèi)存訪問異常。

        1.1 基本思想

        LiteOOC通過宏定義對結(jié)構(gòu)體封裝,巧妙地實現(xiàn)了封裝、繼承與多態(tài)。LiteOOC采用引用計數(shù)的方式來管理存在的對象,只有當對象的引用計數(shù)為0時,調(diào)用delete函數(shù)才會釋放內(nèi)存資源。LiteOOC維護著一個如下所示的對象記錄鏈表:

        /* 對象記錄鏈表的每個成員*/

        typedef struct LOOC_MemAllocUnit_s{

        char file[LOOC_MAX_PATH]; //文件名

        int line; //行號

        void* addr; //內(nèi)存地址

        size_t size; //內(nèi)存塊大小

        struct LOOC_MemAllocUnit_s* next;//下一個內(nèi)存塊記錄

        } LOOC_MemAllocUnit;

        存放用戶調(diào)用looc_malloc函數(shù)分配的內(nèi)存信息,包括調(diào)用內(nèi)存分配函數(shù)的文件名、內(nèi)存地址、內(nèi)存大小等,雖然這會額外消耗一定的內(nèi)存資源,但是在開發(fā)初期非常有助于監(jiān)視內(nèi)存泄露的情況。另外在LiteOOC中,所有的類都繼承自同一個父類——loocObject,利用多態(tài)的性質(zhì),loocObject類型的指針可以指向所有的對象。

        1.2 封 裝

        封裝,即隱藏對象的屬性和實現(xiàn)細節(jié),僅公開必要的接口給用戶讀取和修改對象的屬性。封裝可以增強安全性、簡化編程,使用者不必去了解具體的實現(xiàn)細節(jié)。在LiteOOC中,使用如下所示的宏定義來模擬C++、Java等面向?qū)ο笳Z言中的類:

        /* 抽象類*/

        #define ABS_CLASS(type)

        typedef struct type##_s type;

        extern void type##_ctor(type* cthis);

        extern void type##_dtor(type* cthis);

        extern void type##_delete(type* cthis);

        struct type##_s

        /* 具體類*/

        #define CLASS(type)

        typedef struct type##_s type;

        extern type* type##_new(looc_file_line_param);

        extern void type##_ctor(type* cthis);

        extern void type##_dtor(type* cthis);

        extern void type##_delete(type* cthis);

        struct type##_s

        實質(zhì)上是利用結(jié)構(gòu)體來封裝對象的屬性與方法。通過給CLASS宏傳遞一個類名,將會同時聲明以該類名為前綴的new、delete、ctor和dtor函數(shù),它們分別相當于C++中的new關(guān)鍵字、delete關(guān)鍵字、構(gòu)造函數(shù)和析構(gòu)函數(shù)。與此同時,因為抽象類不能被直接實例化,所以ABS_CLASS宏中沒有聲明new函數(shù)。

        C++在堆上實例化一個類需要使用new關(guān)鍵字,編譯器會立即為該對象分配內(nèi)存空間,然后調(diào)用構(gòu)造函數(shù)完成對象的初始化。相應(yīng)地,在LiteOOC中使用如下所示的CTOR宏定義來實現(xiàn)對象的new函數(shù),new函數(shù)中先調(diào)用looc_malloc為對象分配內(nèi)存,并將地址返回給cthis指針,接著調(diào)用對象的構(gòu)造函數(shù)ctor完成對象的初始化工作。ctor函數(shù)的具體實現(xiàn)細節(jié)需要由用戶在CTOR與END_CTOR兩個宏之間完成。

        #define CTOR(type)

        type* type##_new(const char* file, int line){

        type* cthis;

        cthis = (type*)looc_malloc(sizeof(type),#type,file,line);

        if(!cthis){

        return NULL;

        }

        type##_ctor(cthis);

        return cthis;

        }

        void type##_ctor(type* cthis){

        #define END_CTOR

        }

        C++中釋放堆上對象的內(nèi)存空間需要使用delete關(guān)鍵字,編譯器會自動釋放當前對象的內(nèi)存,然后調(diào)用析構(gòu)函數(shù)完成資源的回收。相應(yīng)地,在LiteOOC中使用如下所示的DTOR宏來實現(xiàn)對象的delete函數(shù):

        #define DTOR(type)

        void type##_delete(type* cthis){

        type##_dtor(cthis);

        looc_free((void*)cthis);

        }

        void type##_dtor(type* cthis){

        #define END_DTOR

        }

        delete函數(shù)中先調(diào)用對象的析構(gòu)函數(shù)dtor,回收對象的資源,然后調(diào)用looc_free釋放記錄在對象鏈表中的內(nèi)存空間。dtor函數(shù)的具體實現(xiàn)細節(jié)需要由用戶在DTOR和END_DTOR兩個宏之間完成。

        1.3 繼 承

        面向?qū)ο笾械睦^承機制通過擴展原有的類、聲明新的類來實現(xiàn),使得代碼具有可重用性和擴展性。在LiteOOC中,通過如下所示的EXTENDS宏來模擬繼承的思想,其功能是將父類在子類中實例化,且EXTENDS只能在CLASS宏內(nèi)部使用。

        #define EXTENDS(type) struct type##_s type

        1.4 多 態(tài)

        在面向?qū)ο髾C制中,同一方法在子類和父類中的行為是不同的,方法的行為取決于調(diào)用方法的對象,這種行為即為多態(tài)。多態(tài)性允許將父類對象的指針指向子類對象,父類對象指針根據(jù)當前指向的子類對象的特性以不同的方式運作。在LiteOOC中,實現(xiàn)多態(tài)需要分三步:首先子類需要繼承某個抽象類,然后重寫其抽象方法,最后將實現(xiàn)的方法綁定在抽象類上。所謂綁定,在LiteOOC中是指將具體實現(xiàn)的函數(shù)地址賦給類的成員方法。使用如下所示的FUNCTION_SETTING宏可以實現(xiàn)函數(shù)綁定的功能:

        #define FUNCTION_SETTING(f1,f2)

        cthis->f1 = f2

        該宏必須在CTOR和END_CTOR宏之間調(diào)用。LiteOOC中的析構(gòu)函數(shù)是多態(tài)的,用戶調(diào)用父類的delete函數(shù)將會釋放父類對象指針指向的子類對象的內(nèi)存空間,本文第2.2節(jié)會通過例子來分析具體的實現(xiàn)過程。

        使用多態(tài)的過程中常需要做類型轉(zhuǎn)換,LiteOOC提供了向上類型轉(zhuǎn)換SUPER_PTR的宏:

        #define SUPER_PTR(cthis, father)

        ((father*)(&(cthis->father)))

        向下類型轉(zhuǎn)換SUB_PTR的宏:

        #define SUB_PTR(selfptr,self,child)

        ((child*)((char*)selfptr-looc_offsetof(child,self)))

        向上類型轉(zhuǎn)換將子類對象cthis轉(zhuǎn)換成father類型的對象。向下類型轉(zhuǎn)換將self類型的父類對象selfptr轉(zhuǎn)換成child類型的對象。

        1.5 loocObject類

        loocObject類是LiteOOC中所有類的父類,如下所示:

        ABS_CLASS(loocObject){

        /*引用計數(shù)*/

        int _use;

        /*子類通過覆寫finalize方法,實現(xiàn)對資源清理行為的定制*/

        void (*finalize)(loocObject* object);

        };

        該類只有兩個成員:一是引用計數(shù),用來管理何時釋放內(nèi)存資源,只有當引用計數(shù)為0時才能將對象析構(gòu);二是finalize方法,是一個抽象方法,需要子類重寫來實現(xiàn)具體的析構(gòu)操作。loocObject類的實現(xiàn)如下所示,在構(gòu)造函數(shù)中,將對象的引用計數(shù)清零,在析構(gòu)函數(shù)中,調(diào)用了finalize方法。

        ABS_CTOR(loocObject)

        /*初始引用計數(shù)為0*/

        cthis->_use = 0;

        END_ABS_CTOR

        DTOR(loocObject)

        /*調(diào)用子類自定義的finalize方法*/

        cthis->finalize(cthis);

        END_DTOR

        2 在LiteOOC上實現(xiàn)隊列

        隊列是嵌入式編程中常用的數(shù)據(jù)結(jié)構(gòu)之一,本節(jié)將介紹如何在LiteOOC的基礎(chǔ)上,利用封裝、繼承、多態(tài)的思想實現(xiàn)隊列的基本操作。

        2.1 loocQueue類的聲明

        CLASS(loocQueue) {

        /*繼承自loocObject*/

        EXTENDS(loocObject);

        /*隊列最大的大小*/

        int _maxSize;

        /*隊列中每個元素的大小*/

        int _elementSize;

        /*隊首*/

        int front;

        /*隊尾*/

        int rear;

        /*隊列有效長度*/

        int length;

        /*內(nèi)存池*/

        void* queue_pool;

        /*初始化一個隊列*/

        void (*init)(loocQueue* cthis, int maxSize, int elementSize);

        /*入隊操作*/

        looc_bool (*enqueue)(loocQueue* cthis, void* data);

        /*出隊操作*/

        void* (*dequeue)(loocQueue* cthis);

        };

        以上是隊列類loocQueue的聲明,實際上是利用宏CLASS聲明了一個類型為loocQueue的結(jié)構(gòu)體,以及l(fā)oocQueue_new、loocQueue_delete、loocQueue_ctor和loocQueue_dtor四個函數(shù)。在類的內(nèi)部,使用EXTENDS宏繼承了loocObject類,定義了隊列的成員變量如隊列首尾元素索引front和rear、隊列的有效長度length等,還聲明了隊列的成員方法,如入隊操作enqueue和出隊操作dequeue。

        2.2 loocQueue類的定義

        類的定義分三步完成。一要實現(xiàn)類的成員方法,例如loocQueue_enqueue函數(shù)實現(xiàn)了類的enqueue方法,如果繼承了抽象類,那么還需要重寫抽象方法,例如loocQueue_finalize函數(shù)重寫了父類loocObject的finalize方法。二要在構(gòu)造函數(shù)中初始化成員變量并且綁定成員方法。三要在析構(gòu)函數(shù)中完成類的析構(gòu)操作。loocQueue類的構(gòu)造函數(shù)如下所示:

        CTOR(loocQueue)

        /*調(diào)用父類的構(gòu)造函數(shù)*/

        SUPER_CTOR(loocObject);

        cthis->_elementSize = 1;

        cthis->_maxSize = LOOC_QUEUE_DEFAULT_SIZE;

        cthis->front = 0;

        cthis->rear = 0;

        cthis->length = 0;

        /*成員函數(shù)的綁定*/

        FUNCTION_SETTING(init, loocQueue_init);

        FUNCTION_SETTING(enqueue, loocQueue_enqueue);

        FUNCTION_SETTING(dequeue, loocQueue_dequeue);

        FUNCTION_SETTING(loocObject.finalize, loocQueue_finalize);

        END_CTOR

        首先調(diào)用父類的構(gòu)造函數(shù),初始化父類對象,接著初始化子類的成員變量,最后綁定類的成員方法。需要注意的是,loocQueue_finalize重寫了父類loocObject的抽象方法,所以需要綁定在父類上。loocQueue類的析構(gòu)函數(shù)如下所示,里面向上調(diào)用了父類的析構(gòu)函數(shù)。

        DTOR(loocQueue)/*調(diào)用父類的析構(gòu)函數(shù),實質(zhì)上就是子類實現(xiàn)的finalize方法*/

        SUPER_DTOR(loocObject);

        END_DTOR

        LiteOOC中的析構(gòu)函數(shù)是多態(tài)的,如圖1所示,假如程序中除了有隊列l(wèi)oocQueue,還存在鏈表loocList,他們都繼承自loocObject抽象類,且對象都通過SUPER_PTR宏向上類型轉(zhuǎn)換成loocObject類型的對象,當調(diào)用loocObject類的finalize方法時,前者會執(zhí)行l(wèi)oocQueue_finalize函數(shù),后者會執(zhí)行l(wèi)oocList_finalize函數(shù)。這是因為在使用new函數(shù)實例化對象的時候已經(jīng)在構(gòu)造函數(shù)中將loocQueue_finalize綁定在了父類的finalize上,用戶調(diào)用loocObject類的finalize方法就是調(diào)用與之綁定在一起的函數(shù)。這便是LiteOOC實現(xiàn)多態(tài)的精髓所在——函數(shù)綁定。

        圖1 析構(gòu)函數(shù)的多態(tài)

        2.3 loocQueue類的使用

        loocQueue的測試程序如下所示:

        /*創(chuàng)建隊列對象*/

        loocQueue* queue = loocQueue_new(looc_file_line);

        /*初始化隊列*/

        queue->init(queue, 10, sizeof(int));

        /*入隊操作*/

        for (i = 0; i < 15; i++){

        queue->enqueue(queue, (void*) &i);

        }

        /*出隊操作*/

        for (i = 0; i < 10; i++){

        printf("%d ", *(int*) queue->dequeue(queue));

        }

        printf(" ");

        /*釋放隊列內(nèi)存空間*/

        loocQueue_delete(queue);

        /*報告內(nèi)存泄漏情況*/

        looc_report();

        使用loocQueue_new函數(shù)來創(chuàng)建一個隊列對象queue,該函數(shù)會間接調(diào)用loocQueue_ctor,完成對象成員方法的綁定和成員變量的初始化。調(diào)用類的enqueue方法來實現(xiàn)入隊的操作,調(diào)用類的dequeue方法來實現(xiàn)出隊的操作,調(diào)用loocQueue_delete函數(shù)可以回收queue對象的內(nèi)存空間。程序的最后,利用LiteOOC提供的looc_report函數(shù)可以報告此時的內(nèi)存泄漏情況,方便用戶排錯。

        3 Protothreads介紹

        Protothreads為C語言模擬了一種無堆棧的輕量級線程環(huán)境,能夠?qū)崿F(xiàn)線程的條件阻塞、信號量等操作系統(tǒng)中特有的機制。Protothreads目前已經(jīng)成為物聯(lián)網(wǎng)操作系統(tǒng)Contiki的一部分,同時也是Arduino中普遍使用的多線程庫。嚴格意義上來講,Protothreads是一種協(xié)程而非線程,一個程序可以包含多個協(xié)程,這類似一個進程包含多個線程。因為小型嵌入式系統(tǒng)程序往往是單進程的,所以也可以將Protothreads稱為線程。

        3.1 基本思想

        Protothreads的實現(xiàn)全部在頭文件中使用宏定義封裝,本質(zhì)上是構(gòu)造了C語言的狀態(tài)機模型,巧妙地利用了switch語句能夠隨意跳轉(zhuǎn)進入if和while控制語句內(nèi)部的優(yōu)點。Protothreads將程序跳轉(zhuǎn)的行號作為狀態(tài)切換的標記,程序如下所示:

        #define LC_INIT(s) s = 0;

        #define LC_RESUME(s) switch(s) { case 0:

        #define LC_SET(s) s = __LINE__; case __LINE__:

        #define LC_END(s) }

        3.2 基本操作

        Protothreads中的線程控制結(jié)構(gòu)體pt被定義為一個16位的整型,用來保存狀態(tài)機跳轉(zhuǎn)時的行號。在線程調(diào)度前,需要使用PT_INIT宏將pt初始化為0,復(fù)位狀態(tài)機。Protothreads中的線程執(zhí)行函數(shù)的返回值必須是整型,且線程的開始和結(jié)束都必須在PT_BEGIN與PT_END兩個宏之間。程序如下所示:

        #define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; LC_RESUME((pt)->lc)

        #define PT_END(pt) LC_END((pt)->lc); PT_YIELD_FLAG = 0;

        PT_INIT(pt); return PT_ENDED; }

        圖2 生產(chǎn)者和消費者模型

        PT_BEGIN設(shè)置了PT_YIELD_FLAG標志,表示當前線程可以讓出控制權(quán),然后又會進入switch判斷語句,根據(jù)當前pt的值跳轉(zhuǎn)到上一次線程退出的地方繼續(xù)執(zhí)行。PT_END用來結(jié)束當前的switch判斷語句,并將PT_YIELD_FLAG標志清零,把當前pt的值也清零,返回當前狀態(tài)機的狀態(tài)。因為Protothreads切換線程的時候不會保存上下文,所以線程函數(shù)中不允許使用局部變量,但可以通過靜態(tài)局部變量或者全局變量來代替。

        Protothreads中讓出線程控制權(quán)的方法主要有以下幾個函數(shù):PT_WAIT_UNTIL(pt, condition)函數(shù)會根據(jù)condition條件是否成立來條件阻塞當前線程;PT_WAIT_THREAD(pt, thread)函數(shù)會一直等待直到子線程thread結(jié)束;PT_YIELD_UNTIL(pt, condition)函數(shù)會立即退出當前線程,直到condition條件成立,它與PT_WAIT_UNTIL的差別在于,第一次調(diào)用PT_YIELD_UNTIL函數(shù)一定會退出線程,而不管condition條件是否成立。

        3.3 互斥與同步

        多線程編程中的互斥是指臨界資源同一時刻只允許一個訪問者對其進行訪問,具有唯一性和排他性,但是互斥無法限制訪問者對資源的訪問順序。同步是指在互斥的基礎(chǔ)上,實現(xiàn)訪問者對資源的有序訪問。Protothreads使用信號量來實現(xiàn)互斥與同步,信號量是一個32位無符號整型數(shù),值為正時,說明資源空閑,若為0說明資源被占用。Protothreads中對信號量的操作有3種:PT_SEM_INIT(s, c)函數(shù)用來初始化一個信號量,s代表信號量結(jié)構(gòu)體指針,c表示信號量的初始化值。PT_SEM_WAIT(pt, s)函數(shù)執(zhí)行“等信號”操作,如果此時信號量為0,線程將阻塞,直到信號量大于0,否則將信號量減1,線程繼續(xù)往下執(zhí)行。PT_SEM_SIGNAL(pt, s)函數(shù)執(zhí)行“給信號”操作,直接將信號量加1,然后線程繼續(xù)往下執(zhí)行。

        4 在Protothreads上實現(xiàn)生產(chǎn)者-消費者模型

        生產(chǎn)者和消費者模式能夠解決大多數(shù)并發(fā)問題,該模型通過平衡生產(chǎn)線程和消費線程的工作能力來提高程序的整體處理速度。如圖2所示,定義了兩個信號量:full和empty。前者代表待生產(chǎn)的資源數(shù),后者代表可供消費的資源數(shù)。生產(chǎn)者線程會先檢查full信號量是否為0,如果等于0,則表示暫時不需要生產(chǎn),線程阻塞,直到消費者調(diào)用PT_SEM_SIGNAL(pt,&full)。消費者線程會先檢查empty信號量是否為0,如果等于0,則表示暫時沒有資源可供消費,線程阻塞,直到生產(chǎn)者調(diào)用PT_SEM_SIGNAL(pt,&empty)??梢娎肞rotothreads的同步與互斥功能能夠快速高效地實現(xiàn)生產(chǎn)者-消費者模型。

        結(jié) 語

        [1] 高煥堂.UML+OOPC嵌入式C語言開發(fā)精講[M].北京:電子工業(yè)出版社,2008.

        [2] Mark Allen Weiss.數(shù)據(jù)結(jié)構(gòu)與算法分析:C語言描述[M].北京:機械工業(yè)出版社,2010.

        [3] Dunkels.Protothreads-Lightweight,Stackless Threads in C[EB/OL].[2017-02].http://dunkels.com/adam/pt/.

        [4] Contiki-os.org.Contiki:The Open Source Operating System for the Internet of Things[EB/OL].[2017-02].http://www.contiki-os.org/.

        茅勝榮、肖家文(在校研究生):研究方向為嵌入式系統(tǒng)設(shè)計、信號處理;喬東海(教授),研究方向為信號處理、MEMS器件設(shè)計。

        Object-oriented and Multi-thread Programming in Embedded C Language

        Mao Shengrong,Xiao Jiawen,Qiao Donghai

        (Shool of Electronic Information,Soochow University,Suzhou 215006,China)

        Object-oriented and multi-thread programming greatly enhance the efficiency of software development,and reduce the difficulty to develop complex applications,but it is difficult to apply in some small embedded systems.The most important constraint is the small space of microcontroller and the software architecture which is suitable for computer but unfit for embedded devices.In the paper,an object-oriented and multi-thread programming mechanism is introduced which can be used in the embedded environment.By constructing special macro definitions,the object-oriented and multi-thread ideology can be simulated,which is known for low overhead and high efficiency.Using this construction,the software will have higher code readability and portability,so that we can accelerate the upgrade and iteration of the embedded software.

        embedded system;C language;object-oriented;multi-thread

        TP311.1

        A

        士然

        2017-02-06)

        亚洲综合色婷婷七月丁香| 开心五月激情综合婷婷色| 拍摄av现场失控高潮数次| 狠狠狠狠狠综合视频| 最新日本久久中文字幕| 青春草在线视频观看| 久久不见久久见免费影院www| 亚洲AV综合久久九九| 国产一区二区一级黄色片| 蜜桃视频免费进入观看| 人妻av乱片av出轨| 女女同性黄网在线观看| 国产免费一区二区三区在线观看| 狂猛欧美激情性xxxx大豆行情| 中文字幕一区二区三区日韩精品| 欧美色色视频| 日本女优爱爱中文字幕| 国产香港明星裸体xxxx视频 | 91青青草久久| 亚洲精品不卡av在线免费| 国产成人小视频| 日本韩无专砖码高清| 无码伊人久久大香线蕉| 中文字幕av熟女中文av| 在线成人一区二区| 国产91福利在线精品剧情尤物| 漂亮人妻被强中文字幕乱码| 亚洲av丰满熟妇在线播放| 国产久热精品无码激情| 人妻系列无码专区久久五月天 | 国产aⅴ无码专区亚洲av麻豆 | 国产精品无码成人午夜电影| 亚洲欧美国产日产综合不卡| 久久婷婷综合色一区二区| 无码人妻丰满熟妇啪啪网站| 国产nv精品你懂得| 91麻豆精品激情在线观最新| 久久久99精品成人片| 亚洲国产精品特色大片观看完整版 | 色妺妺在线视频| 国产精东一区二区三区|