注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

singleboy的博客

愿工作和生活中的点点滴滴与你分享。。。感谢各位同仁,让我跟着大家一起进步。

 
 
 

日志

 
 

Linux应用程序开发(三)---移植kvm到arm linux  

2011-08-10 11:14:44|  分类: Linux应用开发 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

移植环境(红色粗字体字修改后内容,蓝色粗体字为特别注意内容)

1,主机环境:VMare下CentOS 5.5 ,1G内存。

2,集成开发环境:Elipse IDE

3,编译编译环境:arm-linux-gcc v4.4.3,arm-none-linux-gn?i-gcc v4.5.1。

4,开发板:mini2440,2M nor flash,128M nand flash。

5,u-boot版本:u-boot-2009.08

6,linux 版本:linux-2.6.32.2

7,参考文章:

Java虚拟机KVM在嵌入式Linux上的移植

尽管前面基于php的嵌入式web服务器已经能够运行java脚本文件,而且也能够执行xajax运行库。但是还是有些系统用不到php那样复杂的功能,而且php作为嵌入式的移植也比较复杂。java技术在嵌入式领域的应用已经流行起来。下面就有关java在嵌入式方面的移植和应用问题做些探讨。

移植kvm到arm-linux

【1】安装jdk

(1)检查系统中是否已经安装jkd,因为j2me_cldc/api目录下的源代码是用javac编译的,所以这里只需查询下javac的安装位置即可。

[root@localhost ~]# find / -name javac
/var/lib/alternatives/javac
/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0/bin/javac
/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/bin/javac
/usr/bin/javac
/etc/alternatives/javac
[root@localhost ~]#

查看下javac版本

[root@localhost ~]# java -version
java version "1.6.0_20"
OpenJDK Runtime Environment (IcedTea6 1.9.8) (rhel-1.22.1.9.8.el5_6-i386)
OpenJDK Client VM (build 19.0-b09, mixed mode)
[root@localhost ~]#

如果系统中没有找到javac,可安装下面方式安装。

方式1,j2me 1.4.2 版,这里不安装。

j2sdk-1_4_2_19-linux-i586-rpm.bin.gz :http://file.ajava.org/tool/java/j2sdk-1_4_2_19-linux-i586-rpm.bin.gz

方式2,jdk1.6.0_26版,可以是最新版,这里不安装。

下载完解压

 

(2)添加环境变量

打开/etc/profile文件,定位到27行,确认如下修改:

# Path manipulation
if [ "$EUID" = "0" ]; then
        pathmunge /sbin
        pathmunge /usr/sbin
        pathmunge /usr/local
        pathmunge /usr/local/bin
        pathmunge /usr/local/sbin
        pathmunge /usr/local/lib
        
pathmunge /usr/local/arm/4.4.3/bin
        pathmunge /usr/local/CodeSourcery/Sourcery_G++_Lite/bin
        pathmunge /usr/local/JLink_Linux_V422
fi

添加上面一行的目的是为了让编译器找到libiconv所在的路径。

... ...
#set to java jre
JAVA_HOME=/usr/local/jdk1.6.0_26
CLASSPATH=$JAVA_HOME/lib:/root/java
PATH=$JAVA_HOME/bin:$PATH
export JAVA_HOME PATH CLASSPATH

根据你自己的实际解压后安装位置作适当的修改,我的解压后安装位置为/usr/local文件夹下,其中PATH是命令的搜索路径,比如说用javac去编译一个.java文件,直接在命令行中用javac就可以,而不要代绝对路径了。CALSSPATH中的$JAVA_HOME/lib 为你的java代码运行的类库路径,/root/JAVA 为编译你的java代码生成的class所放置的路径。

文件修改并保持完以后,运行source etc/profile命令即可使修改操作立即生效。

(3)运行测试

在/root/java下新建一个文件名helloworld.java文件,并添加如下内容:

class HelloWorldApp
{
 p lic static void main(String args[])
 {
  System.out.println("welcome to java!");
 }
}

然后保存,并按下面操作编译后运行

[root@localhost java]# javac helloworld.java
[root@localhost java]# java HelloWorldApp
welcome to java!
[root@localhost java]#

【2】下载并解压kvm

j2me_cldc-1_1-fcs-src-winunix:http://www.oracle.com/technetwork/java/javame/javamobile/download/overview/index.html

在上面打开的页面左侧点击 REFERENCE IMPLEMENTATIONS->Connected Limited Device Configuration (CLDC) 1.1->download,如果您没有注册用户名,那么需要您注册一个并登录后才能下载。

下载后解压

[root@localhost linux-test]#  unzip /root/linux-test/j2me_cldc-1_1-fcs-src-winunix.zip -d ./

【3】j2me_cldc文档结构

j2me_cldc解压缩的目录有以下几个:
api-目录下包含了java类库的代码
bin—包含了编译过的class文件以及一些常用的与平台相关的可执行文件
build---与平台相关的makefile文件存放目录
docs ---与开发或移植相关说明文档
jam---应用管理代码
kvm---kvm代码
samples--实例代码
tools---随kvm代码的工具

说明:跟平台移植无关的代码都在kvm/vmcommon目录,平台有关的代码在kvm/vmextra目录下。

【4】java在kvm中的执行流程

在j2me中,程序流程从java源码(.java)开始的。Java源码被编译平台编译后生成与平台无关的Java字节码文件。该字节码文件经过一个外表校验器来验证字节码的合法性。当验证通过后,字节码会送到kvm中执行。其流程如下图所示。

Linux应用程序开发(三)---移植kvm到arm linux并与PHP5集成 - singleboy - singleboy的博客

 

【5】修改j2me_cldc/kvm/VmUnix/build/Makefile文件

(1)先改变其只读属性

[root@localhost linux-test]# cd j2me_cldc/kvm

[root@localhost kvm]# chmod u+w VmUnix/build/Makefile

(2)修改VmUnix/build下的Makefile,定位到文件开始处,修改如下:

export PLATFORM=linux
TOP=../../..
incl? $(TOP)/build/Makefile.inc

ifeq ($(PLATFORM), linux)
  export GCC=tr
endif

(3)定位到需要定位到95行,指定交叉编译器,修改如下:

ifeq ($(GCC), tr)
   CC = arm-linux-gcc
   CFLAGS =  -Wall $(CPPFLAGS) $(ROMFLAGS) $(OTHER_FLAGS)
   DEBUG_FLAG = -g
   OPTIMIZE_FLAG = -O2
   FP_OPTIMIZE_FLAG =
else
   CC = cc
   CFLAGS = -Xa $(CPPFLAGS) $(ROMFLAGS) $(OTHER_FLAGS)
   DEBUG_FLAG = -g -xsb
   OPTIMIZE_FLAG = -xO2
   FP_OPTIMIZE_FLAG =
endif
修改完后保存退出。

【6】修改j2me_cldc/kvm/VmUnix/src/runtime_md.c文件

(1)改变其只读属性

[root@localhost build]# cd ../src
[root@localhost src]# chmod u+w runtime_md.c

(2)把这个文件中void InitializeFloatingPoint()函数中的下面两句注释掉
[root@localhost src]# vim runtime_md.c

定位到171行,修改如下:

void InitializeFloatingPoint() {
#if defined(LINUX) && PROCESSOR_ARCHITECTURE_X86
    /* Set the precision FPU to do le precision */
   // fpu_control_t cw = (_FPU_DEFAULT & ~_FPU_EXTENDED) | _FPU_DO LE;
   // _FPU_SETCW(cw);

#endif
}
保存退出。

【7】修改j2me_cldc/tools/preverifier/build/linux目录下的Makefile

[root@localhost ~]# cd linux-test/j2me_cldc/tools/preverifier/build/linux
[root@localhost linux]# chmod u+w Makefile
[root@localhost linux]# vim Makefile

定位到39行附近,修改如下:

CC = gcc
LD = gcc

DEBUG_FLAG = 
LDFLAGS = -l iconv

ifeq ($(DEBUG), tr)
   DEBUG_FLAG = -g
endif

加入上面一行的目的是引入iconv库,不然在编译是会出现如下错误:

convert_md.o: In function `open_iconv':
convert_md.c:(.text+0x16): undefined reference to `libiconv_open'
convert_md.o: In function `native2utf8':
convert_md.c:(.text+0x239): undefined reference to `libiconv'
convert_md.c:(.text+0x276): undefined reference to `libiconv_close'
convert_md.o: In function `utf2native':
convert_md.c:(.text+0x365): undefined reference to `libiconv'
convert_md.c:(.text+0x3a2): undefined reference to `libiconv_close'
collect2: ld 返回 1
make: *** [preverify] 错误 1

【6】修改j2me_cldc/api目录下的Makefile,使其向下兼容1.4版本

需要先改变其只读属性

[root@localhost api]# chmod u+w Makefile

然后打开j2me_cldc/api/Makefile,定位到16行,修改如下:
DEBUGFLAG=":none"
endif

JAVAC     = javac -source 1.4

ifneq ($(findstring win, $(PLATFORM)),)

这样修改的目的是使其向下兼容1.4版本,不然在编译时出现如下错误:

src/java/lang/Object.java:132: cannot access java.lang.StringBuilder
class file for java.lang.StringBuilder not found
        return getClass().getName() + "@" + Integer.toHexString(hashCode());

网上说问题是出在几个String相加原因是JDK1.5太新,wtk2.2只能用JDK1.4.2的。JDK1.5使用StringBuilder类来代替JDK1.4中的StringB?r类。

【7】进入j2me_cldc/build/linux目录编译

[root@localhost j2me_cldc]# cd build/linux
[root@localhost linux]# make
... ...

src/java/lang/Object.java:132: cannot access java.lang.StringBuilder
class file for java.lang.StringBuilder not found
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
                                          ^
1 error
94 warnings
make[1]: *** [compilefiles] Error 1
make[1]: Leaving directory `/root/linux-test/j2me_cldc/api'
make: *** [all] 错误 1

 

【8】在/usr/lib目录下建立libiconv库文件

因为gcc默认的库文件路径为/usr/lib,需要将/usr/local/lib目录下的libiconv.so,libiconv.so.2,libiconv.so.2.5.0三个文件复制到此目录下或者在此目录先建立到/usr/local/lib/libiconv.so的软连接。不然会出现下面错误:

... ...
../tools/preverifier/build/linux/preverify -d classes tmpclasses
../tools/preverifier/build/linux/preverify: error while loading shared libraries: libiconv.so.2: cannot open shared object file: No s h file or directory
make[1]: *** [compilefiles] Error 1
make[1]: Leaving directory `/root/linux-test/j2me_cldc/api'
make: *** [all] 错误 1

【9】修改j2me_cldc/tools/jcc/src/util目录下ClassReader.java

需要先改变其只读属性

[root@localhost api]# chmod u+w Makefile

然后打开其目录下的ClassReader.java,定位到85行修改如下:

p lic int
    readZip (String fileName, Vector done) throws IOException
    {
    int i = 0;

        ZipFile zf = new ZipFile(fileName);
        Enumeration myenum = zf.entries();
        while (myenum.hasMoreElements()) {
            ZipEntry ent = (ZipEntry)myenum.nextElement();
        String name = ent.getName();
        if (!ent.isDirectory() &&
不然会出现如下错误:

... ...

src/util/ClassReader.java:85: as of release 5, 'enum' is a keyword, and may not be used as an identifier
(use -source 1.4 or lower to use 'enum' as an identifier)
        Enumeration enum = zf.entries();
                    ^
src/util/ClassReader.java:86: as of release 5, 'enum' is a keyword, and may not be used as an identifier
(use -source 1.4 or lower to use 'enum' as an identifier)
        while (enum.hasMoreElements()) {
               ^
src/util/ClassReader.java:87: as of release 5, 'enum' is a keyword, and may not be used as an identifier
(use -source 1.4 or lower to use 'enum' as an identifier)
            ZipEntry ent = (ZipEntry)enum.nextElement();
... ...

【10】参考Memo for Explanting KVM to ARM-Linux,针对如下错误需要安装低版本的编译器。

... ...

../../../kvm/VmCommon/src/verifierUtil.c: In function 'verifyClass':
../../../kvm/VmCommon/src/verifierUtil.c:547: error: invalid storage class for function 'Vfy_verifyMethod'
../../../kvm/VmCommon/src/verifierUtil.c:571: warning: implicit declaration of function 'Vfy_verifyMethod'
../../../kvm/VmCommon/src/verifierUtil.c: At top level:
../../../kvm/VmCommon/src/verifierUtil.c:1595: error: static declaration of 'Vfy_verifyMethod' follows non-static declaration
../../../kvm/VmCommon/src/verifierUtil.c:571: note: previous implicit declaration of 'Vfy_verifyMethod' was here
../../../kvm/VmCommon/src/verifierUtil.c: In function 'Vfy_verifyMethod':
../../../kvm/VmCommon/src/verifierUtil.c:1598: error: invalid storage class for function 'Vfy_checkNewInstr tions'
../../../kvm/VmCommon/src/verifierUtil.c:1633: warning: implicit declaration of function 'Vfy_checkNewInstr tions'
../../../kvm/VmCommon/src/verifierUtil.c: At top level:
../../../kvm/VmCommon/src/verifierUtil.c:1671: error: conflicting types for 'Vfy_checkNewInstr tions'
../../../kvm/VmCommon/src/verifierUtil.c:1633: note: previous implicit declaration of 'Vfy_checkNewInstr tions' was here
make[1]: *** [obj/verifierUtil.o] Error 1
make[1]: Leaving directory `/root/linux-test/j2me_cldc/kvm/VmUnix/build'
make: *** [all] 错误 1
[root@localhost linux]#

(1)下载arm-linux-gcc-3.3.2.tar.bz2 : http://code.google.com/p/mini4020/downloads/detail?name=3.3.2.tar.bz2&can=2&q=label%3AMini4020

(2)修改第【4】中的Makefile,修改如下:

ifeq ($(GCC), tr)
   CC = /usr/local/arm/3.3.2/arm-linux/bin/gcc 
   CFLAGS =  -Wall $(CPPFLAGS) $(ROMFLAGS) $(OTHER_FLAGS)
   DEBUG_FLAG = -g
   OPTIMIZE_FLAG = -O2
   FP_OPTIMIZE_FLAG =

【11】进入j2me_cldc/kvm/VmUnix/build编译

[root@localhost src]# cd ../build
[root@localhost build]# make
... ...
Linking ... kvm
make[1]: Leaving directory `/root/linux-test/j2me_cldc/kvm/VmUnix/build'
<<<Finished Recursively making ../../kvm/VmUnix/build all.
[root@localhost linux]#

 OK,编译成功。

【12】查看下面两个重要文件

[root@localhost ~]# file /root/linux-test/j2me_cldc/kvm/VmUnix/build/kvm
/root/linux-test/j2me_cldc/kvm/VmUnix/build/kvm: ELF 32-bit LSB executable, ARM, version 1 (ARM), for GNU/Linux 2.0.0, dynamically linked (uses shared libs), for GNU/Linux 2.0.0, not stripped
[root@localhost ~]# file /root/linux-test/j2me_cldc/tools/preverifier/build/linux/preverify
/root/linux-test/j2me_cldc/tools/preverifier/build/linux/preverify: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped
[root@localhost ~]#
可以看到,生成的kvm可执行文件是用来在目标板上运行java程序的,生成的preverify是用来预校验用。

【13】kvm验证测试

(1)进入到/root/java目录下,在linux主机上编译上面【1】jdk的测试文件helloworld.java

[root@localhost ~]# cd /root/java
[root@localhost java]# javac helloworld.java
[root@localhost java]

(2)将编译生成的j2me_cldc/tools/preverifier/build/linux/preverify文件复制到linux主机/bin目录下
[root@localhost ~]# cp linux-test/j2me_cldc/tools/preverifier/build/linux/preverify  /bin

将linux-test/j2me_cldc/tools/jcc目录下classes.zip 和classesUnix.zip 分别解压到/root/java目录的classes 和classesUnix目录下

[root@localhost ~]# cd linux-test/j2me_cldc/tools/jcc
[root@localhost jcc]# unzip classes.zip -d /root/java/classes/

[root@localhost jcc]# unzip classesUnix.zip -d /root/java/classesUnix/

用下面命令进行预校验

preverify -classpath classesdir myclass

[root@localhost ~]# cd java
[root@localhost java]# preverify -classpath classes/classes classes/classesUnix HelloWorldApp
段错误
[root@localhost java]#
参考http://www.cnblogs.com/oomusou/archive/2008/06/14/j2me_cpld_preverify.html,知是使用的语系问题。Solution如下:

<1>显示目前使用的语系

[root@localhost java]# echo $LANG
zh_CN.UTF-8

不管目前使用的中文还是英文,只要是UTF-8就会出现上面错误。

<2>暂时修改成en_US.ISO8859-1语系
[root@localhost java]# export LANG=en_US.ISO8859-1
[root@localhost java]# echo $LANG
en_US.ISO8859-1

<3>再次执行preverify

[root@localhost java]# preverify -classpath classes/classes classes/classesUnix HelloWorldApp
[root@localhost java]#

执行成功。

(3)在目标板上运行测试

先将/root/linux-test/j2me_cldc/kvm/VmUnix/build目录下的kvm复制到开发板根目录即nfsboot/rootfs/usr/local/sbin目录下

[root@localhost ~]# cp linux-test/j2me_cldc/kvm/VmUnix/build/kvm /nfsboot/rootfs/usr/local/sbin
[root@localhost ~]#

然后将校验后生成的Java/output目录下HelloWorldApp.class复制到开发板的/root目录下

[root@localhost ~]# cp /root/java/output/HelloWorldApp.class /nfsboot/rootfs/root/
[root@localhost ~]#

(4)在开发板串口终端运行

在执行之前先确认开发板/etc/profile文件中的PATH系统变量有如下路径:

PS1='[\u@\h \W]\$'
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$PATH
HOSTNAME='/bin/hostname'
export USER LOGNAME PS1 PATH
然后再串口终端中执行

[root@mini2440 /]#kvm
-/bin/sh: kvm: not found
[root@mini2440 /]#

问题分析:kvm是用arm-linux-gcc-3.3.2编译的,而内核是用arm-linux-gcc-4.4.3编译的。在【12】中用file指令查看结果是" for GNU/Linux 2.0.0 ”,显然出现了兼容问题。

由此,我突然想到一个问题,之前用arm-linux-gcc-4.4.3编译应用程序时,通过file查看,可以看到如"for GNU/Linux 2.6.32" 之类的信息,而编译kvm则是出现的" for GNU/Linux 2.0.0 ”这样的信息,arm-linux-gcc是如何知道内核版本信息的呢?

  评论这张
 
阅读(2818)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017