新買了1G的記憶體,所以follow pchome的說明,把paging 關掉。
用Regedit,把..
[ HKLM ] - [System] - [Current Control Set] - [ Control ] - [ Session Manager ] - [ Memory Management] 的 ' DisablePagingExecutive ' 這一個Item由 ' 0 ' 改為 ' 1 ' 就可以了。
* 這個item 是說要不要disable Paging。所以 ' 1 ' 是 disable。
將來如有需要,再把他改回 ' 0 ' 就可以了。
7.09.2007
7.05.2007
share data in DLL
CE 的DLL 在使用上應該當作是code archive (.a)。--- 省略RAM, 和loading 問題不管的話。
所以DLL 中的變數scope 也僅限於使用 (link到) 該DLL 的exe 檔而已。
所以說..link 同一個DLL的兩個exe檔,無法藉由那個DLL來溝通。
因為每一個exe 檔有自己的DLL空間。
但是... 還是有辦法的.. 就是在DLL中增加一個share data 區塊。
宣告在share 區塊的variable 會是所有link 該dll 的exe檔都共用的。
宣告的方式:
在 c code 中:
msdn 說明的地方在 http://msdn2.microsoft.com/en-us/library/h90dkhs0(VS.80).aspxmsdn中說明得很清楚。
所以DLL 中的變數scope 也僅限於使用 (link到) 該DLL 的exe 檔而已。
所以說..link 同一個DLL的兩個exe檔,無法藉由那個DLL來溝通。
因為每一個exe 檔有自己的DLL空間。
但是... 還是有辦法的.. 就是在DLL中增加一個share data 區塊。
宣告在share 區塊的variable 會是所有link 該dll 的exe檔都共用的。
宣告的方式:
在 c code 中:
#pragma data_seg(".shared")
共用變數區- 宣告時一定要初始化。否則無效。
#pragma data_seg()宣告出一個區域,然後在DLL的def 檔中,宣告該 .shared 區段是 share:SECTIONS
.shared READ WRITE SHARED
msdn 說明的地方在 http://msdn2.microsoft.com/en-us/library/h90dkhs0(VS.80).aspxmsdn中說明得很清楚。
- 有一堆variable 不會被放到share segment,即使你宣告在那裡也沒用,
- 還有要注意一件事,因為DLL mapping 到每一個exe檔的virtual address 並不相同,所以不可能share pointer。
- 還有.. process 的 HANDLER 只對該process有用,所以放在share seq,讓另一個exe 存取的話,會有意外的情況。
- c++ 的class 和 static variable 也別想,在class load時,該variable 會被re-initialize,造成混亂。
6.27.2007
Win32 的同步物件 - 一些
Citical Section
Critical Section 可以重複進入 ( 正確的說,是對已經進入Critical Section 的Thread而言..),但是進入的次數和退出的次數必須要一樣,才可以正確離開critical section。
和Critcal Sectin 類似的mutex 元件,使用上要比Critical Section 花比較多的時間(約100倍)。因為critical section 可以在user space中完成,mutex卻一定要進入kernel space。
所以 Critical Section 只能用在同一個process中,各thread之間的同步。無法做到 process間的同步。
mutex就可以用在 process間。
... 所以 criticalsection 沒有 "name",mutex可以有name (在create時指定)。
Semaphore
Semaphore 是counting semaphore,在 CreateSemaphore( )時就要指定 maximum counting number。
Event
Event 有AutoReset和ManualReset 兩種 (CreateEvent( )時指定)。ResetEvent( )把Event 設定為un-triggered。 SetEvent( )和 PulseEvent( )都可以把Event設定為Trigger。
PulseEvent( )是特殊的:
InterlockedXXX
這是用在multi-tasking 系統中常用的 if(xx > 0) xx--; 的問題,避免在if( )後被task switch 掉,導致 回來執行時,xx已經改變。所以提供一個atomic lock++, lock-- 的function。
如其名所示,InterlockXX 只能作相對於0的判斷。
其他,就是上次提到的... Thread 本身也是一個同步物件。
Critical Section 可以重複進入 ( 正確的說,是對已經進入Critical Section 的Thread而言..),但是進入的次數和退出的次數必須要一樣,才可以正確離開critical section。
和Critcal Sectin 類似的mutex 元件,使用上要比Critical Section 花比較多的時間(約100倍)。因為critical section 可以在user space中完成,mutex卻一定要進入kernel space。
所以 Critical Section 只能用在同一個process中,各thread之間的同步。無法做到 process間的同步。
mutex就可以用在 process間。
... 所以 criticalsection 沒有 "name",mutex可以有name (在create時指定)。
Semaphore
Semaphore 是counting semaphore,在 CreateSemaphore( )時就要指定 maximum counting number。
Event
Event 有AutoReset和ManualReset 兩種 (CreateEvent( )時指定)。ResetEvent( )把Event 設定為un-triggered。 SetEvent( )和 PulseEvent( )都可以把Event設定為Trigger。
PulseEvent( )是特殊的:
- Event是AutoReset : PulseEvent( )只會Wakeup 一個Waiting Event的Thread。然後恢復un-trigger。
- Event是ManualReset : PulseEvent( )會Wakeup 所有Waiting Event的Thread,然後恢復un-trigger。
HANDLE WINAPI CreateEvent(
__in_opt LPSECURITY_ATTRIBUTES lpEventAttributes,
__in BOOL bManualReset,
__in BOOL bInitialState,
__in_opt LPCTSTR lpName
);InterlockedXXX
這是用在multi-tasking 系統中常用的 if(xx > 0) xx--; 的問題,避免在if( )後被task switch 掉,導致 回來執行時,xx已經改變。所以提供一個atomic lock++, lock-- 的function。
如其名所示,InterlockXX 只能作相對於0的判斷。
- int InterlockedIncrement( *count ) : 將count++,如果 > 0,return 1,等於0 return 0,小於0 return 負值
- int InterlockedDecrement( *count) : 將count--....
- int InterlockedExchange( *var, newvalue) : return oldvar回來。
其他,就是上次提到的... Thread 本身也是一個同步物件。
UpdateData in Thread
在Thread 中call UpdateData( )會導致Crash。
據說,Win32 programming 有一條Rule(http://forums.ni.com/ni/board/message?board.id=231&message.id=4331):
所以,可以用UpdateData( )這個funciton 的,也只有Dialog 自己這個thread 囉。
那Dialog create 出來的Thread 要怎麼update dialog 的data呢?
一般的解法是用Message,Thread Post Message,叫Dialog UpdateData。
例如在 這一篇 (http://forums.microsoft.com/msdn/showpost.aspx?postid=95099&siteid=1)所列出的code :
看起來似乎OK,但是在CE這種,OEM到處定義WM_USER+XX 的系統,要找到一個safe 的 message number 還真不容易呀,稍不小心就會誤觸地雷。
Robert 說WM_USER+XX 的scope只在同一個AP。所以不用擔心會有和其他AP重複定義的問題。
另外Robert說在Thread中和Dialog要互通資料,一般會用Timer Trigger,比較安全,然後其中用queue來傳遞資料。
不然就要一勞永逸,大家都用PostMessage,由Dialog的WinProc 統一UpdateData( )。
關於Thread中呼叫UpdateData( )來Update UI 內容,這一篇(http://blog.csdn.net/jeven2005/archive/2007/02/14/1510039.aspx)也有詳細的說明:解法也是使用USER MESSAGE。
關於這一點還真有名呀,另外類似的rule有:
這一篇(http://www.codeproject.com/cpp/
avoidupdatedata.asp?df=100&forumid=696&exp=0&select=845137)的
據說,Win32 programming 有一條Rule(http://forums.ni.com/ni/board/message?board.id=231&message.id=4331):
"Thou shall not access UI controls from a thread other than the one that created the UI control in the first place"因為Dialog 不是Thread Safe。
所以,可以用UpdateData( )這個funciton 的,也只有Dialog 自己這個thread 囉。
那Dialog create 出來的Thread 要怎麼update dialog 的data呢?
一般的解法是用Message,Thread Post Message,叫Dialog UpdateData。
例如在 這一篇 (http://forums.microsoft.com/msdn/showpost.aspx?postid=95099&siteid=1)所列出的code :
然後其他的Thread 都呼叫UpdateUserData( )來代替 UpdateData( )。#define WM_USER_UPDATE_DATA ( WM_USER + 1 )
void UpdateUserData( BOOL bUpdate )
{
SendMessage( WM_USER_UPDATE_DATA, bUpdate, 0 );
}
LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
if( message == WM_USER_UPDATE_DATA ) {
if( wParam )
UpdateData( TRUE );
else
UpdateData( FALSE );
}
}
看起來似乎OK,但是在CE這種,OEM到處定義WM_USER+XX 的系統,要找到一個safe 的 message number 還真不容易呀,稍不小心就會誤觸地雷。
Robert 說WM_USER+XX 的scope只在同一個AP。所以不用擔心會有和其他AP重複定義的問題。
另外Robert說在Thread中和Dialog要互通資料,一般會用Timer Trigger,比較安全,然後其中用queue來傳遞資料。
- 所以如果說是經常update的資料,就用Timer。
- 如果是偶而才 update一次,就用 WM_USER+XX。
- 在Dialog 本身的Thread中,用UpdateData
- 在其他的Thread中,用PostMessage( )通知Dialog作UpdateData( )。
不然就要一勞永逸,大家都用PostMessage,由Dialog的WinProc 統一UpdateData( )。
關於Thread中呼叫UpdateData( )來Update UI 內容,這一篇(http://blog.csdn.net/jeven2005/archive/2007/02/14/1510039.aspx)也有詳細的說明:解法也是使用USER MESSAGE。
關於這一點還真有名呀,另外類似的rule有:
這一篇(http://www.codeproject.com/cpp/
avoidupdatedata.asp?df=100&forumid=696&exp=0&select=845137)的
DO NOT EVER TOUCH A WINDOW FROM A THREAD.
6.26.2007
eVC+VSS : ClassView will not be available
當eVC 配合VSS 使用時,如果是先用eVC將project create好,再把整個project 拉進VSS。然後再開啟時,由於VSS會把所有的 file 都改為read-only,導致eVC開啟會出現:
eVC很奇怪,如果你不管,繼續開啟,還是可以正常build project,但是在run debug program時,會出現error 無法launch program。
Cannot access the ClassView information file. ClassView information will not be available這時候,只要把所有的file 都改成 read/write 就可以正常開啟了。
eVC很奇怪,如果你不管,繼續開啟,還是可以正常build project,但是在run debug program時,會出現error 無法launch program。
6.25.2007
SendMessage Hang.
遇到一個糟糕的問題:
UI 的 message handler 中 正在wait 一個 low priority thread的 semaphore。
這個low priority thread 此時 SendMessage( )給 UI。
導致 low priority thread hang 著 -- 應該說是UI和thread都Hang著。
直到 UI Handler 的wait timeout後,處理完low priority thread 的SendMessage( )後。
那個low priority thread 才有機會執行。
理論上..low priority thread 的SendMessage動作,只是將messasge放進 UI 的message queue中。
即使UI的priority 比較高,但是他的state 是Waiting,所以控制權應該要立刻交回low priority thread 才對呀。
OS做到這樣有點糟糕喔..有點 priority inversion 沒做好的感覺 (其實還沒到這裡)。
同樣的一句....還是我又在耍白痴?
的確,又是我在耍白痴。
感謝 Kun-Yi 的告知(ref comment),原來 SendMessage( )就是會block and wait return。
放到message queue的是PostMessasge( )。
依照Kun-Yi 所說的修改後,block 現象就消失了。
UI 的 message handler 中 正在wait 一個 low priority thread的 semaphore。
這個low priority thread 此時 SendMessage( )給 UI。
導致 low priority thread hang 著 -- 應該說是UI和thread都Hang著。
直到 UI Handler 的wait timeout後,處理完low priority thread 的SendMessage( )後。
那個low priority thread 才有機會執行。
理論上..low priority thread 的SendMessage動作,只是將messasge放進 UI 的message queue中。
即使UI的priority 比較高,但是他的state 是Waiting,所以控制權應該要立刻交回low priority thread 才對呀。
OS做到這樣有點糟糕喔..有點 priority inversion 沒做好的感覺 (其實還沒到這裡)。
同樣的一句....還是我又在耍白痴?
的確,又是我在耍白痴。
感謝 Kun-Yi 的告知(ref comment),原來 SendMessage( )就是會block and wait return。
放到message queue的是PostMessasge( )。
依照Kun-Yi 所說的修改後,block 現象就消失了。
訂閱:
文章 (Atom)