2011年12月16日 星期五

Memory Mapped Files 初探

因為又要recording video 同時又要能 print 2Kx3K 的超高清圖片
記憶體根本不夠。所以得由我單方面來節省記憶體的使用量(另一面的Programmer, 老闆, 實在太忙了)

想了想沒有什麼節省的辦法,記憶體總共有三次配置,
一個是 alloc 2Kx3Kx3 = 23M 的buffer, 做為排版使用和最終 print 的buffer。
二是把圖片資料讀進來的buffer 約為1920x1080x3= 6M大小,這個也無法省。
三是把圖片rotate 或 resize 的buffer ,我不知道這個如何省。

最後只有最簡單 寫入檔案
也就是把Disk 當成記憶體來用
想到的就是 Memory Mapped File

在Windows 上,其流程就是
CreateFile --> CreateFileMapping --> MapViewOfFile --> 開始使用
結束則是
UnmapViewOfFile --> Close FileMapping --> Close File

在此列出實驗後的要點
1. 在WINCE 上,用CreateFile 之後的Handle 來傳入 CreateFileMapping 一直都會失敗,回傳 6 ( ERROR_INVALID_HANDLE ), 要用CreateFileForMapping 取代 CreateFile 開檔就ok。 在WINCE 上
CreateFileMapping 似乎不接受 CreateFile 所產生的 HANDLE。

2. CreateFileMapping 用PAGE_WRITECOPY 失敗用 PAGE_READWRITE 成功

2011年12月13日 星期二

CreateProcess 呼叫另一個程式

同事在用 CreateProcess 呼叫我寫的程式的時候
有出點問題

 把 CreateProcess 做個重點整理
( All Info is describe in Jeffery Ritcher's Windows Via C/C++, Chap 4 )

1. 同事用 loop 一直判斷 子Process 結束了沒,這是很不好的做法,浪費CPU時間。
 if ( GetExitCodeProcess() == STILL_ACTIVE )

而且,如果子程式笨笨的 不小心把 STILL_ACTIVE (259, 0x103) 做為傳回值之一會讓Parent Process 誤判,這會是個很不容易發現的錯誤。

2. CreateProcess 後, PROCESS_INFORMATION 會回傳 2 個handle, 一個Process Handle, 一個Thread Handle。記得沒用的話要使用CloseHandle關掉,
不然的話就得等到Parent Process 整個結束的時候才會free。
其概念就是 系統在創建 Kernel Object 時會把reference counter 加一,
reference counter 為0時 才會真正destroy object. 所以回傳的 PROCESS_INFORMATION  Process Handle, 在 child process 結束後並不會被free, (否則如何 call GetExitCodeProcess?) 必需自己手動CloseHandle。所以一個Process 的Handle 可能會活得比Process更久. This is a feature, not a bug.

3. 整個流程如下

PROCESS_INFORMATION pi;
DWORD dwExitCode;

// Spawn the child process.
BOOL fSuccess = CreateProcess(..., &pi);
if (fSuccess) {
// Close the thread handle as soon as it is no longer needed!
CloseHandle(pi.hThread);
// Suspend our execution until the child has terminated.
WaitForSingleObject(pi.hProcess, INFINITE);
// The child process terminated; get its exit code.
GetExitCodeProcess(pi.hProcess, &dwExitCode);
// Close the process handle as soon as it is no longer needed.
CloseHandle(pi.hProcess);
}

第一個CloseHandle(hThread) 並不會真正把 child process 的primary thread 停掉 (因為 usage counter 並不為0) , 所以這也是沒事就在第一行先把它 close掉的原因)

As already mentioned, creating a new process causes the system to create a process kernel object and a thread kernel object. At creation time, the system gives each object an initial usage count of 1. Then, just before CreateProcess returns, the function opens with full access to the process object and the thread object, and it places the process-relative handles for each in the hProcess and hThread members of the PROCESS_INFORMATION structure. When CreateProcess opens these objects internally, the usage count for each becomes 2.