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

        ?

        嵌入式C語(yǔ)言中的面向?qū)ο笈c多線(xiàn)程編程

        2017-05-12 09:41:13茅勝榮肖家文喬?hào)|海
        關(guān)鍵詞:信號(hào)量子類(lèi)多態(tài)

        茅勝榮,肖家文,喬?hào)|海

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

        嵌入式C語(yǔ)言中的面向?qū)ο笈c多線(xiàn)程編程

        茅勝榮,肖家文,喬?hào)|海

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

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

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

        引 言

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

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

        1 LiteOOC介紹

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

        1.1 基本思想

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

        /* 對(duì)象記錄鏈表的每個(gè)成員*/

        typedef struct LOOC_MemAllocUnit_s{

        char file[LOOC_MAX_PATH]; //文件名

        int line; //行號(hào)

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

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

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

        } LOOC_MemAllocUnit;

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

        1.2 封 裝

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

        /* 抽象類(lèi)*/

        #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

        /* 具體類(lèi)*/

        #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

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

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

        #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++中釋放堆上對(duì)象的內(nèi)存空間需要使用delete關(guān)鍵字,編譯器會(huì)自動(dòng)釋放當(dāng)前對(duì)象的內(nèi)存,然后調(diào)用析構(gòu)函數(shù)完成資源的回收。相應(yīng)地,在LiteOOC中使用如下所示的DTOR宏來(lái)實(shí)現(xiàn)對(duì)象的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)用對(duì)象的析構(gòu)函數(shù)dtor,回收對(duì)象的資源,然后調(diào)用looc_free釋放記錄在對(duì)象鏈表中的內(nèi)存空間。dtor函數(shù)的具體實(shí)現(xiàn)細(xì)節(jié)需要由用戶(hù)在DTOR和END_DTOR兩個(gè)宏之間完成。

        1.3 繼 承

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

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

        1.4 多 態(tài)

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

        #define FUNCTION_SETTING(f1,f2)

        cthis->f1 = f2

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

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

        #define SUPER_PTR(cthis, father)

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

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

        #define SUB_PTR(selfptr,self,child)

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

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

        1.5 loocObject類(lèi)

        loocObject類(lèi)是LiteOOC中所有類(lèi)的父類(lèi),如下所示:

        ABS_CLASS(loocObject){

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

        int _use;

        /*子類(lèi)通過(guò)覆寫(xiě)finalize方法,實(shí)現(xiàn)對(duì)資源清理行為的定制*/

        void (*finalize)(loocObject* object);

        };

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

        ABS_CTOR(loocObject)

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

        cthis->_use = 0;

        END_ABS_CTOR

        DTOR(loocObject)

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

        cthis->finalize(cthis);

        END_DTOR

        2 在LiteOOC上實(shí)現(xiàn)隊(duì)列

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

        2.1 loocQueue類(lèi)的聲明

        CLASS(loocQueue) {

        /*繼承自loocObject*/

        EXTENDS(loocObject);

        /*隊(duì)列最大的大小*/

        int _maxSize;

        /*隊(duì)列中每個(gè)元素的大小*/

        int _elementSize;

        /*隊(duì)首*/

        int front;

        /*隊(duì)尾*/

        int rear;

        /*隊(duì)列有效長(zhǎng)度*/

        int length;

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

        void* queue_pool;

        /*初始化一個(gè)隊(duì)列*/

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

        /*入隊(duì)操作*/

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

        /*出隊(duì)操作*/

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

        };

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

        2.2 loocQueue類(lèi)的定義

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

        CTOR(loocQueue)

        /*調(diào)用父類(lèi)的構(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)用父類(lèi)的構(gòu)造函數(shù),初始化父類(lèi)對(duì)象,接著初始化子類(lèi)的成員變量,最后綁定類(lèi)的成員方法。需要注意的是,loocQueue_finalize重寫(xiě)了父類(lèi)loocObject的抽象方法,所以需要綁定在父類(lèi)上。loocQueue類(lèi)的析構(gòu)函數(shù)如下所示,里面向上調(diào)用了父類(lèi)的析構(gòu)函數(shù)。

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

        SUPER_DTOR(loocObject);

        END_DTOR

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

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

        2.3 loocQueue類(lèi)的使用

        loocQueue的測(cè)試程序如下所示:

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

        loocQueue* queue = loocQueue_new(looc_file_line);

        /*初始化隊(duì)列*/

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

        /*入隊(duì)操作*/

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

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

        }

        /*出隊(duì)操作*/

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

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

        }

        printf(" ");

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

        loocQueue_delete(queue);

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

        looc_report();

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

        3 Protothreads介紹

        Protothreads為C語(yǔ)言模擬了一種無(wú)堆棧的輕量級(jí)線(xiàn)程環(huán)境,能夠?qū)崿F(xiàn)線(xiàn)程的條件阻塞、信號(hào)量等操作系統(tǒng)中特有的機(jī)制。Protothreads目前已經(jīng)成為物聯(lián)網(wǎng)操作系統(tǒng)Contiki的一部分,同時(shí)也是Arduino中普遍使用的多線(xiàn)程庫(kù)。嚴(yán)格意義上來(lái)講,Protothreads是一種協(xié)程而非線(xiàn)程,一個(gè)程序可以包含多個(gè)協(xié)程,這類(lèi)似一個(gè)進(jìn)程包含多個(gè)線(xiàn)程。因?yàn)樾⌒颓度胧较到y(tǒng)程序往往是單進(jìn)程的,所以也可以將Protothreads稱(chēng)為線(xiàn)程。

        3.1 基本思想

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

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

        #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)者和消費(fèi)者模型

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

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

        3.3 互斥與同步

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

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

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

        結(jié) 語(yǔ)

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

        [2] Mark Allen Weiss.數(shù)據(jù)結(jié)構(gòu)與算法分析:C語(yǔ)言描述[M].北京:機(jī)械工業(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/.

        茅勝榮、肖家文(在校研究生):研究方向?yàn)榍度胧较到y(tǒng)設(shè)計(jì)、信號(hào)處理;喬?hào)|海(教授),研究方向?yàn)樾盘?hào)處理、MEMS器件設(shè)計(jì)。

        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)

        猜你喜歡
        信號(hào)量子類(lèi)多態(tài)
        基于STM32的mbedOS信號(hào)量調(diào)度機(jī)制剖析
        分層多態(tài)加權(quán)k/n系統(tǒng)的可用性建模與設(shè)計(jì)優(yōu)化
        卷入Hohlov算子的某解析雙單葉函數(shù)子類(lèi)的系數(shù)估計(jì)
        參差多態(tài)而功不唐捐
        Nucleus PLUS操作系統(tǒng)信號(hào)量機(jī)制的研究與測(cè)試
        關(guān)于對(duì)稱(chēng)共軛點(diǎn)的倒星象函數(shù)某些子類(lèi)的系數(shù)估計(jì)
        人多巴胺D2基因啟動(dòng)子區(qū)—350A/G多態(tài)位點(diǎn)熒光素酶表達(dá)載體的構(gòu)建與鑒定及活性檢測(cè)
        μC/OS- -III對(duì)信號(hào)量的改進(jìn)
        Linux操作系統(tǒng)信號(hào)量機(jī)制的實(shí)時(shí)化改造
        煙堿型乙酰膽堿受體基因多態(tài)與早發(fā)性精神分裂癥的關(guān)聯(lián)研究
        亚洲a∨无码一区二区| 成人女同av在线观看网站| 97人妻人人做人碰人人爽| 精品无码中文视频在线观看| 亚洲av影院一区二区三区四区| 丰满熟女人妻一区二区三区| 国产成人精品无码免费看| 国产人妻人伦精品1国产盗摄| 国产精品亚洲A∨天堂| 亚洲精品一区二区三区日韩| 国产内射一级一片内射视频| 亚洲av日韩综合一区在线观看 | 日本真人边吃奶边做爽电影| 国自产偷精品不卡在线| 精品国产性色av网站| 男人的天堂av你懂得| 久久亚洲日韩精品一区二区三区| 国产内射性高湖| 人妻中文字幕一区二区二区| 亚洲中文字幕九色日本| 亚洲欧美精品suv| 亚洲国产精品久久久久秋霞1| 久久精品一区二区三区夜夜| 国精产品一区一区三区有限在线 | 国产91清纯白嫩初高中在线观看 | 日韩狼人精品在线观看| 国产黑色丝袜在线看片| 野狼第一精品社区| 欧美日韩中文亚洲另类春色| 射进去av一区二区三区| 日韩少妇内射免费播放18禁裸乳| 先锋影音av资源我色资源| 能看的网站中文字幕不卡av| 在线视频国产91自拍| 麻豆一区二区99久久久久| 亚洲第一区无码专区| 午夜男女靠比视频免费| 消息称老熟妇乱视频一区二区| 国产精品久久久久久久久免费观看| 亚洲综合国产精品一区二区| 亚洲乳大丰满中文字幕|