2011年3月12日 星期六

uClinux 新手筆記

如果想要知道一些概念,這篇是很好的總整理:
[ uClinux for Linux Programmers ]

大致上的摘要是這樣:
  uClinux 給沒有 MMU 的 CPU 使用,因此不支援原來
  Linux 的 Virtual Memory (VM) 環境。

  沒有 VM,process 不能於 run time 時期增加 process
  address space,所以 brk/sbrk() 無法被實做,
  也不能用 tmpfs,因為它依賴於 VM 的支援。

  沒有 VM,每一支 uClinux app 都要在 run time 時由系統來作 relocation。
  而且是 sequential && contiguous. 的排在 file system 內,一次就得載入
  整個程式 於連續的 physical memory 上,所以只能用 romfs。

  傳統的 power of 2 memory allocation 機制在這裡會造成許多浪費
 (例如要 33k 會給 64k),所以可選其他的 memory allocation 機制
  ,例如 page_alloc2 或 kmalloc2。
  page_alloc2 以 4k 為單位分配 (例如要 33k 會給 36k)
  kmalloc2 以 8k 為判斷,大於 8k 的需求從 free memory 的底部拿,
  小於 8k 的從 free memory 的起始處拿。這樣的好處是減少由
  短暫而多次的 allocation --- 如網路程式的 buffer --- 引起的碎片問題。

  沒有 VM,對應用程式來說,就沒有 dynamic stack 可用,一旦程式超出
  stack 範圍,會引發不可預期的結果。程式要自己知道需要多大的 stack,
  在 compile time 就必須決定好。
  heap 也不能使用 VM 機制,所以 uClinux 使用了 kernel free memory
  當作一個大的 system memory pool.
 
  對於應用程式與程序來說,uClinux 沒有提供 fork();只提供替代的 vfork(),
  有別於 fork(),使用 vfork() 會使得 parent process suspend 直到
  child process  結束 或 執行 exec() 為止

  fork() 發生後,parent & child process 有各自的資源 (address space 與 stack),
  parent & child process 沒有任何共用的東西。
  反觀 vfork() ,它會使得 child process 與 parent process 共用 stack。
  因此 vfork() 後,parent process suspend 了,若此時 child process 從現在的
  stack frame 返回上層,則會影響到 parent  process stack ---
  應用程式必須自行注意,確保不會發生這種情形!(心得:難怪
  網路上有人建議 busybox API 加上 fork_and_exit())!
  另外,child process 也必須使用 _exit() 而不能用 exit() ,
  原因也是因為 stack 共用。

  沒有 VM,uClinux 的程式只能使用 flat executable format (bFLT),
  這有兩種型態:
  一、code text & data 都是 relocatable
  二、Compile 出 PIC 碼 (Position Independent Code)
         只有部份 data 需要 relocation 即可。
  其中第二項衍生出 XIP (eXecute In Place) ,就是程式可以直接在 ROM
  上面執行的方式,因為 ROM 是 read only,可以被多個 instance share 使用。

  因為 romfs 上面的程式是 contiguously 排放的,這使得 romfs 是唯一可支援
  XIP 的 file system。
  從這裡可推出這樣的關係:做出 XIP 系統 需要 compiler 支援 PIC 碼。目前
  只有 m68k & ARM 有這樣的 gcc compiler.

  編出 bFLT 的程式,其實就是先編出 ELF 格式,再由 linker 轉換。只要
  compile 選項使用 -Wl,-elf2flt 即可作到。另外例如 -Wl,-elf2flt=s16384 這樣
  可以指定 stack 為 16k,toolchain default stack is 4k。(心得:有時
  default 是不夠的)

  再來談到 shared library,僅僅想用gcc -shared 選項,無法幫你在 bFLT
  格式中製作  shared library。(心得:下面有 Analog Device 網站上
  的好文詳細描述如何製作 shared library for uClinux)
  這裡只提一個重要概念,shared  library 必須是 XIP ,否則在每個
  uClinux application 都會產生一份 copy --- 這種情形比 static linking
  還要糟糕!

  結論:伴隨著 NOMMU,uClinux 衍生出這些 與 Linux 的不同處
             uClinux 應用程式開發者,需要自行注意。
摘要(完)

[ 認識 bFLT ],當然增加概念,但是對於開發程式,沒有直接幫助。

另外,下面這幾篇好文,並沒有排在 google 的前面,但是對於在 uClinux
下開發程式, 極有幫助,特此紀錄之。
1.  Executable file formats
2.  elf2flt 的說明
3.  用 flthdr (flat header)工具來看 bFLT 檔案
4.  Creating Libries

一些 uClinux mailing list 的摘要:
[ Problems building for uClinux ]: Jamie Lokier 有教讀者一些 narrow down problem 的方法,很實用!
還有遇到 error: no memory region specified for loadable section `.plt` 的現象,是因為 linker 遇到 .plt .got ,使其無法 link 成 BFLT program--- 這個 error 在 porting  program for uClinux 時很常遇到.

1. BFLT program 的製作 ,其實就是 compile 出 elf 後,再用 elf2flt  轉換成 BFLT format program,一般都用 CFLAGS += -elf2flt 告訴 compiler 在 link time 時幫我們轉換。

2. 若您的程式有自己的 lib ,而且是 static link 的方式,則 lib 先只是作成 elf ,然後 archive 起來 ,用 ranlib 做出 library index (方便 linking ,可有可無),等到和 program linking 時才使用 elf2flt  轉換成 BFLT.

#



沒有留言:

張貼留言