新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > ARM/uClinux應(yīng)用程序的開(kāi)發(fā)

ARM/uClinux應(yīng)用程序的開(kāi)發(fā)

作者: 時(shí)間:2012-11-16 來(lái)源:網(wǎng)絡(luò) 收藏

  可以移植已有的程序還要感謝開(kāi)放源代碼的弟兄,沒(méi)有這些C文件和H文件讓你重新編譯一下,怎么在你的CPU上跑?其實(shí)不止這些,后面還會(huì)看見(jiàn)開(kāi)源組織的牛人專為程序可移植性所作的專門的工作。

  那么為什么要移植程序?

  問(wèn)這問(wèn)題就像問(wèn)地上有個(gè)錢包為什么要撿一樣,答案不言而喻。現(xiàn)成的東西為什么不要。當(dāng)然,移植程序可沒(méi)有撿錢包那么簡(jiǎn)單,尤其是第一次,后面會(huì)說(shuō)一些移植之前應(yīng)該考慮的問(wèn)題。(就像現(xiàn)在地上有個(gè)錢包也千萬(wàn)別上去就揣自己兜里,說(shuō)不定就是套)。另一方面,你給我你寫好的程序讓我拿去用,我還要考慮一下,或許里頭問(wèn)題多的還不如自己寫一個(gè)。我這里所說(shuō)的可移植的程序應(yīng)該是維護(hù)比較好,比較成熟的源代碼(像我后面的所說(shuō)的UCD-SNMP),目前的開(kāi)放源代碼運(yùn)動(dòng)決不僅僅是把自己的程序公開(kāi)就行了,而是有了一套成熟完整的版本控制,BUG報(bào)告和PATCH提交流程。

  這樣的代碼才有更大的使用價(jià)值。

  什么時(shí)候可以考慮移植程序? 在基于嵌入式操作系統(tǒng)進(jìn)行開(kāi)發(fā)時(shí),具有一定規(guī)模的程序都可以到網(wǎng)上查一查都沒(méi)有成熟的源代碼可用。前面已經(jīng)說(shuō)到,程序的移植最終只針對(duì)CPU,其實(shí)和操作系統(tǒng)沒(méi)什么關(guān)系,但另一方面,因?yàn)榇a中可能會(huì)使用一些庫(kù)函數(shù),這些庫(kù)會(huì)包括C語(yǔ)言標(biāo)準(zhǔn)庫(kù)和操作系統(tǒng)提供的API(接口)庫(kù)。假設(shè)源代碼中只包括C標(biāo)準(zhǔn)庫(kù),那么該程序就可以跨操作系統(tǒng)去移植。例如hello world程序中使用了printf,因?yàn)樵摵瘮?shù)是C標(biāo)準(zhǔn)函數(shù),所以在X86上使用TC(BC或VC)可以直接編譯運(yùn)行,在平臺(tái)下也一樣,但如果程序中調(diào)用了vfork函數(shù),那么只有l(wèi)inux一脈相承的操作系統(tǒng)支持這種特殊服務(wù)了,在window或dos操作系統(tǒng)下無(wú)法直接編譯該程序了。只能找該操作系統(tǒng)支持的類似的功能來(lái)實(shí)現(xiàn)。再進(jìn)一步,硬件上的生理缺陷也會(huì)為移植帶來(lái)麻煩,S3C4510B不支持MMU,在其上運(yùn)行的也不提供和MMU有關(guān)的服務(wù)(其實(shí)本身可以支持MMU),于是在移植前相關(guān)的函數(shù)(比如FORK)都要被替代掉(使用VFORK)。好在uClinux和linux提供的應(yīng)用接口大部分還是相同的。所以這樣的工作還可以承受。

  由上可知,如果是在各種嵌入式linux(除了uClinux以外,還有好幾種)平臺(tái)上開(kāi)發(fā),那么針對(duì)該平臺(tái)以及l(fā)inux平臺(tái)上的源代碼都可以使用,但是要牢記他們之間的差異。在我的系統(tǒng)中需要實(shí)現(xiàn)網(wǎng)絡(luò)監(jiān)控,所以想使用snmp協(xié)議,該協(xié)議和http,ftp一樣屬于應(yīng)用層的成熟協(xié)議,專用于網(wǎng)絡(luò)管理。目前已經(jīng)有一些針對(duì)該協(xié)議成熟的代碼,最有名的是ucd-snmp,不光軟件本身功能強(qiáng)大,可移植性也比較好,在linux,unix等平臺(tái)上都可以移植,于是決定將它移植到+uClinux平臺(tái)上(別看現(xiàn)在說(shuō)的這么輕松,當(dāng)時(shí)接這活時(shí)都有點(diǎn)哆嗦)。
簡(jiǎn)單總結(jié)一下,移植的前提是有源代碼,移植的關(guān)鍵工具是編譯器,源代碼中和硬件平臺(tái)相關(guān)的東西越少越好(這里主要指使用了匯編,或做了針對(duì)自己平臺(tái)的事,比如將指針指向特定地址然后操作),另一方面,如果該程序是基于某個(gè)操作系統(tǒng)(利用了操作系統(tǒng)提供的特殊服務(wù),即API),要看自己的操作系統(tǒng)是否提供了相關(guān)服務(wù)。

  下面簡(jiǎn)單列出一些我認(rèn)為移植時(shí)需要考慮的問(wèn)題:

  (1) 自己的操作系統(tǒng)的特點(diǎn)以及在當(dāng)前版本下支持的特性。
例如:uClinux不支持MMU,同樣就無(wú)法支持相應(yīng)的特性。

  (2) 硬件資源。

  因?yàn)榍度胧较到y(tǒng)資源比較緊張,硬件資源考慮必須要周全:

  (1) 軟件存儲(chǔ)空間的大小

  這一般要等用目標(biāo)編譯器重新編譯完以后可能才會(huì)知道,所以只能大概估算,但千萬(wàn)不要看這個(gè)程序在linux下只有幾十k,就認(rèn)為程序很小,這是因?yàn)閘inux下程序多時(shí)使用動(dòng)態(tài)庫(kù),而在嵌入式系統(tǒng)中,很有可能是把用到的庫(kù)都鏈接在一起,所以程序的尺寸會(huì)大大增加。

  (2) 程序運(yùn)行空間。

  (3) 硬件以及相應(yīng)的驅(qū)動(dòng)是否完備

  以上工作應(yīng)該盡量做,但有時(shí)事先無(wú)法把握,只能聽(tīng)天由命了(有沒(méi)有搞錯(cuò)!?。?P>  可能有人已經(jīng)要暈菜了,振奮一下大家,如果找到了好的源代碼(可移植性好),那么剩下的如要工作就是玩轉(zhuǎn)你的編譯器,只要你能順利的把源代碼用你的編譯器重新編譯一下。90%的工作就完成了(不是嗎)

上回已經(jīng)介紹了一些編譯器方面的東西,下面針對(duì)我的編譯器的具體參數(shù)來(lái)講解一些編譯器主要參數(shù)的設(shè)置。
加入我已經(jīng)有了hello.c,在x86的linux平臺(tái)下編譯鏈接一下。

  gcc –c hello.c 產(chǎn)生.o

  gcc –o hello hello.o 產(chǎn)生可執(zhí)行文件,上回說(shuō)過(guò),主機(jī)編譯器參數(shù)都有環(huán)境變量保存,所以看起來(lái)很簡(jiǎn)單。這里我故意分兩個(gè)步鄹。
下面看一下用我的編譯器編這個(gè)程序(心臟不好的先吃藥)。

  arm-elf-gcc -Iroot/uClibc/include -msoft-float -mcpu=arm7tdmi -fomit-frame-pointer -fsigned-char -mcpu=arm7tdmi -Os –Wall -DEMBED -D_uclinux_ -c hello.c

  這只是編譯,將參數(shù)逐一講解。

  Arm-elf-gcc 是gnu的arm編譯工具

  1)Include地址:參數(shù):-I 值:root/uClibc/include(這是在主機(jī)上我的uClinux的頭文件路徑) 用法:-I root/uClibc/include-I參數(shù)保證后面的頭文件路徑在搜索系統(tǒng)頭文件路徑前被搜索從而有可能替代系統(tǒng)的頭文件,如果有多個(gè)這樣的參數(shù),則搜索的順序是從左到右,然后是系統(tǒng)的頭文件。

  2)-m 是針對(duì)CPU的選項(xiàng)。

  -mcpu=arm7tdmi 說(shuō)明CPU類型
  -msoft-float 產(chǎn)生包含浮點(diǎn)庫(kù)的輸出
  -fsigned-char 讓char類型有符號(hào)
  -fomit-frame-pointer 對(duì)所有不需要幀指針的函數(shù)都不將其保存在寄存器中。
  3) -Os –Wall

  -Wall:所有警告都顯示

  Os:優(yōu)化尺寸,該選項(xiàng)使能所有所有不增加尺寸的O2優(yōu)化,并且進(jìn)一步根據(jù)尺寸優(yōu)化

  4) = -DEMBED -D_uclinux_

  -D: 將-Dmacro 后的macro定義為字符串1。

  以下是鏈接:
  arm-elf-ld -L/root/uClibc/lib -L/usr/local/gnu/arm-elf/lib -L/usr/local/gnu/lib/gcc-lib/arm-elf/3.0.1 -elf2flt –o hello /root/uClibc/lib/crt0.o /usr/local/gnu/lib/gcc-lib/arm-elf/3.0.1/crtbegin.o hello.o
/usr/local/gnu/lib/gcc-lib/arm-elf/3.0.1/crtend.o -lc -lgcc –lc

  其中
  1) 鏈接工具: arm-elf-ld

  2) -L指明需要鏈接的庫(kù)的路徑,用法和-I一樣,自己的庫(kù)的路徑也可以在這里加入。 -L/root/uClibc/lib -L/usr/local/gnu/arm-elf/lib -L/usr/local/gnu/lib/gcc-lib/arm-elf/3.0.1

  3) –o 后面緊跟生成的最終的文件名

  4)/root/uClibc/lib/crt0.o /usr/local/gnu/lib/gcc-lib/arm-elf/3.0.1/crtbegin.o OBJECTS.o
/usr/local/gnu/lib/gcc-lib/arm-elf/3.0.1/crtend.o

這是需要鏈接在一起的.o文件

  5) -lc -lgcc –lc -l 后面緊跟的是需要鏈接的庫(kù)的名字,一般庫(kù)的名字是libxxx.a,使用時(shí)為-lxxx即可,不加lib和.a。還要注意位置,自己的庫(kù)文件應(yīng)該加在他的庫(kù)前面。

  編譯通過(guò)后,移植就算完成了,對(duì)于比較小的源代碼都可以這樣,即先分析他的編譯選項(xiàng)(用到了那些頭文件,庫(kù)文件等),然后用自己的編譯器對(duì)照相應(yīng)參數(shù)重新編譯一下就行了。


上一頁(yè) 1 2 下一頁(yè)

關(guān)鍵詞: ARM uClinux 應(yīng)用程序

評(píng)論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉