设为首页 收藏本站
查看: 1806|回复: 0

[经验分享] Linux应用程序开发(三)---移植kvm到arm linux

[复制链接]

尚未签到

发表于 2015-10-10 13:30:10 | 显示全部楼层 |阅读模式
Linux应用程序开发(三)---移植kvm到arm linux  
  移植环境(红色粗字体字修改后内容,蓝色粗体字为特别注意内容)
  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的安装位置即可。
  [iyunv@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
[iyunv@localhost ~]#
  查看下javac版本
  [iyunv@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)
[iyunv@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!");
}
}
  然后保存,并按下面操作编译后运行
  [iyunv@localhost java]# javac helloworld.java
[iyunv@localhost java]# java HelloWorldApp
welcome to java!
[iyunv@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,如果您没有注册用户名,那么需要您注册一个并登录后才能下载。
  下载后解压
  [iyunv@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中执行。其流程如下图所示。
DSC0000.png

  
  【5】修改j2me_cldc/kvm/VmUnix/build/Makefile文件
  (1)先改变其只读属性
  [iyunv@localhost linux-test]# cd j2me_cldc/kvm
  [iyunv@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)改变其只读属性
  [iyunv@localhost build]# cd ../src
[iyunv@localhost src]# chmod u+w runtime_md.c
  (2)把这个文件中void InitializeFloatingPoint()函数中的下面两句注释掉
[iyunv@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
  [iyunv@localhost ~]# cd linux-test/j2me_cldc/tools/preverifier/build/linux
[iyunv@localhost linux]# chmod u+w Makefile
[iyunv@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版本
  需要先改变其只读属性
  [iyunv@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目录编译
  [iyunv@localhost j2me_cldc]# cd build/linux
[iyunv@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
  需要先改变其只读属性
  [iyunv@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
[iyunv@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编译
  [iyunv@localhost src]# cd ../build
[iyunv@localhost build]# make
... ...
Linking ... kvm
make[1]: Leaving directory `/root/linux-test/j2me_cldc/kvm/VmUnix/build'
<<<Finished Recursively making ../../kvm/VmUnix/build all.
[iyunv@localhost linux]#
  OK,编译成功。
  【12】查看下面两个重要文件
  [iyunv@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
[iyunv@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
[iyunv@localhost ~]#
可以看到,生成的kvm可执行文件是用来在目标板上运行java程序的,生成的preverify是用来预校验用。
  【13】kvm验证测试
  (1)进入到/root/java目录下,在linux主机上编译上面【1】jdk的测试文件helloworld.java
  [iyunv@localhost ~]# cd /root/java
[iyunv@localhost java]# javac helloworld.java
[iyunv@localhost java]
  (2)将编译生成的j2me_cldc/tools/preverifier/build/linux/preverify文件复制到linux主机/bin目录下
[iyunv@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目录下
  [iyunv@localhost ~]# cd linux-test/j2me_cldc/tools/jcc
[iyunv@localhost jcc]# unzip classes.zip -d /root/java/classes/
  [iyunv@localhost jcc]# unzip classesUnix.zip -d /root/java/classesUnix/

  用下面命令进行预校验
  preverify -classpath classesdir myclass
  [iyunv@localhost ~]# cd java
[iyunv@localhost java]# preverify -classpath classes/classes classes/classesUnix HelloWorldApp
段错误
[iyunv@localhost java]#
参考http://www.cnblogs.com/oomusou/archive/2008/06/14/j2me_cpld_preverify.html,知是使用的语系问题。Solution如下:
  <1>显示目前使用的语系
  [iyunv@localhost java]# echo $LANG
zh_CN.UTF-8
  不管目前使用的中文还是英文,只要是UTF-8就会出现上面错误。
  <2>暂时修改成en_US.ISO8859-1语系
[iyunv@localhost java]# export LANG=en_US.ISO8859-1
[iyunv@localhost java]# echo $LANG
en_US.ISO8859-1
  <3>再次执行preverify
  [iyunv@localhost java]# preverify -classpath classes/classes classes/classesUnix HelloWorldApp
[iyunv@localhost java]#
  执行成功。
  (3)在目标板上运行测试
  先将/root/linux-test/j2me_cldc/kvm/VmUnix/build目录下的kvm复制到开发板根目录即nfsboot/rootfs/usr/local/sbin目录下
  [iyunv@localhost ~]# cp linux-test/j2me_cldc/kvm/VmUnix/build/kvm /nfsboot/rootfs/usr/local/sbin
[iyunv@localhost ~]#
  然后将校验后生成的Java/output目录下HelloWorldApp.class复制到开发板的/root目录下
  [iyunv@localhost ~]# cp /root/java/output/HelloWorldApp.class /nfsboot/rootfs/root/
[iyunv@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
然后再串口终端中执行
  [iyunv@mini2440 /]#kvm
-/bin/sh: kvm: not found
[iyunv@mini2440 /]#
  问题分析:kvm是用arm-linux-gcc-3.3.2编译的,而内核是用arm-linux-gcc-4.4.3编译的。在【12】中用file指令查看结果是&quot;for GNU/Linux 2.0.0 ”,显然出现了兼容问题。
  由此,我突然想到一个问题,之前用arm-linux-gcc-4.4.3编译应用程序时,通过file查看,可以看到如&quot;for GNU/Linux 2.6.32&quot; 之类的信息,而编译kvm则是出现的&quot;for GNU/Linux 2.0.0 ”这样的信息,arm-linux-gcc是如何知道内核版本信息的呢?

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-125130-1-1.html 上篇帖子: 机房KVM招标:市场主要品牌选型推荐 下篇帖子: 在Vmware的CentOS 6上安装kvm
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表