2011年8月26日金曜日

Android上でUbuntuのアプリを実行できるようにしてみた際の作業メモ。

環境:

  • Android
  • 作業に使ったPC
    • windows7 home 64bit
    • VMWARE Player / ubuntu-9.10-server-amd64.iso

1. はじめに

前提

Android = Linuxカーネル  Androidユーザランド

スタティックリンクされたELFなら、そのまま動く。

一般的なlinuxシステムでは、ごく基本的なコマンドも共有ライブラリに依存している。

これらを動かすには、実際のlinuxシステムと同じ位置に、共有ライブラリ群を配置することが必要。

 

目標

Ubuntu(ARM)の実行ファイルおよび、共有ライブラリを配置して、起動できること。

(オプション1)chrootした環境で、sshdを起動し、リモートログインできるようにすること。apt-getで任意のパッケージをインストールできるようにすること。

(オプション2)vnc経由で、X環境が利用できるようにすること。

2. 手順の概要

1. X86版のUbuntu Linuxをインストール。

VMWARE Player

2. arm版のUbuntu Linuxの作成。

rootstock

QEMUで起動確認。

3. Android上で、上記2.をループバックデバイスにマウント。

/bin/lib等にubuntuのディレクトリをバインド。ここまででubuntuELFが起動できる。

4. chroot → 実際のubuntuとほぼ等価の環境

Apt-get任意のパッケージのインストール。

sshdを起動。リモートログイン。

5. vnc-server → LXDE環境の起動。

3. Androidの構成

カーネル

基本的には、素のlinuxカーネルと同じ。

今回は再ビルドせずに、そのまま利用。以下の機能は使用可能。

–loopback device

–ext2, ext3 filesystem

 

共有ライブラリ

Bionic

Android独自の共有ライブラリで構成されており、linuxglibcとはまったく別。ディレクトリの配置場所も異なる。

 

ディレクトリ構成

Androidのファイル群は、/system以下に配置。

/bin/usrなどは存在していないので、逆に言うと、ここにubuntuのファイル群をそのまま持ってくることができる。

/lib/modulesは存在するが、/lib直下は空。

 

ファイルシステム構成

'/' はリードオンリー。RAMDISK

ブート時に自動実行する仕掛けを作るのは面倒。

その他 /system/dataなどは、MTD (Memory Technology Device) 形式のパーテーション。


3.1 Android
で利用可能なコマンド

前提

Android SDKをインストールして、ADBが使えるようになっていること。

Root権限を取得済みであること。

 

Androidで利用可能なコマンド

シェルは、/system/bin/sh

たぶんroot化の際に、busyboxが組み込み済み。

Mount, mknod など。

/system/bin内のコマンドによっては、実体が/system/bin/toolbox へのリンクのものがある。

mount busyboxtoolboxで挙動が異なる。

 

Androidで利用不可なコマンド

存在していないコマンド。Free, touch, uname などなど。

linuxの共有ライブラリの世界とは無縁なので、lddの類も使えない。

3.2. Androidのファイルシステム

ボリューム構成。

内蔵の4GB NANDフラッシュは、先頭1GBMTD形式。残り3GBFATにパーテーションが切られている。

ルートはRAMディスクで、roでマウント。(boot)

その他は、/dev/block/mtdblock*をそれぞれマウント。

# cat /proc/mtd

dev:    size   erasesize  name

mtd0: 00a00000 00200000 "boot"

mtd1: 00600000 00200000 "kpanic"

mtd2: 10400000 00200000 "system"

mtd3: 00400000 00200000 "splash"

mtd4: 03c00000 00200000 "cache"

mtd5: 29e00000 00200000 "userdata"

mtd6: 00a00000 00200000 "recovery"

mtd7: 00200000 00200000 "misc"

mtd8: 00200000 00200000 "tcc"

# mount

rootfs on / type rootfs (ro,relatime)

tmpfs on /dev type tmpfs (rw,relatime,mode=755)

devpts on /dev/pts type devpts (rw,relatime,uid=0,gid=5,mode=620)

proc on /proc type proc (rw,relatime)

sysfs on /sys type sysfs (rw,relatime)

tmpfs on /broadcasting type tmpfs (rw,relatime,size=1024k)

none on /acct type cgroup (rw,relatime,cpuacct)

tmpfs on /mnt/asec type tmpfs (rw,relatime,mode=755,gid=1000)

tmpfs on /mnt/obb type tmpfs (rw,relatime,mode=755,gid=1000)

none on /dev/cpuctl type cgroup (rw,relatime,cpu)

/dev/block/mtdblock2 on /system type yaffs2 (ro,relatime)

/dev/block/mtdblock5 on /data type yaffs2 (rw,nosuid,nodev,relatime)

/dev/block/mtdblock4 on /cache type yaffs2 (rw,nosuid,nodev,relatime)


カーネルがサポートしているデバイス。

Loop deviceは使える。(/proc/devices
Ext2,ext3は使える。ext4は多分無理。(/proc/filesystems


/dev ディレクトリ

/dev/loop* は存在していないので、手動で作る必要あり。'busybox mknod'が使える。
mount時にどのloopデバイスファイルが使われるか分からないので、0~7まで、一通り作る。

4. 手順:armubuntuの作成

x86ubuntu

9.10 (karmic) server版を使用。

VMWARE Player上で普通にインストール。

 

ARMubuntu

x86ubuntu上で、rootstockを実行。

ループバックデバイスに書き込んで、イメージファイルを作成。

rootstock --fqdn arm-karmic --login user --password user

dd if=/dev/zero of=arm-ubuntu-9.10.img bs=1MB count=0 seek=1024

mkfs.ext3 -F arm-ubuntu-9.10.img

mount -o loop arm-ubuntu-9.10.img /mnt/loop/

cd /mnt/loop

tar xzvf /home/xxxx/armel/armel-rootfs-201108092351.tgz

 

QEMUによる起動確認。

wget http://ports.ubuntu.com/ubuntu-ports/dists/karmic/main/installer-armel/current/images/imx51/netboot/initrd.gz

wget http://ports.ubuntu.com/ubuntu-ports/dists/lucid/main/installer-armel/current/images/versatile/netboot/vmlinuz

qemu-system-arm -M versatilepb -cpu cortex-a8 -m 256 -kernel ./vmlinuz -hda arm-ubuntu-9.10.img -append "root=/dev/sdamem=256M devtmpfs.mount=0 rw"

5. 手順:androidubuntuファイルシステムを追加

ルートファイルシステムをrwでリマウント。

/dev/loop*を作成。

イメージファイルをマウント。

/bin, /lib, /usr, /home に、ubuntuのディレクトリをバインド。

逆に、/proc, /dev は、chrootしたときに見えるように、ubuntu側にバインドしておく。

mount -o rw,remount -t rootfs rootfs /

busybox mknod /dev/loop0 b 7 0

busybox mknod /dev/loop1 b 7 1

busybox mknod /dev/loop2 b 7 2

busybox mknod /dev/loop3 b 7 3

busybox mknod /dev/loop4 b 7 4

busybox mknod /dev/loop5 b 7 5

busybox mknod /dev/loop6 b 7 6

busybox mknod /dev/loop7 b 7 7

mkdir /mnt/ubuntu

mkdir /bin

mkdir /home

mkdir /usr

mount -o ro,remount -t rootfs rootfs /

busybox mount -o rw,loop -t ext3 /mnt/sdcard/tflash/arm-ubuntu-9.10.img /mnt/ubuntu

busybox mount -o bind /mnt/ubuntu/bin /bin

busybox mount -o bind /mnt/ubuntu/lib /lib

busybox mount -o bind /mnt/ubuntu/usr /usr

busybox mount -o bind /mnt/ubuntu/home /home

busybox mount -o bind /proc /mnt/ubuntu/proc

busybox mount -o bind /dev /mnt/ubuntu/dev

 

6. ubuntu版のELFを実行した例

LDDコマンドでELFが依存している共有ライブラリを表示。

/ # cd /usr/bin

/usr/bin # ldd python

  libpthread.so.0 => /lib/libpthread.so.0 (0x40025000)

  libdl.so.2 => /lib/libdl.so.2 (0x40045000)

  libutil.so.1 => /lib/libutil.so.1 (0x40050000)

  libz.so.1 => /lib/libz.so.1 (0x4005b000)

  libm.so.6 => /lib/libm.so.6 (0x40079000)

  libc.so.6 => /lib/libc.so.6 (0x400ec000)

  /lib/ld-linux.so.3 (0x40000000)

  libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x40219000)

 

 例として、/usr/bin/pythonを実行。/usr/libなども参照できるため、pythonの標準ライブラリをimportすることも可能。

/usr/bin # python

Python 2.6.4rc2 (r264rc2:75497, Oct 20 2009, 03:46:31)

[GCC 4.4.1] on linux2

Type "help", "copyright", "credits" or "license" for more information.

>>> import datetime

>>> a = datetime.datetime.now()

>>> print a

2011-08-18 07:03:15.380133

>>> import sys

>>> sys.exit()

/usr/bin #

7. そのほか

ネットワークが使えるようにする。

echo "nameserver 8.8.8.8" > /etc/resolv.conf

echo "nameserver 8.8.4.4" >> /etc/resolv.conf

echo "127.0.0.1 localhost" > /etc/hosts

 

chroot

/usr/sbin/chroot /mnt/ubuntu /bin/bash /root/start-ssh.sh

 

sshd

/bin/umount /dev/pts

/bin/mount -t devpts -o uid=0,gid=5,mode=620 devpts /dev/pts

 

export HOME=/home/user

export PATH=/bin:/usr/bin:/usr/sbin:$PATH

export USERNAME=root

export PS1='\w \$ '

 

/etc/init.d/ssh stop

/etc/init.d/ssh start

 

11/08/20 追記)

LXDE環境

# apt-get install vncserver

# apt-get install lxde    

 

android端末上からapt-getを実行。パッケージのダウンロードとインストールがubuntu実機と同様に行われます。

300MB強。

セットアップの最後のほうで、xserver-xorgがエラーを起こしますが、ファイルの展開はできていると信じて、放置。

> xserver-xorg (1:7.4+3ubuntu7) を設定しています ...

> start: Unable to connect to Upstart: Failed to connect to socket /com/ubuntu/upstart: Connection refused

> invoke-rc.d: initscript hal, action "restart" failed.

 

# LANG=C vncserver -geometry 1024x600 -depth 16

# ps aux | grep vnc

root     20687  0.8  0.8   5736  3224 pts/2    S    21:11   0:00 Xtightvnc :2 -desktop X -auth /root/.Xauthority -geometry 1024x600 -depth 16 -rfbwait 120000 -rfbauth /root/.vnc/passwd -rfbport 5902 -fp /usr/share/fonts/X11/misc/,/usr/share/fonts/X11/Type1/,/usr/share/fonts/X11/75dpi/,/usr/share/fonts/X11/100dpi/ -co /etc/X11/rgb

 

英語環境でXを起動。

上記の「-rfbport 5902」が待ち受けのポート番号。リモートから、あるいは、android上のvncクライアントアプリから接続します。

日本語環境は未セットアップのため、日本語の表示・入力はできません。

 

0 件のコメント:

コメントを投稿