Android跨平台移植经验之谈

来源:互联网 发布:apache ant 1.9.4.jar 编辑:程序博客网 时间:2024/05/30 04:12

元旦休息,闲来无事,又暂无睡意,写点东西捣鼓捣鼓吧!学的东西多了,就怕忘记以前的知识,所以还是记下来比较好。正所谓,好记性不如烂笔头!目前做的一个项目是移植android4.2,所以刚好可以把移植的经验跟大家分享分享,共同进步。尽管界面还没启动起来,但相信到那一天应该不远了。

    标题自称为跨平台移植,那么究竟怎样跨平台了呢?出于公司利益的考虑,这里只透露一点点吧!我们现在所用的cpu(面向嵌入式)是公司自主研发的,市场上暂时还没有,其指令架构不同于市场上任何的cpu架构,例如arm、mips等。由于google谷歌官方不支持我们的cpu架构,而我们又想跑android系统,所以就需要把它移植到我们的平台上。架构不同,必然要使用不同的编译器,公司也自己开发了一个编译器,本人觉得开发编译器的这位老大好牛x的说,他还是美国斯坦福大学现任校长的得意门生。算了,题外话还是不多说了!我们继续!

    android使用的kernel也是linux,所以在移植android之前,必须先把linux kernel移植好,这部份工作由kernel团队的成员完成,我很少参与,这里大概说个情况吧。首先就是要选择kernel的版本,在google官方,JellyBean(android 4.x版本的代号)搭配的kernel是3.0.x版本的,所以android4.2至少应该选择一个3.0或以上的kernel。我们选择的是3.4,为何要选择如此高版本的kernel?因为android与kernel的版本更新太快了,我们不想google官方出一个新版本,我们就要重新移植一次kernel,所以就选择版本比较高的kernel,用来兼容未来的android版本。版本定下来后,还要考虑用哪里的linux源代码,因为目前支持android的kernel有多种多样,这些都是被各大芯片厂商或者手机厂商修改过的,所以要选择最合适自己架构的kernel。kernel源码下载下来后,把里面架构相关的代码修改成自己平台的代码,其实主要是汇编级的代码。修改完毕后,做一个根文件系统,让kernel能启动到shell。最后就是开发各种驱动,不断地支持android的移植工作。

    对于android这边的工作,首先下载4.2的源码,用git管理,源码里面有多个分支,我们一般不会跟着master分支走,因为master分支每天都有更新,所以很难维护。一般checkout到某个分支上,例如android-4.2_r1。android4.2里面支持3种架构:arm、mips、x86,它们的代码都混杂在一起,编译系统是如何区分它们的?是通过android自己的Makefile区分的,在一些目录下面的Android.mk文件中,可以看到里面有语句判断是哪个架构的;还有,在一些头文件(xx.h)里面也能看到#ifdef或者#ifndef等,这些架构信息都是在编译时通过读取环境变量得到的,编译系统会根据不同的环境变量来编译需要的代码。所以,我们需要修改android的编译脚本,把自己的架构添加进去,具体修改的地方有build/和device/目录下的编译脚本等。修改后的效果是,在编译前,执行source build/envsetup.sh,然后lunch,能看到自己的平台,这是最基本的一步。跟着,我们要了解有哪些模块涉及到架构相关的代码。经过一番摸索,终于知道了有哪些模块跟架构相关,这里给各位看官列出来:

1、bionic:仿生库,其实这个不用说大家也知道,bionic提供libc、libstdc++等函数库以及一些系统调用,里面很多头文件都由kernel导过来,所以必然有架构相关代码。要想android能够跑起来,bionic一定要移植成功。其实bionic的移植工作非常困难,公司是由一个有多年工具链开发经验的同事做的。

2、llvm:一个编译器的后端,前端是clang。涉及编译器相关知识,不太了解,clang是apple公司开发的一款编译器,貌似性能要比gcc好。

3、v8:JavaScript引擎,在浏览器中用到,分为解析执行和编译执行,解析执行时会产生汇编代码,所以要修改汇编代码生成器。

4、libbcc:RenderScript需要依赖于libbcc和llvm。

5、RenderScript:由于2和4的原因,所以RenderScript也涉及架构相关的代码。RenderScript是一个3D的画图库,功能类似于openGL,虽然没有openGL强大,但是其开发流程比较简单,而且拥有高性能的3D渲染效果。主要用在动态壁纸的实现等。

6、dalvik:android的java虚拟机,这家伙也是一大块啊,涉及很多编译原理。

可能还有些跟架构相关的模块没列出来,本人目前只记得这些了,欢迎补充!android的启动不需要依赖于上面所有的模块,所以我们的计划是先把必须的模块移植好,先让系统起来。在上面的模块中,我们只需要移植好bionic和dalvik就能把系统运行起来。

    必要的架构相关的模块移植好后,下一步要做的是编译一个android的最小系统,并把镜像做出来。编译的话,只能编到哪里出错就解决哪里的问题了。如果人手足够的话,可以把最小系统的模块分工好,让其他人员一个模块一个模块地扫过去,把不能编译的都修复好。修复的内容主要是,缺少架构的定义,缺少头文件,缺少某些变量和宏的定义等。这些一般都是修改一些xx.mk文件添加架构支持,或者在bionic中导入所需要的头文件,定义变量、宏等。这样分工,能加快进展速度。

    最小系统编译完成后,就要做image,烧到SD卡或者nanflash中启动,什么样的根文件系统格式配什么样的镜像,大家要弄清楚。

    启动的第一步当然是启动init进程,接着是把必要的服务运行起来,直到shell能用。这时,就能调试servicemanager和surfaceflinger等服务了,幸运的话,一般起来都不会有太大的问题。surfaceflinger可以用bootanimation验证它的功能,如果看到android的文字logo,就证明surfaceflinger能工作。如果shell都不能启动的话,可以跑一下在android源码中system/extra/tests下面的测试程序,主要是测试kernel是否为启动android作了足够的准备。在jni层的服务都能启动后,接下来就是调试zygote了,zygote里面开始进入java世界,调试zygote是最难的一关,总会遇到各种segmentfault,很恐怖的说。。。。。

    目前的进展只到这里,等到系统的界面出来后再跟大家接着分享吧!!

原创粉丝点击