首先列举一些问题:
(1)X86上运行的程序能不能在51单片机上运行,为何linux定时器,有没有可能,假如可以,应当做什么工作才可以实现。
(2)相同CPU平台,DOS的程序为何可以在windows下运行,能不能在Linux下运行,为何,作哪些工作可能实现。
为何可以移植程序,为何要移植程序?
程序可以移植首先要谢谢开发出中级语言的大牛们,记住,无论多么漂亮的代码经过编译之后都要弄成CPU可以辨识的机器语言,而几乎一千种CPU说着一千种语言。为保证你们有共同语言,规定一种中级语言――高级语言。每一个CPU派出自己的翻译――编译器。这个翻译精通两国语言,中级语言和自己的语言。(由此早已可以看出编译工具在程序移植中的重要性)。只要程序没有硬件上的约束,可以说这些沟通是无极限的,甚至于不同操作系统平台。(操作系统也是程序,也可以移植喽)举例:在x86的windows下用VC(或TC,BC)编一个c程序实现i=i+1,丝毫不改就可以用51的C编译器重新编译并在51单片机上运行。一次大型的移植就结束了。
可以移植已有的程序还要谢谢开放源代码的弟兄,没有这种C文件和H文件让你重新编译一下,如何在你的CPU上跑?似乎不止这种,旁边都会看到开源组织的牛人专为程序可移植性所作的专门的工作。
这么为何要移植程序?
问这问题犹如问地上有个皮夹为何要捡一样,答案不言而喻。现成的东西为何不要。其实,移植程序可没有捡皮夹这么简单,尤其是第一次,旁边会说一些移植之前应当考虑的问题。(如同现今地上有个皮夹也千万别起来就揣自己兜里,说不定就是套)。另一方面,你给我你写好的程序让我拿去用,我还要考虑一下,似乎里头问题多的还不如自己写一个。这儿所说的可移植的程序应当是维护比较好,比较成熟的源代码(像前面的所说的UCD-SNMP),目前的开放源代码运动决不仅仅是把自己的程序公开就行了,而是有了一套成熟完整的版本控制,BUG报告和PATCH递交流程。这样的代码才有更大的使用价值。
哪些时侯可以考虑移植程序?
在基于嵌入式操作系统进行开发时,具有一定规模的程序都可以到网上查一查都没有成熟的源代码可用。上面早已说到,程序的移植最终只针对CPU,虽然和操作系统没哪些关系,但另一方面,由于代码中可能会使用一些库函数,这种库会包括C语言标准库和操作系统提供的API(应用程序插口)库。
假定源代码中只包括C标准库,这么该程序就可以跨操作系统去移植。
比如helloworld程序中使用了printf,由于该函数是C标准函数,所以在X86上使用TC(BC或VC)可以直接编译运行,在ARM+uClinux平台下也一样,但若果程序中调用了vfork函数,这么只有linux一脉相承的操作系统支持这些特殊服务了,在window或dos操作系统下难以直接编译该程序了。只能找该操作系统支持的类似的功能来实现。再进一步,硬件上的生理缺陷也会为移植带来麻烦,S3C4510B不支持MMU,在其上运行的uClinux也不提供和MMU有关的服务(虽然uClinux本身可以支持MMU),于是在移植前相关的函数(例如FORK)都要被取代掉(使用VFORK)。好在uClinux和linux提供的应用插口大部份还是相同的。所以这样的工作还可以承受。
由上可知,倘若是在各类嵌入式linux(不仅uClinux以外,还有好几种)平台上开发,这么针对该平台以及linux平台上的源代码都可以使用,而且要谨记她们之间的差别。在系统中须要实现网路监控,就可以使用snmp合同,该合同和httplinux课程,ftp一样属于应用层的成熟合同,专用于网路管理。早已有一些针对该合同成熟的代码,最有名的是ucd-snmp,不光软件本身功能强悍,可移植性也比较好,在linuxwindows代码移植linux,unix等平台上都可以移植,于是决定将它移植到ARM+uClinux平台上(别看如今说的那么轻松,当时接这活时都有点发冷)。
简单总结一下,移植应用程序的前提是有源代码,移植的关键工具是编译器,源代码中和硬件平台相关的东西越少越好(这儿主要指使用了汇编,或做了针对自己平台的事,例如将表针指向特定地址之后操作),另一方面,假如该程序是基于某个操作系统(借助了操作系统提供的特殊服务,即API),要看自己的操作系统是否提供了相关服务。
下边简单列举一些移植时须要考虑的问题:
(1)自己的操作系统的特性以及在当前版本下支持的特点。
比如:uClinux不支持MMU,同样就难以支持相应的特点。
(2)硬件资源。
由于嵌入式系统资源比较紧张,硬件资源考虑必需要周全:
(1)软件储存空间的大小
这通常要等用目标编译器重新编译完之后可能就会晓得,所以只能大约计算,但千万不要看这个程序在linux下只有几十k,就觉得程序很小,这是由于linux下程序多时使用动态库windows代码移植linux,而在嵌入式系统中,很有可能是把用到的库都链接在一起,所以程序的规格会大大降低。
(2)程序运行空间。
(3)硬件以及相应的驱动是否完备
以上工作应当尽量做,但有时政先难以掌握,只能听天由命了(有没有弄错!!)
可能有人早已要晕菜了,激奋一下你们,假若找到了好的源代码(可移植性好),这么剩下的如要工作就是玩转你的编译器,只要你能顺利的把源代码用你的编译器重新编译一下。90%的工作就完成了(不是吗)
上回早已介绍了一些编译器方面的东西,下边针对ARM编译器的具体参数来讲解一些编译器主要参数的设置。
如果我早已有了hello.c,在x86的linux平台下编译链接一下。
gcc–chello.c形成.o
gcc–ohellohello.o形成可执行文件,上回说过,主机编译器参数都有环境变量保存,所以看上去很简单。这儿我故意分两个步鄹。
下边看一下用我的编译器编这个程序(肾脏不好的先服药)。
arm-elf-gcc-Iroot/uClibc/include-msoft-float-mcpu=arm7tdmi-fomit-frame-pointer-fsigned-char-mcpu=arm7tdmi-Os–Wall-DEMBED-D_uClinux_-chello.c
这只是编译,将参数逐一讲解。
Arm-elf-gcc是gnu的arm编译工具
1)Include地址:参数:-I值:root/uClibc/include(这是在主机上我的uClinux的头文件路径)用法:-Iroot/uClibc/include
-I参数保证旁边的头文件路径在搜索系统头文件路径前被搜索因而有可能取代系统的头文件,倘若有多个这样的参数,则搜索的次序是从左到右,之后是系统的头文件。
2)-m是针对CPU的选项。
-mcpu=arm7tdmi说明CPU类型
-msoft-float形成包含浮点库的输出
-fsigned-char让char类型有符号
-fomit-frame-pointer对所有不须要帧表针的函数都不将其保存在寄存器中。
3)-Os–Wall
-Wall:所有警告都显示
Os:优化规格,该选项使能所有所有不降低规格的O2优化,但是进一步依照规格优化
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–ohello/root/uClibc/lib/crt0.o/usr/local/gnu/lib/gcc-lib/arm-elf/3.0.1/crtbegin.ohello.o
/usr/local/gnu/lib/gcc-lib/arm-elf/3.0.1/crtend.o-lc-lgcc–lc
其中
1)链接工具:arm-elf-ld
2)-L指明须要链接的库的路径,用法和-I一样,自己的库的路径也可以在这儿加入。
-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.oOBJECTS.o
/usr/local/gnu/lib/gcc-lib/arm-elf/3.0.1/crtend.o
这是须要链接在一起的.o文件
5)-lc-lgcc–lc-l前面紧随的是须要链接的库的名子,通常库的名子是libxxx.a,使用时为-lxxx即可,不加lib和.a。还要注意位置,自己的库文件应当加在他的库后面。
编译通过后,移植即使完成了,对于比较小的源代码都可以这样,即先剖析他的编译选项(用到了这些头文件,库文件等),之后用自己的编译器对照相应参数重新编译一下就行了。
非常推荐
文章评论