2011年12月26日
Androidでinitの代わりに/system/bin/shを動かしてみた
AndroidをNFSROOTで動かしているときにはカーネルのブートパラメータで init=/init を指定しますが、これを init=/system/bin/sh にしてみました。
rootファイルシステムをinitrdにしているときには/system/bin/shはそこには含まれていないので、なんとかしてshコマンドとそれに必要なダイナミックリンクライブラリをramdiskに入れておく必要があります。
でも今回は最初からrootも/systemも一緒にしてマウントしているので簡単です。
... [ 5.290000] IP-Config: Got DHCP answer from 0.0.0.0, my address is 192.168.1.122 [ 5.290000] IP-Config: Complete: [ 5.300000] device=eth0, addr=192.168.1.122, mask=255.255.255.0, gw=192.168.1.62, [ 5.300000] host=192.168.1.122, domain=kmckk.jp, nis-domain=(none), [ 5.310000] bootserver=0.0.0.0, rootserver=192.168.1.26, rootpath= [ 5.320000] Looking up port of RPC 100003/2 on 192.168.1.26 [ 5.330000] Looking up port of RPC 100005/1 on 192.168.1.26 [ 5.340000] VFS: Mounted root (nfs filesystem) on device 0:12. [ 5.340000] Freeing init memory: 120K sh: can't access tty; job control turned off #
このようにシリアルコンソールにプロンプトが出ました。
# ls ls: not found # export PATH=/system/bin # ls acct cache config d data default.prop dev etc init init.goldfish.rc init.kzm9d.rc init.rc init.rc.2 init.rc.min init.rc.org initlogo.rle lib mnt oprofile_target.tar proc sbin sdcard sys system ueventd.goldfish.rc ueventd.kzm9d.rc ueventd.rc usr vendor #
環境変数PATHの設定をしたら、lsコマンドが使えるようになりました。
# ps USER PID PPID VSIZE RSS WCHAN PC NAME # mount -t proc proc /proc # ps USER PID PPID VSIZE RSS WCHAN PC NAME root 1 0 728 308 c00597f8 4000d264 S /system/bin/sh root 2 0 0 0 c006be50 00000000 S kthreadd root 3 2 0 0 c005bf5c 00000000 S ksoftirqd/0 root 4 2 0 0 c008bfb0 00000000 S migration/0 root 5 2 0 0 c008bfb0 00000000 S migration/1 root 6 2 0 0 c005bf5c 00000000 S ksoftirqd/1 root 7 2 0 0 c00681f8 00000000 S events/0 root 8 2 0 0 c00681f8 00000000 S events/1 root 9 2 0 0 c00681f8 00000000 S khelper root 10 2 0 0 c00724c0 00000000 S async/mgr root 11 2 0 0 c00681f8 00000000 S suspend root 12 2 0 0 c00aee78 00000000 S sync_supers root 13 2 0 0 c00af724 00000000 S bdi-default root 14 2 0 0 c00681f8 00000000 S kblockd/0 root 15 2 0 0 c00681f8 00000000 S kblockd/1 root 16 2 0 0 c01faac0 00000000 S khubd root 17 2 0 0 c00681f8 00000000 S kmmcd root 18 2 0 0 c00681f8 00000000 S rpciod/0 root 19 2 0 0 c00681f8 00000000 S rpciod/1 root 20 2 0 0 c00a9900 00000000 S kswapd0 root 21 2 0 0 c00681f8 00000000 S aio/0 root 22 2 0 0 c00681f8 00000000 S aio/1 root 23 2 0 0 c00681f8 00000000 S nfsiod root 24 2 0 0 c00681f8 00000000 S emxx_fb root 25 2 0 0 c00681f8 00000000 S emxx_lcd root 26 2 0 0 c01ce46c 00000000 S kv4l2_rot root 27 2 0 0 c01ce46c 00000000 S kv4l2_tmr root 28 2 0 0 c01ce46c 00000000 S kv4l2_lcd root 31 2 0 0 c00681f8 00000000 S ehci-wq root 32 2 0 0 c00681f8 00000000 S usb_suspend root 33 2 0 0 c021cf54 00000000 S file-storage root 34 2 0 0 c00681f8 00000000 S usbhid_resumer root 35 2 0 0 c00681f8 00000000 S binder root 36 2 0 0 c02339dc 00000000 S mmcqd root 37 2 0 0 c01d3968 00000000 S scsi_eh_0 root 38 2 0 0 c0215004 00000000 S usb-storage root 44 1 928 332 00000000 40010438 R ps #
/procをマウントしたらpsコマンドが使えるようになりました。
# exec /init
このように/initを実行すれば、普通にAndroidが立ち上がります。
# exec /system/xbin/strace -o /data/local/tmp/strace.log /init
代わりにstraceをかませてinitを実行してみました。
# exec /system/xbin/strace -o /data/local/tmp/strace.log /init ptrace: umoven: I/O error ptrace: umoven: I/O error ptrace: umoven: I/O error ptrace: umoven: I/O error ptrace: umoven: I/O error ptrace: umoven: I/O error ptrace: umoven: I/O error ptrace: umoven: I/O error ...
こんなエラーが出ましたが、以下のようにinitのstraceのログをとることができました。
execve("/init", ["/init"], [/* 2 vars */]) = 0 SYS_224(0, 0xbe7e3000, 0x20000, 0xbe802ed8) = 41 syscall_983045(0x2217c, 0x22140, 0x22278, 0x40, 0x22140, 0xbe802f20, 0xbe802f2c, 0xf0005, 0xbe7e3000, 0, 0, 0, 0, 0xbe802ed0, 0x17f01, 0x9350, 0x60000010, 0x2217c, 0xb691, 0, 0x696e692f, 0x74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0 open("/dev/urandom", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory) mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40000000 mprotect(0x40000000, 4096, PROT_READ) = 0 brk(0) = 0x24000 brk(0x24000) = 0x24000 brk(0x26000) = 0x26000 umask(0) = 022 mkdir("/dev", 0755) = -1 EEXIST (File exists) mkdir("/proc", 0755) = -1 EEXIST (File exists) mkdir("/sys", 0755) = -1 EEXIST (File exists) mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, 0x1b374) = 0 mkdir("/dev/pts", 0755) = 0 mkdir("/dev/socket", 0755) = 0 mount("devpts", "/dev/pts", "devpts", 0, 0) = 0 mount("proc", "/proc", "proc", 0, 0) = 0 mount("sysfs", "/sys", "sysfs", 0, 0) = 0 open("/dev/.booting", O_WRONLY|O_CREAT|O_LARGEFILE, 0) = 3 close(3) = 0 mknod("/dev/__null__", S_IFCHR|0600, makedev(1, 3)) = 0 open("/dev/__null__", O_RDWR|O_LARGEFILE) = 3 unlink("/dev/__null__") = 0 dup2(3, 0) = 0 dup2(3, 1) = 1 dup2(3, 2) = 2 close(3) = 0 mknod("/dev/__kmsg__", S_IFCHR|0600, makedev(1, 11)) = 0 open("/dev/__kmsg__", O_WRONLY|O_LARGEFILE) = 3 fcntl64(3, F_SETFD, FD_CLOEXEC) = 0 unlink("/dev/__kmsg__") = 0 open("/init.rc", O_RDONLY|O_LARGEFILE) = 4 lseek(4, 0, SEEK_END) = 16933 lseek(4, 0, SEEK_SET) = 0 brk(0x2a000) = 0x2a000 read(4, "on early-init\n start ueventd\n"..., 16933) = 16933 close(4) = 0 mprotect(0x40000000, 4096, PROT_READ|PROT_WRITE) = 0 mprotect(0x40000000, 4096, PROT_READ) = 0 fstat64(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(1, 3), ...}) = 0 brk(0x2b000) = 0x2b000 mprotect(0x40000000, 4096, PROT_READ|PROT_WRITE) = 0 mprotect(0x40000000, 4096, PROT_READ) = 0 ioctl(1, TCGETS or SNDCTL_TMR_TIMEBASE, 0xbe802590) = -1 ENOTTY (Not a typewriter) brk(0x2c000) = 0x2c000 brk(0x2d000) = 0x2d000 brk(0x2e000) = 0x2e000 open("/proc/cmdline", O_RDONLY|O_LARGEFILE) = 4 read(4, "root=/dev/nfs nfsroot=192.168.1."..., 1023) = 240 close(4) = 0 chmod("/proc/cmdline", 0440) = 0 open("/proc/cpuinfo", O_RDONLY|O_LARGEFILE) = 4 read(4, "Processor\t: ARMv7 Processor rev "..., 1023) = 324 close(4) = 0 open("/init.kzm9d.rc", O_RDONLY|O_LARGEFILE) = 4 lseek(4, 0, SEEK_END) = 574 lseek(4, 0, SEEK_SET) = 0 read(4, "on early-init\n export EXTERNA"..., 574) = 574 close(4) = 0 stat64("/sbin/ueventd", {st_mode=S_IFREG|0750, st_size=98676, ...}) = 0 fork() = 42 msgget(0x1, 0xbe802c00, 0, 0x1) = 0 poll(0xbe802e9c, 0, 0) = 0 mkdir("/mnt", 0775) = -1 EEXIST (File exists) chmod("/mnt", 0775) = 0 chown32(0x25050, 0, 0x3e8) = 0 poll(0xbe802e9c, 0, 0) = 0 poll(0xbe802e9c, 0, 0) = 0 mkdir("/mnt/sdcard", 0) = -1 EEXIST (File exists) chmod("/mnt/sdcard", 0) = 0 chown32(0x2d840, 0x3e8, 0x3e8) = 0 poll(0xbe802e9c, 0, 0) = 0 symlink("/mnt/sdcard", "/sdcard") = -1 EEXIST (File exists) poll(0xbe802e9c, 0, 0) = 0 msgget(0x1, 0xbe802dd8, 0x1b242, 0xff0a0000) = 0 msgget(0x1, 0xbe802dd8, 0x3a80905c, 0x1b242) = 0 stat64("/dev/.coldboot_done", 0xbe802de8) = -1 ENOENT (No such file or directory) nanosleep({0, 10000000}, {0, 10000000}) = 0 msgget(0x1, 0xbe802dd8, 0, 0x989680) = 0 stat64("/dev/.coldboot_done", 0xbe802de8) = -1 ENOENT (No such file or directory) nanosleep({0, 10000000}, {0, 10000000}) = 0 msgget(0x1, 0xbe802dd8, 0, 0x989680) = 0 stat64("/dev/.coldboot_done", 0xbe802de8) = -1 ENOENT (No such file or directory) nanosleep({0, 10000000}, {0, 10000000}) = 0 msgget(0x1, 0xbe802dd8, 0, 0x989680) = 0 stat64("/dev/.coldboot_done", 0xbe802de8) = -1 ENOENT (No such file or directory) nanosleep({0, 10000000}, {0, 10000000}) = 0 msgget(0x1, 0xbe802dd8, 0, 0x989680) = 0 stat64("/dev/.coldboot_done", 0xbe802de8) = -1 ENOENT (No such file or directory) nanosleep({0, 10000000}, {0, 10000000}) = 0 msgget(0x1, 0xbe802dd8, 0, 0x989680) = 0 stat64("/dev/.coldboot_done", 0xbe802de8) = -1 ENOENT (No such file or directory) nanosleep({0, 10000000}, {0, 10000000}) = 0 msgget(0x1, 0xbe802dd8, 0, 0x989680) = 0 stat64("/dev/.coldboot_done", 0xbe802de8) = -1 ENOENT (No such file or directory) nanosleep({0, 10000000}, {0, 10000000}) = 0 msgget(0x1, 0xbe802dd8, 0, 0x989680) = 0 stat64("/dev/.coldboot_done", 0xbe802de8) = -1 ENOENT (No such file or directory) nanosleep({0, 10000000}, {0, 10000000}) = 0 ...
2011.12.27追記
このときとれたログをここに置きました。
/dev/.coldbootはueventdが作成します。
system/core/init/device.c
void device_init(void)
{
suseconds_t t0, t1;
struct stat info;
int fd;
/* is 64K enough? udev uses 16MB! */
device_fd = uevent_open_socket(64*1024, true);
if(device_fd < 0)
return;
fcntl(device_fd, F_SETFD, FD_CLOEXEC);
fcntl(device_fd, F_SETFL, O_NONBLOCK);
if (stat(coldboot_done, &info) < 0) {
t0 = get_usecs();
coldboot("/sys/class");
coldboot("/sys/block");
coldboot("/sys/devices");
t1 = get_usecs();
fd = open(coldboot_done, O_WRONLY|O_CREAT, 0000);
close(fd);
log_event_print("coldboot %ld uS\n", ((long) (t1 - t0)));
} else {
log_event_print("skipping coldboot, already done\n");
}
}