在許多嵌入式開發的系統中,由於沒有檔案系統,所以對於檔案的處理不太方便。如果是一個很小的檔案,可以做成數組形式。可如果檔案稍大該如何處理呢?有沒有一種更好的辦法?呵呵,辦法當然是有的。
假定我們有一個文字檔(一般需要嵌入的都是圖片檔案或者bin檔案,此處只是為了方便示範)data,需要把這個檔案做成.o檔案,並編譯到最終程式中。
首先執行objcopy命令:objcopy -I binary -O pe-i386 -B i386 data data.o 由於本人是在Cygwin下測試,所以-O選擇執行程式檔案格式為pe-i386,-B選擇架構為i386。
然後用nm命令查看產生的data.o檔案:
$ nm data.o
00000241 D _binary_data_end
00000241 A _binary_data_size
00000000 D _binary_data_start
好了,我們看到data.o中有三個對象,_binary_data_end、_binary_data_size和_binary_data_start,對象產生的命名規則是固定的,所以不用nm命令也可以推測出這三個對象的名字。
好了,現在需要在代碼中引用它們了,需要先聲明:
extern char binary_data_start;
extern int binary_data_size;
extern char binary_data_end;
完整的C代碼如下:
#include <stdio.h>extern char binary_data_start;extern int binary_data_size;extern char binary_data_end;int main(void){ printf("%s\n",&binary_data_start); printf("String length: %d\n",&binary_data_size); return 0;}
編譯cc data.o test.c -o test
執行結果:
$ ./testYou Are BeautifulMy life is brilliantMy life is brilliantMy love is pureI saw an angelOf that I'm sureShe smiled at me on the subwayShe was with another manBut I won't lose no sleep on that night'Cause I've got a planYou're beautiful, you're beautifulYou're beautiful, it's tureI saw your face in a crowded placeAnd I don't know what to do'Cause I'll never be with youYes, she caught my eyeAs I walked on byShe could see from my face that I was freaking highAnd I don't think that I'll see her againBut we shared a moment that will last util the end...String length: 577
需要注意的是Cygwin和Linux對於符號表的引用是不同的,Linux下nm匯出的符號表和C代碼中引用的變數名是一致的,Cygwin代碼中引用需要去掉“_”。
另外_binary_data_size這個變數比較特殊,對它取地址可以得到檔案的長度。至於它本身定義成什麼類型,似乎無關緊要。本人對此有個知識盲點,即只知道這樣使用是可以,但不知道該變數本身的具體意義。查看nm的man命令,對於A類型的解釋是“The symbol's value is absolute, and will not be changed by further linking.”,就是說這是一個絕對值,在將來連結時也不會改變。哪位高人看到此文,希望不吝指教。
2012/4/20 補充:
後來我買過一本書,講嵌入式整個項目的開發過程的,寫的很好。作者推薦的做法是做一個標頭檔,標頭檔裡有一個數組,數組內容便是要編譯到系統的檔案。
作者以此為例,實現了一個把任意檔案轉換為數組內容的C程式,進而講述了Office Tools的重要性。
最近我剛剛發現,原來Linux已經有了這樣貼心合用的工具了,xxd,一個以十六進位顯示檔案的工具。
比如:
xxd test.c 將以十六進位顯示test.c的內容,和UltraEdit的顯示類似,左邊是hex,右邊是ASCII。
xxd test.c -i test.h 將test.c檔案轉換為包含test.c檔案內容的數組,數組內容為test_c。
目前只發現這兩種做法,是做成.o,還是做成.h,這個看個人喜好和項目特點。