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.

2011年11月28日 星期一

boost Traverse directory

在看 Effective C++ 3rd 的時候,最後第55條寫 Familiarize yourself with boost.
其中簡述了 boost 的功能,我看到一項 Traverse file system 的功能。
這不正是我想要又常用的功能嗎?

於是搜尋了Google 找到以下網頁
http://stackoverflow.com/questions/2550309/traversing-a-directory

原始碼如下

#include 
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
#define foreach BOOST_FOREACHnamespace fs = boost::filesystem;

fs::recursive_directory_iterator it(top), eod;
foreach (fs::path const & p, std::make_pair(it, eod)) {
    if (is_directory(p)) {
        ...
    } else if (is_regular_file(p)) {
        ...
    } else if (is_symlink(p)) {
        ...
    }
}
第二種寫法                                                                       using namespace boost::filesystem;
using namespace std;                                                                    path Path = "e:\\";
 for(recursive_directory_iterator it(Path); it != recursive_directory_iterator(); ++it)
 {
  if ( is_directory(*it) )
   cout << *it << it.level() << endl;
 }
然後開啟Visual Studio ,試著去編譯這個 boost 範例
1. 要 add include directory \boost_1_46_1\
2. 之後會出現無法 link libboost_filesystem-vc90-mt-gd-1_46_1.lib
這是因為沒有build boost lib
3. 有些boost library 需要build,使用 cmd prompt, 在 \boost_1_46_1\ 下,執行bootstrap
4. boostrap 會build bjam, 但是此處失敗了 因為include 不到 windows.h (因為Windows SDK 7沒裝完整 )。失敗原因從 bootstrap.log 中可以看出。重新執行Windows SDK setup 把Windows header 裝上,然後執行Windows SDK 下的Configuration Tool 設定好預設的SDK。
5. 設好了 include 後,之後 cannot open input file 'kernel32.lib', 所以 LIB 也要設置正確
6. 最後編譯成功後,會提示你 include 要加入 E:\boost_1_46_1, lib 要加入 E:\boost_1_46_1\stage\lib
7. 編譯過程中會出現一些Warning, 跟 D_SCL_SECURE_NO_DEPRECATE  有關, 詳情請google
(Visual Studio 2005 SP1以後 use _SCL_SECURE_NO_WARNINGS ) Standard C++ Library
_SCL_SECURE_NO_WARNINGS
_CRT_SECURE_NO_WARNINGS
_AFX_SECURE_NO_WARNINGS
_ATL_SECURE_NO_WARNINGS
http://connect.microsoft.com/VisualStudio/feedback/details/101151/scl-secure-no-deprecate-is-not-found-by-search
Message: 'Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators''
正確解法要改用 Checked Iterators, and safe functions _s
http://msdn.microsoft.com/en-us/library/aa985872(v=VS.80).aspx

2011年11月7日 星期一

Build Cross Compiler GCC


1. Download
gcc 4.6.2
binutils 2.21.1a
gmp 5.0.2
mpfr 3.1.0
mpc 0.9
newlib 1.19



2. Build binutils
有 build system
     host sytem
     target system

The GNU autotools packages (i.e. autoconfautomake, and libtool) use the notion of a build platform, a host platform, and a target platform. The build platform is where the code is actually compiled. The host platform is where the compiled code will execute. The target platform usually only applies to compilers. It represents what type of object code the package itself will produce (such as cross-compiling a cross-compiler)



  1. build 就是你现在使用的机器。
  2. host 就是你编译好的程序能够运行的平台。
  3. target 编译程序能够处理的平台。一般都用在构建编译本身的时候(gcc), 才用target, 也就是说平时我们所说的交叉编译用不到target.

2.
參考這兩篇
3. 裝cygwin 1.7.9-1
default 之外還需要
-- dev
gcc-core
gcc-c++
make
-- interpreter
m4


4. build binutils
--target 不適用 用--build 和 --host  

要加 libiconv 不然會 make 失敗

5. build GMP
不能用 --target 要改用 --host 及 --build ( 沒有--build 會有warning)






Cross Compilation, --host=CPU-VENDOR-OS







When cross-compiling, the system used for compiling is given by `--build' and the system where the library will run is given by `--host'. For example when using a FreeBSD Athlon system to build GNU/Linux m68k binaries,
./configure --build=athlon-pc-freebsd3.5 --host=m68k-mac-linux-gnu
     
Compiler tools are sought first with the host system type as a prefix. For example m68k-mac-linux-gnu-ranlib is tried, then plain ranlib. This makes it possible for a set of cross-compiling tools to co-exist with native tools. The prefix is the argument to `--host', and this can be an alias, such as `m68k-linux'. But note that tools don't have to be setup this way, it's enough to just have a PATH with a suitable cross-compiling cc etc.
Compiling for a different CPU in the same family as the build system is a form of cross-compilation, though very possibly this would merely be special options on a native compiler. In any case `./configure' avoids depending on being able to run code on the build system, which is important when creating binaries for a newer CPU since they very possibly won't run on the build system.
In all cases the compiler must be able to produce an executable (of whatever format) from a standard C main. Although only object files will go to make up libgmp, `./configure' uses linking tests for various purposes, such as determining what functions are available on the host system.
Currently a warning is given unless an explicit `--build' is used when cross-compiling, because it may not be possible to correctly guess the build system type if the PATH has only a cross-compiling cc.
Note that the `--target' option is not appropriate for GMP. It's for use when building compiler tools, with `--host' being where they will run, and `--target' what they'll produce code for. Ordinary programs or libraries like GMP are only interested in the `--host' part, being where they'll run. (Some past versions of GMP used `--target' incorrectly.)


../gmp-5.0.2/configure --build=i686-cygwin --host=i686-cygwin --prefix=$PREFIX



6. build gcc
gcc 4.6.2 需要 GMP 4.2+, MPFR 2.3.1+, MPC 0.8.0+

1. build gcc 時可以下 make all-gcc 及 make all-install,如此只編譯 gcc,g++,其它的連結庫就不會去編譯,而造成一堆錯誤。
6. 如果只是要編 language c 則不需要 newlib,但是要有 c++ language 時,必需包含 newlib,而且需要 1.14.0,不要 1.15.0,編譯會過不了。


make all-gcc 後會有錯誤,沒有pod2man
這個要安裝 perl 才能解決


 --enable-languages=c,c++


build ARM-EABI 時沒問題
build MIPS-ELF 在 libstdc++ 時 會出現 No support for this host/target combination.
因為在 libstdc++ 下的 crossconfig.m4 沒有 support MIPS-ELF ( cygwin/mips-elf) ?


config.log 會有 configure 時的資訊


sde vs uclibc vs eglibc vs glibc




============================================




From Start
1. Download 
gcc 4.7.1
binutils 2.22
newlib 1.20
gmp 5.0.5
mpfr 3.1.0


2. binutils


make needs libiconv 


gmp
configure needs m4


mpfr

 ./configure --with-gmp=$PREFIX



3.

../gcc-4.1.1/configure --target=$TARGET --prefix=$PREFIX --without-headers --with-gmp=$PREFIX



use --enable-obsolete if compile arm-elf ....

4. When all done, compile booter
 出現 linker error
section .text.startup overlap with .data
這個問題好像是 gcc 4.6 以後會出現的 ( or binutils 2.21?)
通常 .data 的 linker script 是如下面這樣寫的
.data 0x81000000 :
  AT ( ADDR(.text) + SIZEOF(.text) )
但是好像後來又多出了一個 .text.startup section
所以 .data 就會跟 .text.startup 重疊 (開頭位置完全一樣)
所以最簡單且正確的改法是 再加上 .text.startup 的size
 .data 0x81000000 :
  AT ( ADDR(.text) + SIZEOF(.text) + SIZEOF(.text.startup) )

可以用 readelf , objdump 來看
http://www.linuxforums.org/articles/understanding-elf-using-readelf-and-objdump_125.html

5. 再來 build gdb 
需要裝 termcap

但是裝了 termcap 並沒有解決
再裝了 libncurses 也沒有解決
要裝 devel 目錄下的 libncursesw-devel 才 ok

2011年9月13日 星期二

人生失敗的六個原因

http://citytalk.tw/bbs/forum.php?mod=viewthread&tid=44240
搜尋"失敗的人生"時 所發現的網站
寫得很不錯


一, 處世無方
 二,入錯了行
 三,不能投入
 四,缺乏創造性
 五,目標太散
 六,做事本末倒置