作者:Bill Courington 和 Gary Collins
2012 年 8 月发布
如何在一小时内让 Linux 和 Java SE Embedded 在 Raspberry Pi 上运行
它只有信用卡大小,价格约等于一本 Java 编程书。
它就是 Raspberry Pi 计算机,可以支持适用于无头嵌入式应用程序的完整 Java SE 运行时。本文带您了解 Raspberry Pi 上的 Java 编程,包括以下主题:
注:此处所给出的说明可以有多种变化,特别是在主机(台式或便携式)计算机上执行的操作,以及在 Raspberry Pi 上执行的操作。请根据您的知识和喜好(可能还包括可选的 Linux 调优和调整一节中的某些主题)创建适合自己的工作流。
Raspberry Pi 是一款小型、低功耗的主板,采用 700mHz ARMv6 CPU,在单一芯片上集成了硬件浮点和图形处理器。图形处理器和 CPU 共享 256MB RAM。提供了 USB、以太网、高清图形、音频、SD 卡以及通用 I/O 接口。图 1 显示的 Raspberry Pi B 型插入了 SD 卡进行扩展。SD 卡有着特殊的作用:Raspberry Pi 将从 SD 卡启动。本文主要介绍如何创建和修改可启动的 SD 卡上的文件。
图 1. Raspberry Pi B 型
可以通过 USB 键盘和鼠标以及 HDMI 监视器或电视(最高 1080p)与 Raspberry Pi 交互。该板上的以太网连接提供了另一种选择:通过 ssh
从联网主机交互。本文的可选的 Linux 调优和调整一节介绍如何启用 ssh
登录。
要设置 Raspberry Pi B 型使其运行 Java SE Embedded,您需要:
wget
实用程序。
$ sudo apt-get install gparted
通电时,Raspberry Pi 固件从 SD 卡槽启动。Java SE Embedded 在 Linux 上运行,因此首先要在 SD 卡上安装 Linux。
注:这些说明适用于 Debian Squeeze。其他适用于 Raspberry Pi 的 Linux 实现也可以使用,但必须 针对 ARM 芯片的软件浮点计算进行了构建。Raspberry Pi 网站上链接的映像可能已针对硬件浮点计算进行了构建;不适用于 Java SE for Embedded。
可以在此处找到适用于 Raspberry Pi 的压缩 Debian Squeeze 映像:http://elinux.org/RPi_Distributions#Debian_ARM。文件大小约 450MB。以下说明假定已下载到新目录 ~/RaspberryPi/
。要验证下载的文件,请遵循下载开始时显示的页面上的 SHA-1 校验和说明。
按如下所示解压缩映像:
$ cd ~/RaspberryPi $ unzip *.zip
解压缩过程创建一个名称类似 debian6-19-04-2012
的子目录。
在主机上找出 SD 卡设备句柄,如下所示(如果您愿意,也可以采用其他方式):
dmesg | tail
,这将显示与设备挂载有关的消息。我们只对消息的末尾部分感兴趣。dmesg | tail
。与第一个窗口相比,此窗口多出一些与新挂载的 SD 卡有关的行。具体细节可能不尽相同,但应如下所示:[ 110.084625] sdb:detected capacity change from 0 to 3963617280
[ 118.055249] sd 2:0:0:0:[sdb] 7741440 512-byte logical blocks:(3.96 GB/3.69 GiB)
[ 118.059409] sd 2:0:0:0:[sdb] Assuming drive cache:write through
[ 118.064547] sd 2:0:0:0:[sdb] Assuming drive cache:write through
[ 118.066015] sdb:sdb1
sdb
,它表示设备句柄为 /dev/sdb
。sdb1
指示例卡的单个分区。您的卡可能有多个分区。在以下说明中,假定 SD 卡设备句柄为 /dev/sdb
,它只有一个分区:sdb1
。如果需要,可根据您的环境调整说明。
$ sudo umount /dev/sdb1
dd
将 Debian 映像复制到 SD 卡。of
(输出文件)参数值。您将调用低级磁盘复制,这将覆盖所有数据。指定错误的设备会破坏数据。$ cd ~/RaspberryPi/debian6-19-04-2012
$ sudo dd if=yourDebian.img of=/dev/sdb bs=1M
1859+1 records in
1859+1 records out
1950000000 bytes (2.0 GB) copied, 212.344 s, 9.2MB/s
dd
到 SD 卡是一个缓慢的操作。4GB 4 类卡可能需要 5-10 分钟。dd
不提供进度指示,因此请耐心等待它慢慢完成工作。如果现在想确定 SD 卡 Linux 已起作用,请跳到首次启动一节,然后返回调整 SD 卡分区大小。
SD 卡现在包含三个分区和未分配空间。现在我们将未分配空间添加到 Linux 文件系统,为 Java SE Embedded 和应用程序提供更多空间。为了向文件系统分配未分配空间,我们修改 SD 卡上的分区,删除并重新创建一个分区,然后调整另一个分区的大小。
$ sudo gparted
/dev/sdb
上的分区和未分配空间:图 2. 初始 SD 卡分区
三个分区分别是:
/dev/sdb1
:引导分区/dev/sdb2
:Linux 根文件系统。它分配的 1.5GB 空间大部分已使用。/dev/sdb3
:Linux 交换区。大约一半的卡空间未分配。最大一块可用空间跟在 /dev/sdb3
分区后面。为了将此空间添加到 /dev/sdb2
(文件系统),我们临时删除 /dev/sdb3
,扩展 /dev/sdb2
,然后重新创建 /dev/sdb3
。
/dev/sdb3
(linux 交换区),右键单击并选择 Delete。分区显示为已删除,但是 GParted 将此操作加入队列中,稍后运行。图 3. 将 Delete 操作加入队列后的 SD 卡分区
/dev/sdb2
(Linux 文件系统),右键单击并选择 Resize/Move。在出现的对话框中,拖动右箭头,直至 Free space following 约为 512(或者您希望留作交换分区的空间大小)。您可能无法准确地拖到 512,但这并不重要。图 4. 512MB 用作交换分区
图 5. 新的交换分区
图 6. 新的分区图
注:针对这些步骤,以下组件必须连接到 Raspberry Pi:监视器、键盘以及确知有效的以太网电缆。
$ sudo /etc/rc.local
RaspberryIP
ssh
登录:$ sudo update-rc.d -f ssh defaults 20
ssh
登录:$ sudo sync; sudo shutdown -r now
现在,我们可以通过网络从主机读写 Raspberry Pi SD 卡。
在本节中,我们使用主机下载 Java SE Embedded,通过网络将其复制到 Raspberry Pi 的 Linux 文件系统。然后,还是通过远程方式解压缩下载文件并启动 Java。
图 7. 第一个下载链接
图 8. 第二个下载链接
.gz
文件保存到 Downloads
目录。 $ ssh pi@RaspberryIP mkdir /home/pi/java
$ scp ~/Downloads/*.gz pi@RaspberryIP:/home/pi/java
$ ssh pi@RaspberryIP
$ cd /home/pi/java
$ tar -zxvf *.gz
...
$ ls ejre*
ejre1.7.0_04
$ cd ejre*
$ ./bin/java -version
java version "1.7.0_04-ea"
Java(TM) SE Runtime Environment for Embedded (build 1.7.0_04-ea-b20, headless)
Java Hotspot(TM) Embedded Client VM (build 23.0-b21, mixed mode)
$ rm /home/pi/java/*.gz
本节中的命令可以让您的 Raspberry Pi 系统运行地可靠、响应更即时、更方便。根据自己的喜欢进行选择,然后在 Raspberry Pi 上运行。为了简化诊断问题,请在每次更改后重新启动。
在本节中:
如果您的网络重用动态 IP 地址,您可以跳过更改静态 IP,因为 Raspberry Pi 的 IP 地址实际上将保持不变。如果每次启动时 Raspberry Pi 的动态 IP 地址可能不同,对于 ssh
来说,使用静态 IP 地址会更方便。在以下说明中,假定希望为 Raspberry Pi 分配主机名 raspberrypi
。
首先以超级用户身份在文本编辑器中打开 /etc/hosts
(例如,sudo vi /etc/hosts
)。为 Raspberry Pi 添加一行,包括网络中的有效静态 IP 地址、可选的域名以及别名。以下是一个假设示例,其中将 Raspberry Pi 指定为 raspberrypi
:
127.0.0.1 localhost?192.168.0.100 raspberrypi.yourDomain raspberrypi loghost
保存文件,退出编辑器。
以超级用户身份在文本编辑器中打开 /etc/hostname
。添加一行,如下所示:
raspberrypi
保存文件,退出编辑器。
以下说明可以防止过载网络中导致操作系统更改 Raspberry Pi 静态 IP 地址的问题。这一问题会使 ssh
或其他使用静态 IP 地址的操作停止工作。
发现以太网端口的硬件地址,如下所示。
首先,确定以太网控制器的名称(x
代表地址数字):
$ ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1488 qdisc pfifo_fast state UNKNOWN qlen 1000 link/ether b8:27:eb:b5:e8:90 brd ff:ff:ff:ff:ff:ff inet xx.xxx.xxx.xx/xx brd xx.xxx.xxx.xxx scope global eth0在此例中,名称为
eth0
。硬件地址是 link/ether
之后的十六进制数字,本例中为 b8:27:eb:b5:e8:90
。 得到以太网控制器的硬件地址之后,以超级用户身份在文本编辑器中打开 /etc/network/interfaces
,并添加(替代网络详细信息)类似下面所示 # New entries
注释之后的内容。
# Used by ifup(8) and ifdown(8). See the interfaces(5) manpage or? # /usr/share/doc/ifupdown/examples for more information. auto lo iface lo inet loopback # # New entries to support static IP follow: auto eth0 iface eth0 inet static hwaddress ether b8:27:eb:b5:e8:90 address 192.168.0.100 network 192.168.0.0 netmask 255.255.255.0255.255.255.0 broadcast 192.168.0.255 gateway 192.168.0.1
默认情况下,Debian Linux 中禁用交换。如果操作超出 Raspberry Pi 的 256KB RAM 大小,系统就会崩溃。还有一种情况没这么严重,即默认情况下,文件系统要花时间维护每个文件的上次访问时间,这对嵌入式应用程序基本没有用处。维护上次访问时间还可能缩短 SD 卡的生命周期。这两种默认行为均在 /etc/fstab
文件中指定。
以超级用户身份在编辑器(如 vi
)中打开 /etc/fstab
。该文件如下所示:
proc /proc proc defaults 0 0 /dev/mmcblk0p1 /boot vfat defaults 0 0 #/dev/mmcblk0p3 none swap sw 0 0
要启用交换,请取消第三行的注释。
注:SD 卡上的交换很慢。对于嵌入式应用程序,您可能希望管理内存以避免出现此问题。
为避免维护上次访问信息产生的开销,请在 p1
与 p3
之间插入一个 p2
挂载点。noatime
和 nodiratime
选项可完成此任务。当文件如下面所示时,保存文件,退出编辑器:
proc /proc proc defaults 0 0 /dev/mmcblk0p1 /boot vfat defaults 0 0 /dev/mmcblk0p2 / auto rw,noatime,nodiratime,errors=remount-ro 0 1 /dev/mmcblk0p3 none swap sw 0 0
现在,为交换空间分配 p3
(在主机上创建的交换分区 /dev/sdb3
):
$ sudo mkswap /dev/mmcblk0p3
默认情况下,Raspberry Pi 配置为使用欧洲/伦敦时区和 en_GB_UTF-8 语言环境。要实现计算机本地化,请遵循以下说明。
要更改时区,请输入以下命令:
$ sudo dpkg-reconfigure tzdata将出现一个伪图形界面。
图 9. 时区用户界面
使用上下箭头键在地区和城市间移动选择光标。使用左右箭头键选择 <Ok> 或 <Cancel>。按 Return 输入选择。
按如下所示设置语言环境:
$ sudo dpkg-reconfigure -p low locales
用户界面与设置时区的界面类似。
许多操作(包括软件包更新)依赖于正确的日期和时间。要自动设置日期和时间,请了解网络时间服务器的身份,然后运行以下命令:
$ sudo ntpdate yourNTPServer要在每次启动时设置时间,请以超级用户身份编辑
/etc/rc.local
,并在脚本退出前添加以下代码行: ntpdate yourNTPServer
Ping 某个知名的互联网主机,如 www.lego.com
。如果主机不响应,则确定网络是否位于代理后面,如有需要,还可根据网络约定设置环境变量 http_proxy
,例如(假设):
$ sudo export http_proxy =’http:192.168.0.1:3128’
要在每次登录时设置代理,请在 ~/.bash_profile
中添加 export 命令,或等效命令(如果使用其他 shell)。
如果键盘键解释错误或者希望更改键盘布局,请使用以下命令:
$ sudo dpkg-reconfigure keyboard-configuration
用户界面类似于本文设置时区和语言环境一节中描述的内容。
更新随 Debian 发布的软件包之前,以超级用户身份在文本编辑器中打开 /etc/apt/sources.list
。此文件包含新/更新软件包的信息库位置。发行时,位置 URL 中含 ftp.uk。如果您不在英国,将这些条目更改为物理上离您更近的位置可以提高性能。例如,如果您在美国,可以将 ftp.uk 全局更改为 ftp.us。以下站点包含有关 Debian 信息库位置的信息:http://ftp.debian.org/debian/README.mirrors.html。
要更新已安装的软件包,请在验证 Raspberry Pi 可以连接到互联网连接之后,输入以下命令:
$ sudo apt-get update $ sudo apt-get upgrade
如果收到消息,指示软件包列表中有重复项,则在编辑器中再次打开 /etc/apt/sources.list
,注释掉其中一个重复的条目。通常最好保留包含信息较多的条目。
如果希望窗口系统在您本地登录 Raspberry Pi 时自动启动,则需更改默认的运行级别,如下所示。以超级用户身份在文本编辑器中打开 /etc/inittab
。找到以下条目:
# The default runlevel. id:2:initdefault:将它更改为 5:
# The default runlevel. id:5:initdefault:注:图形会使用大量 Raspberry Pi RAM,大约 90MB。
如果使用默认 midori 浏览器遇到困难,可以尝试 iceweasel:
$ sudo apt-get update $ sudo apt-get install iceweasel
默认情况下,Raspberry Pi 声音输出不起作用。要想启用,以超级用户身份在文本编辑器中打开 /etc/modules
。在文件末尾添加以下代码行:
snd_bcm2835
保存并关闭文件。重新启动 Raspberry Pi 时就会启用声音。