日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > windows >内容正文

windows

Windows® CE 系统中的同步机制

發(fā)布時間:2023/12/15 windows 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Windows® CE 系统中的同步机制 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

看到篇好文章,呵呵,獨樂樂,不如眾樂樂

?

本文轉(zhuǎn)自http://blog.csdn.net/thl789/archive/2006/01/17/582246.aspx ,轉(zhuǎn)載請注明出處

?

?

摘要 ... 1

目錄 ... 1

一、 WinCE進(jìn)程 /線程模型概覽 ... 1

二、臨界區(qū)( Critical Section ... 2

三、互斥體( Mutex ... 3

四、信號量( Semaphore ... 4

五、事件( Event ... 5

六、消息隊列( MsgQueue P2P ... 6

七、互鎖函數(shù)( Interlocked Function ... 8

八、 Wait函數(shù) ... 8

總結(jié) ... 10

參考資料以及進(jìn)一步閱讀 ... 10

關(guān)于作者 ... 10

?

一、 WinCE 進(jìn)程 / 線程模型概覽

WinCE 操作系統(tǒng)實現(xiàn)了進(jìn)程 / 線程兩級管理模型。連同內(nèi)核進(jìn)程和系統(tǒng)進(jìn)程,以及應(yīng)用進(jìn)程一起, WinCE 共支持 32 個進(jìn)程。進(jìn)程還可以有自己的線程,進(jìn)程默認(rèn)有一個主線程,線程分為 256 個優(yōu)先級別, WinCE 調(diào)度程序按照線程優(yōu)先級高低來調(diào)度。進(jìn)程是 WinCE 中最小資源分配的單元,線程是 WinCE 的最小調(diào)度單元。

本文講述的同步機(jī)制有些只適用于線程間同步,有些既能用于線程間同步又能用于進(jìn)程間同步,下面討論到某一種機(jī)制的時候,再具體詳述其適用場景。

二、臨界區(qū)( Critical Section

(本節(jié)內(nèi)容適用于 WinCE 1.0 及以上版本

WinCE 實現(xiàn)了操作系統(tǒng)理論里的臨界區(qū)管理。臨界區(qū)內(nèi)含有對臨街資源的訪問。通過對臨界區(qū)進(jìn)行有效管理,使得某一時刻最多只能有一個線程進(jìn)入臨界區(qū),實現(xiàn)對臨界資源的保護(hù)。

考慮下面用臨界區(qū)實現(xiàn)兩個線程對臨界資源互斥訪問的情形。 The 1st Thread The 2nd Thread 都要調(diào)用 Func_CriticalSection() 函數(shù),而 Func_CriticalSection() 內(nèi)部會對某一臨界資源進(jìn)行操作,為了保護(hù)這一臨界資源,我們用一個 WinCE CriticalSection 來實現(xiàn)。

圖一是該解決方案的一個場景。 The 1st Thread The 2nd Thread 進(jìn)入臨界區(qū)之前已經(jīng)創(chuàng)建( new )并初始化( InitializeCriticalSection() )了一個臨界區(qū)。試圖進(jìn)入該臨界區(qū)的線程首先必須獲得進(jìn)入該臨界區(qū)(通過 EnterCriticalSection() / TryEnterCriticalSection() )的資格 ,如果臨界區(qū)內(nèi)沒有線程,它就能進(jìn)入,否則必須被掛起等待。進(jìn)入臨界區(qū)的線程可以對臨界資源進(jìn)行操作( OpOnSharedResources() )。操作完成之后退出臨界區(qū)( LeaveCriticalSection () ),以允許其它線程進(jìn)入。圖一中第一個線程進(jìn)入臨界區(qū)還未退出之前,第二個線程因執(zhí)行 EnterCriticalSection() 一直在被掛起等待,第一個線程退出臨界區(qū)之后,第二個線程從等待中被喚醒,按照相應(yīng)的調(diào)度機(jī)制重新競爭獲得 CPU ,從而繼續(xù)執(zhí)行,完成臨界區(qū)內(nèi)的操作。

?

圖一、應(yīng)用臨界區(qū)( CriticalSection )實現(xiàn)同步

利用臨界區(qū)可以實現(xiàn)對臨界資源的互斥操作, WinCE 的臨界區(qū)應(yīng)用在同一進(jìn)程內(nèi),亦即實現(xiàn)的是同一進(jìn)程內(nèi)的線程間同步,不能應(yīng)用在進(jìn)程之間。

三、互斥體( Mutex

(本節(jié)內(nèi)容適用于 WinCE 1.01 及以上版本

互斥體( Mutex )顧名思義就是實現(xiàn)對共享資源實現(xiàn)互斥訪問的。 WinCE 中的互斥體的使用規(guī)則如下(按線程之間的同步為例):

? 互斥體可以是匿名互斥體也可以是命名互斥體;
? 線程創(chuàng)建互斥體的時候可以指定創(chuàng)建完畢它是否就立即擁有該互斥體;
? 某一時刻最多只有一個線程擁有給定的互斥體;
? 擁有互斥體的線程可多次獲得該互斥體;
? 線程可用 CreateMutex wait函數(shù) 來獲得互斥體。

看下面應(yīng)用互斥體的情景。 Thread1 創(chuàng)建并擁有了一個互斥體 g_hMutex[ 序列 1&2] 。互斥體 g_hMutex 是定義的全局量, thread2 可訪問到, Thread2 WaitForSingleObject() 試圖獲得該互斥體,因為此時 g_hMutex 是被 Thread1 擁有的,所以 Thread2 被掛起 [ 序列 3] Thread1 執(zhí)行了一些操作之后,又用 wait 函數(shù)試圖再次獲得了該互斥體,因為此時 g_hMutex 的擁有者還是 Thread1 ,所以 Thread1 立即再次獲得了該互斥體 [ 序列 4-6] Thread1 對互斥體 g_hMutex 保護(hù)的共享資源操作完畢,釋放該互斥體 [ 序列 7] ,但是因為 Thread1 兩次獲得了 g_hMutex ,所以 g_hMutex 的擁有權(quán)并沒有交出。等到 Thread1 再次釋放互斥體 g_hMutex[ 序列 8] 之后, Thread1 才失去了 g_hMutex 的擁有權(quán), Thread2 可競爭 g_hMutex 的擁有權(quán),如能成功擁有,就可從等待狀態(tài)被喚醒,完成對共享資源的訪問操作。

?

圖二、應(yīng)用互斥體( Mutex )實現(xiàn)同步

不 知道從上面的描述,讀者有又沒有看出互斥體與臨界區(qū)之間的區(qū)別。使用上,它們都實現(xiàn)的對共享資源的互斥訪問,但是臨界區(qū)是多個線程對同一段程序的執(zhí)行,這 段程序會訪問到臨界資源,所以它們是同一個進(jìn)程內(nèi)的多個線程;而互斥體的應(yīng)用情景是在線程之間獨立執(zhí)行,可以不是程序上的重疊,只是一個線程執(zhí)行到共享資 源的時候,有可能別的線程也要訪問該共享資源,所以要用互斥體來保護(hù)該共享資源。

由于互斥體上述的應(yīng)用范圍,它不但能應(yīng)用在同一進(jìn)程內(nèi)的線程之間,也能應(yīng)用在進(jìn)程之間。進(jìn)程之間可以通過命名互斥體來實現(xiàn)。一個進(jìn)程通過為 CreateMutex() 指定一個名字做參數(shù)來獲得已經(jīng)存在的互斥體的句柄,處理過程如下面程序所示。

? HANDLE? hMutex;

? hMutex = CreateMutex (
??????????????? NULL,?????????????????????? //
??????????????? FALSE,????????????????????? // Mutex object NOT initially owned
??????????????? TEXT("NameOfMutexObject")); // Muetx Name

? if (NULL == hMutex)
? {
??? // Something wrong, deal with it here.
? }
? else
? {
??? if ( ERROR_ALREADY_EXISTS == GetLastError () )
??? {
????? // CreateMutex() opened existing mutex."
????? // ...
??? }
??? else
??? {
????? // CreateMutex() created new mutex."
????? // ...
??? }
? }

進(jìn)程獲得已經(jīng)存在的互斥體的句柄之后,就可以如線程之間同步規(guī)則那樣來實現(xiàn)進(jìn)程之間的互斥體使用。

四、信號量( Semaphore

(本節(jié)內(nèi)容適用于 WinCE 3.0 及以上版本

信號量實體有一個數(shù)值指示當(dāng)前該信號量使用情況,當(dāng)前值的大小處于零和最大值之間。用下列操作原語實現(xiàn)信號量的同步操作(用線程間同步來說明):

P S, num :如果信號量當(dāng)前值減去 num 大于零,執(zhí)行該操作的線程獲得信號量,可繼續(xù)執(zhí)行,同時信號量的當(dāng)前值減小 num ;否則訪問線程被掛起等待
V S, num :信號量的當(dāng)前值增加 num (增加之后仍不大于最大值),如果有等待該信號量的線程被掛起,喚醒等待線程并按照相應(yīng)的調(diào)度機(jī)制參與調(diào)度。

信號量一般用來控制某類共享資源,最大值標(biāo)識該類資源的數(shù)目,執(zhí)行 P 操作是申請一定數(shù)目這類資源, V 操作是釋放一定數(shù)目的這類資源。在 WinCE 的信號量實現(xiàn)中,并未實現(xiàn) OpenSemaphore P 操作是用 wait函數(shù) 來實現(xiàn)的,而 V 操作由 ReleaseSemaphore 來實現(xiàn)。

看下面用信號量來控制數(shù)量為 2 的某類共享資源的使用情景。

?

圖三、用信號量( Semaphore )實現(xiàn)同步

Thread1 創(chuàng)建一個控制 2 個共享資源的信號量 [ 序列 1&2] ,并且自己用 WaitForSingleObject() 來申請一個資源,因為當(dāng)前可用的這類資源有 2 個,所以它就獲得了其中的一個 [ 序列 3&4] 。同樣地, Thread2 獲得了另外一個資源 [ 序列 5&6] 。但是當(dāng) Thread3 也申請這類資源的時候,因為此時已經(jīng)沒有這類資源,信號量的值為零,它就被掛起 [ 序列 7] 。擁有這類資源的線程釋放掉一個資源 [ 序列 8&9] ,并且滿足能滿足 Thread3 申請資源數(shù)目的要求, Thread3 競爭獲得了該資源 [ 序列 10]

信號量是實現(xiàn)同步的基本方法,在幾乎所有的多任務(wù)操作系統(tǒng)里面都做了信號量的實現(xiàn),其它一些同步機(jī)制其實可以通過信號量來實現(xiàn)。如果把信號量的最大值和初始值均設(shè)置為 1 ,那么它就可實現(xiàn)互斥體 ,即保證對共享資源互斥訪問的保護(hù)。如果把信號量的初始值設(shè)置為 0 ,等待別的線程 ReleaseSemaphore 來喚醒它,那么它就可實現(xiàn)事件( Event 機(jī)制。

信號量機(jī)制可以用在同一進(jìn)程內(nèi)的線程之間同步,也可以用在進(jìn)程之間的同步。進(jìn)程間同步的實現(xiàn)方法如同互斥體的此類實現(xiàn)。

五、事件( Event

(本節(jié)內(nèi)容適用于 WinCE 1.0 及以上版本

WinCE 系統(tǒng)中廣泛用到事件( Event )機(jī)制來實現(xiàn)線程之間的協(xié)調(diào)工作,具體表現(xiàn)在:

通知一個線程什么時候去執(zhí)行它的特定的任務(wù)
標(biāo)識事件的發(fā)生

WinCE 中的線程操作原語有 CreateEvent() SetEvent()/PulseEvent() ResetEvent() 等。創(chuàng)建 Event 的時候在 CreateEvent() 的參數(shù)中指定 Event 的初始狀態(tài)(觸發(fā)的 / 未觸發(fā)的),還要指定事件是否手動復(fù)位(手動復(fù)位是只有用 ResetEvent() 才能把事件狀態(tài)顯式地設(shè)置為未觸發(fā)的,自動復(fù)位是等待該事件的線程等待事件到來之后,系統(tǒng)自動把該事件的狀態(tài)復(fù)位為未觸發(fā)的)。線程等待事件仍然用 wait函數(shù)

下面是使用 Event 同步的簡單情況:

?

圖四、用事件( Event )實現(xiàn)同步

線程 Thread1 執(zhí)行過程中,要等到某個條件滿足(事件觸發(fā)),所以它創(chuàng)建了一個事件 Event (參數(shù)設(shè)置為:手動復(fù)位,初始條件為未觸發(fā)的),用 WaitForSingleObject() 來等待這個事件。線程 Thread2 執(zhí)行了一些操作之后,滿足了 Thread1 的條件,用 SetEvent 來觸發(fā)該事件。

?????? 除了可以用 SetEvent() 來觸發(fā)事件之外,也可以用 PulseEvent() 來觸發(fā),區(qū)別是 PulseEvent() 觸發(fā)該事件之后把它又復(fù)位。

?????? 另外,也可以把命名事件用于進(jìn)程之間的同步。實現(xiàn)方法同互斥體中的描述。

六、消息隊列( MsgQueue P2P

(本節(jié)內(nèi)容適用于 WinCE.net 4.0 及以上版本

消息隊列通信機(jī)制如同建立了一個管道,管道的雙方通過分別建立到管道的兩端,與管道的讀端口建立連接的進(jìn)程可以從該端口讀取消息( Message ),與管道的寫端口建立連接的進(jìn)程可以寫入消息( Message )到管道。管道內(nèi)消息組成了一個 FIFO F irst I n F irst O ut )的隊列,從讀端口讀取消息是讀取隊列的頭,寫入消息到寫端口是在隊列尾部追加一個消息。

WinCE 中關(guān)于 MsgQueue 的操作函數(shù)主要有:

CreateMsgQueue() 創(chuàng)建一個消息隊列。在該函數(shù)的參數(shù)中指定消息隊列的名字,消息隊列的最大數(shù)目,每個消息的最大長度,對該消息隊列可進(jìn)行讀還是寫操作等。因為調(diào)用一次 CreateMsgQueue 函數(shù),只能指定讀或者寫這樣的二選一的消息隊列,所以一般需要用相同的消息隊列名字做參數(shù)兩次調(diào)用該函數(shù),分別創(chuàng)建讀消息隊列和寫消息隊列,它們的返回值分別被讀進(jìn)程和寫進(jìn)程用 OpenMsgQueue() 打開用于讀取消息和寫入消息。
OpenMsgQueue() 打開消息隊列并建立與相應(yīng)端口的連接。進(jìn)程與讀端口建立連接之后,可用返回的句柄從消息隊列中讀取消息;進(jìn)程與寫端口建立連接之后,可用返回的句柄寫入消息到消息隊列中。
CloseMsgQueue() 斷開與消息隊列相應(yīng)的端口之間的連接,并關(guān)閉由 CreateMsgQueue() OpenMsgQueue() 創(chuàng)建或打開的消息隊列。
ReadMsgQueue() 如同從普通文件中讀取數(shù)據(jù)一樣,用于從消息隊列中讀取消息。可以指定讀取消息時,如果消息隊列為空,讀進(jìn)程是被掛起還是直接返回。
WriteMsgQueue() 如同寫數(shù)據(jù)到普通文件中一樣,用于寫消息到消息隊列中。可以指定寫入消息時,如果消息隊列已滿,寫進(jìn)程是被掛起還是直接返回。

下圖是 MsgQueue 應(yīng)用的典型場景。

?

圖五、用消息隊列( MsgQueue )實現(xiàn)同步

這種場景下的執(zhí)行過程為:

主進(jìn)程 MainProcess 創(chuàng)建了名為“ Reader/Writer MsgQueue ”的讀和寫的消息隊列,并分別返回 hMsgQ_r_m hMsgQ_w_m[ 序列 1-4]
讀進(jìn)程 ReaderProcess 以主進(jìn)程的 ProcessId hMsgQ_r_m 為參數(shù),通過 OpenMsgQueue() MainProcess 消息隊列的讀端口建立連接 [ 序列 5&6]
ReaderProcess 與消息隊列建立連接之后,用 WaitForSingleOnject(hMsg_r) 看消息隊列中是否有消息,因為此時消息隊列為空,所以 ReaderProcess 被掛起 [ 序列 7]
寫進(jìn)程 WriterProcess 以主進(jìn)程的 ProcessId hMsgQ_w_m 為參數(shù),通過 OpenMsgQueue() MainProcess 消息隊列的寫端口建立連接 [ 序列 8&9]
WriterProcess 與消息隊列建立連接之后,用 WaitForSingleOnject(hMsg_w) 看消息隊列中消息是否滿,因為此時消息隊列為空,未滿,所以 WriterProcess 不會被掛起 [ 序列 10&11]
WriterProcess 寫消息到消息隊列中 [ 序列 12&13]
因為消息隊列中已經(jīng)有了消息, ReaderProcess 從掛起狀態(tài)被喚醒 [ 序列 14]
ReaderProcess 繼續(xù)執(zhí)行,從消息隊列中讀取 WriterProcess 剛才寫入的消息。

消息隊列除可用于同步之外,主要用于進(jìn)程之間的數(shù)據(jù)傳遞,另外消息隊列也可以用于同一進(jìn)程中的線程之間同步,但是既然線程之間能直接傳遞數(shù)據(jù),又何必那么麻煩呢。

七、互鎖函數(shù)( Interlocked Function

(本節(jié)內(nèi)容適用于 WinCE 1.0 及以上版本)

除了上面各節(jié)的同步方法之外, WinCE 還提供了一些用于原子操作的互鎖函數(shù),這些函數(shù)在執(zhí)行過程中,不會因為線程的調(diào)度引起的當(dāng)前線程被搶占而打斷函數(shù)內(nèi)的操作。

這些函數(shù)主要有:

InterlockedIncrement
InterlockedDecrement
InterlockedExchange
InterlockedTestExchange
InterlockedCompareExchange
InterlockedCompareExchangePointer
InterlockedExchangePointer
InterlockedExchangeAdd

八、 Wait 函數(shù)

(本節(jié)內(nèi)容適用于 WinCE 1.0 及以上版本

Wait 函數(shù)不是特指的某一個函數(shù),而是指 wait 的系列函數(shù)。 wait 函數(shù)并不是 WinCE 同步機(jī)制中的一種,但是 WinCE 的很多同步機(jī)制要用到 wait 函數(shù),這些在前面講述各個同步方法的時候也已有論述。

一般地,執(zhí)行 wait 函數(shù)時,如果等待的同步對象條件不滿足,那么執(zhí)行 wait 函數(shù)的進(jìn)程 / 線程會被掛起,當(dāng)然也可以給它們設(shè)置等待的超時時間,超過給定時間,不管條件是否滿足,它們會自動從等待狀態(tài)蘇醒。等待既可以等待某一個條件,也可以等待多個條件中的一個, WinCE 不支持等待多個條件同時滿足,如果有這種需要,要自己實現(xiàn)。

Wait 函數(shù)原型如下:

DWORD WaitForSingleObject (HANDLE hHandle, DWORD dwMilliseconds );

DWORD WaitForMultipleObjects (
? DWORD nCount,????????????? // No. of object handles in the array.
? CONST HANDLE* lpHandles,?? // Pointer to an array of object handles.
? BOOL fWaitAll,???????????? // MUST be FALSE in WinCE
? DWORD dwMilliseconds?????? // Timeout (0, mills, or INFINITE)
);

DWORD MsgWaitForMultipleObjects (
? DWORD nCount,???????????? // No. of object handles in the array.
? LPHANDLE pHandles,??????? // Pointer to an array of object handles.
? BOOL fWaitAll,??????????? // MUST be FALSE in WinCE
? DWORD dwMilliseconds,???? // Timeout (0, mills, or INFINITE)
? DWORD dwWakeMask????????? // Input types for which an input event object handle
);

前面講述各種同步機(jī)制的時候都是以 WaitForSingleObject() 來說明的,這里就不再贅述它了。

WaitForMultipleObjects() MsgWaitForMultipleObjects() 可以用來等多個同步對象,它們之間的區(qū)別就是 MsgWaitForMultipleObjects() 還等待 dwWakeMask 參數(shù)中指定的輸入事件,即這些事件發(fā)生時,等待的進(jìn)程 / 線程也能被喚醒。

WaitForMultipleObjects() 等待的多個同步對象的句柄放在參數(shù) lpHandles 數(shù)組中,同步對象的句柄的數(shù)目放在參數(shù) nCount 中。 dwMilliseconds 指定了等待的超時參數(shù):如果指定為 0 ,該函數(shù)等待每個同步對象之后,不管觸發(fā)與否都直接返回;如果指定為 INFINITE ,該函數(shù)等待每個同步對象,直到有一個同步對象被觸發(fā),否則執(zhí)行該函數(shù)的運(yùn)行實體將一直被掛起;如果指定為非 0 ,非 INFINITE 的一個數(shù)值,那么不管 等待的同步對象是否被觸發(fā),到了指定的時間,執(zhí)行該函數(shù)而被掛起的運(yùn)行實體也會被喚醒。因哪個同步對象被觸發(fā)而返回還是因超時而返回,可以從返回值中來判定,返回值為 WAIT_TIMEOUT ,是因為超時; 返回值為 WAIT_OBJECT_0 WAIT_OBJECT_0 + nCount -1 之間的數(shù)時,可以按順序找到具體那個同步對象被觸發(fā)

下面是 WaitForMultipleObjects 的典型應(yīng)用。

? HANDLE hSynchObjects[EVENT_COUNT];
? DWORD dwEvent;

? /* Put event handles in hEvents */
? // ...
?
? dwEvent = WaitForMultipleObjects (
????????????????????? EVENT_COUNT,??????? // Number of objects in an array
????????????????????? hSynchObjects,????? // Array of objects
????????????????????? FALSE,????????????? // MUST be FALSE
????????????????????? 500);?????????????? // timeout, 0.5s

? switch (dwEvent)
? {
??? case WAIT_TIMEOUT:
????? // Handle for timeout
????? break;
?????
??? case WAIT_OBJECT_0 + 0:
????? // Handle the 1st event
????? break;
?????
??? case WAIT_OBJECT_0 + 1:
????? // Handle the 2nd one
????? break;

??? ...
???
??? case WAIT_OBJECT_0 + EVENT_COUNT -1:
????? // Handle the final one
????? break;

??? default:
????? // Error: Not an anticipant one, handle it.
????? break;
? }

總結(jié)

本文探討了 WinCE 中的各種同步機(jī)制的用法,并給出了它們的典型應(yīng)用場景。關(guān)于它們進(jìn)一步的高級話題,將在后續(xù)文章中探討。

參考資料以及進(jìn)一步閱讀

1) MSDN
2) UML Reference Manual, 2nd Edition
3 ) Abraham Silberschatz, Peter Baer Galvin, Greg Gagne. Operating System Concepts, 6th Edition. John Wiley & Sons, Inc/ 高等教育出版社影印 , 2002.5
4
) David R. Butenhof/ 于磊,曾剛 . Programming with POSIX Threads. Addison Wesley/ 中國電力出版社 , 2003

?

總結(jié)

以上是生活随笔為你收集整理的Windows® CE 系统中的同步机制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。