Linux
Chromium
webOS
Raspberrypi3

webOS Open Source Edition の観察(4)

webOSの本丸はどうやらWebAppMgrのようだ。

WebAppMgr

WebAppMgrがリンクしているライブラリ。

# /lib/ld-linux-armhf.so.3 --list /usr/bin/WebAppMgr
    linux-vdso.so.1 (0x7eee1000)
    /lib/libSegFault.so (0x76f3f000)
    libcbe.so => /usr/lib/libcbe.so (0x70c2d000)
    libWebAppMgr.so.1 => /usr/lib/libWebAppMgr.so.1 (0x70be8000)
    libWebAppMgrCore.so.1 => /usr/lib/libWebAppMgrCore.so.1 (0x70ba9000)
    libluna-prefs.so.3 => /usr/lib/libluna-prefs.so.3 (0x70ba3000)
    libPmLogLib.so.3 => /usr/lib/libPmLogLib.so.3 (0x70b97000)
    libglib-2.0.so.0 => /usr/lib/libglib-2.0.so.0 (0x70ad1000)
    libQt5Core.so.5 => /usr/lib/libQt5Core.so.5 (0x70726000)
    libpthread.so.0 => /lib/libpthread.so.0 (0x706fd000)
    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x705f8000)
    libm.so.6 => /lib/libm.so.6 (0x7057a000)
    libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x70560000)
    libc.so.6 => /lib/libc.so.6 (0x70425000)
    libunwind-arm.so.8 => /usr/lib/libunwind-arm.so.8 (0x703f2000)
    libfreetype.so.6 => /usr/lib/libfreetype.so.6 (0x70397000)
    librt.so.1 => /lib/librt.so.1 (0x70380000)
    libdl.so.2 => /lib/libdl.so.2 (0x7036d000)
    libgobject-2.0.so.0 => /usr/lib/libgobject-2.0.so.0 (0x70336000)
    libfontconfig.so.1 => /usr/lib/libfontconfig.so.1 (0x70308000)
    libexpat.so.1 => /usr/lib/libexpat.so.1 (0x702ef000)
    libpangocairo-1.0.so.0 => /usr/lib/libpangocairo-1.0.so.0 (0x702e4000)
    libpango-1.0.so.0 => /usr/lib/libpango-1.0.so.0 (0x702b5000)
    libcairo.so.2 => /usr/lib/libcairo.so.2 (0x7022b000)
    libgconf-2.so.4 => /usr/lib/libgconf-2.so.4 (0x7020b000)
    libxkbcommon.so.0 => /usr/lib/libxkbcommon.so.0 (0x701db000)
    libwayland-egl.so.1 => /usr/lib/libwayland-egl.so.1 (0x701d8000)
    libwayland-client.so.0 => /usr/lib/libwayland-client.so.0 (0x701cf000)
    libwayland-webos-client.so.1 => /usr/lib/libwayland-webos-client.so.1 (0x701ca000)
    libasound.so.2 => /usr/lib/libasound.so.2 (0x70133000)
    libluna-service2.so.3 => /usr/lib/libluna-service2.so.3 (0x70100000)
    libndl-directmedia2.so.1 => /usr/lib/libndl-directmedia2.so.1 (0x700d1000)
    libdbus-1.so.3 => /usr/lib/libdbus-1.so.3 (0x7009f000)
    libumedia_api.so.1 => /usr/lib/libumedia_api.so.1 (0x7008a000)
    /lib/ld-linux-armhf.so.3 (0x54b71000)
    libcjson.so.1 => /usr/lib/libcjson.so.1 (0x70084000)
    libsqlite3.so.0 => /usr/lib/libsqlite3.so.0 (0x70008000)
    libnyx.so.7 => /usr/lib/libnyx.so.7 (0x6fffb000)
    libpbnjson_c.so.2 => /usr/lib/libpbnjson_c.so.2 (0x6ffd5000)
    libpcre.so.1 => /usr/lib/libpcre.so.1 (0x6ffa0000)
    libz.so.1 => /lib/libz.so.1 (0x6ff90000)
    libicui18n.so.57 => /usr/lib/libicui18n.so.57 (0x6fe00000)
    libicuuc.so.57 => /usr/lib/libicuuc.so.57 (0x6fcee000)
    libunwind.so.8 => /usr/lib/libunwind.so.8 (0x6fcbd000)
    libffi.so.6 => /usr/lib/libffi.so.6 (0x6fcb6000)
    libpixman-1.so.0 => /usr/lib/libpixman-1.so.0 (0x6fc4f000)
    libpng16.so.16 => /usr/lib/libpng16.so.16 (0x6fc2f000)
    libpangoft2-1.0.so.0 => /usr/lib/libpangoft2-1.0.so.0 (0x6fc21000)
    libgthread-2.0.so.0 => /usr/lib/libgthread-2.0.so.0 (0x6fc1e000)
    libharfbuzz.so.0 => /usr/lib/libharfbuzz.so.0 (0x6fbc1000)
    libdbus-glib-1.so.2 => /usr/lib/libdbus-glib-1.so.2 (0x6fba9000)
    libgio-2.0.so.0 => /usr/lib/libgio-2.0.so.0 (0x6fabc000)
    libgmodule-2.0.so.0 => /usr/lib/libgmodule-2.0.so.0 (0x6fab8000)
    libsystemd.so.0 => /lib/libsystemd.so.0 (0x6fa5f000)
    libcap.so.2 => /lib/libcap.so.2 (0x6fa5a000)
    libresolv.so.2 => /lib/libresolv.so.2 (0x6fa36000)
    liblzma.so.5 => /usr/lib/liblzma.so.5 (0x6fa1b000)
    libopenmaxil.so => /usr/lib/libopenmaxil.so (0x6fa15000)
    libpbnjson_cpp.so.2 => /usr/lib/libpbnjson_cpp.so.2 (0x6fa07000)
    libmedia-resource-calculator.so.1 => /usr/lib/libmedia-resource-calculator.so.1 (0x6f9fc000)
    libavcodec.so.55 => /usr/lib/libavcodec.so.55 (0x6ed66000)
    libavutil.so.52 => /usr/lib/libavutil.so.52 (0x6ed1d000)
    libswresample.so.0 => /usr/lib/libswresample.so.0 (0x6ed0e000)
    libmdc_client.so.1 => /usr/lib/libmdc_client.so.1 (0x6ed04000)
    libmdc_content_provider.so.1 => /usr/lib/libmdc_content_provider.so.1 (0x6ecfa000)
    libresource_mgr_client.so.1 => /usr/lib/libresource_mgr_client.so.1 (0x6ece9000)
    libbcm_host.so => /usr/lib/libbcm_host.so (0x6ecd9000)
    libomxcomponents.so.1 => /usr/lib/libomxcomponents.so.1 (0x6ecce000)
    libums_connector.so.1 => /usr/lib/libums_connector.so.1 (0x6ecc4000)
    libyajl.so.2 => /usr/lib/libyajl.so.2 (0x6ecbd000)
    liburiparser.so.1 => /usr/lib/liburiparser.so.1 (0x6ecad000)
    libgmp.so.10 => /usr/lib/libgmp.so.10 (0x6ec67000)
    libicudata.so.57 => /usr/lib/libicudata.so.57 (0x6d3e9000)
    libvchiq_arm.so => /usr/lib/libvchiq_arm.so (0x6d3e1000)
    libvcos.so => /usr/lib/libvcos.so (0x6d3d8000)
    libdrm.so.2 => /usr/lib/libdrm.so.2 (0x6d3cd000)
    libums_connector_impl.so.1 => /usr/lib/libums_connector_impl.so.1 (0x6d3b8000)

ps で見ると複数のWebAppMgrが動いている。

# ps ax |grep [W]ebAppMgr
  737 ?        SLsl   0:03 /usr/bin/WebAppMgr --application-cache-domain-limit=10485760 --application-cache-size=52428800 --browser-subprocess-path=/usr/bin/WebAppMgr --disable-direct-npapi-requests --disable-extensions --disable-gpu-rasterization --disable-low-res-tiling --disk-cache-size=52428800 --enable-aggressive-release-policy --enable-accelerated-plugin-rendering --accelerated-plugin-rendering-blacklist=device;drmAgent;sound;service --enable-key-event-throttling --enable-threaded-compositing --enable-watchdog --hide-selection-handles --ignore-gpu-blacklist --ignore-netif=p2p --in-process-gpu --max-unused-resource-memory-usage-percentage=0 --network-stable-timeout=3 --noerrdialogs --num-raster-threads=2 --ozone-platform=wayland --remote-debugging-port=9998 --resource-buffer-max-allocation-size=262144 --resource-buffer-size=1048576 --touch-events=disabled --ui-disable-opaque-shader-program --user-data-dir=/var/lib/wam --enable-devtools-experiments --webos-wam --skia-font-cache-size-mb=8 --skia-image-cache-size-mb=80 --skia-background-font-cache-size-kb=512 --gpu-program-cache-size-kb=6144 --watchdog-render-timeout=200 --enable-local-resource-code-cache --disallow-code-cache-from-file-uris-with-query-string --js-flags \
  770 ?        S      0:00 /usr/bin/WebAppMgr --type=zygote --no-sandbox --no-sandbox --webos-wam
  791 ?        Sl     0:00 /usr/bin/WebAppMgr --type=renderer --disable-direct-npapi-requests --disable-low-res-tiling --disallow-code-cache-from-file-uris-with-query-string --enable-aggressive-release-policy --enable-local-resource-code-cache --enable-threaded-compositing --js-flags --no-sandbox --touch-events=disabled --ozone-platform=wayland --network-stable-timeout=3 --webos-wam --enable-watchdog --watchdog-render-timeout=200 --skia-image-cache-size-mb=80 --skia-font-cache-size-mb=8 --skia-background-font-cache-size-kb=512 --primordial-pipe-token=D63B0C7165AE1596A434D9E3EA60C518 --lang --no-sandbox --webos-wam --enable-pinch --num-raster-threads=2 --content-image-texture-target=3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553 --video-image-texture-target=3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553 --mojo-channel-token=5D89B229E5B548C1639C9DA073575C82 --mojo-application-channel-token=D63B0C7165AE1596A434D9E3EA60C518 --channel=737.2.1095503763 --v8-natives-passed-by-fd --v8-snapshot-passed-by-fd

zygote

3つ動いていたWebAppMgrのプロセスのうちのひとつに --type=zygote というオプションがついている。zygote といえばAndroidで使われていたテクニックで、起動を高速化するたけに、初期化処理を済ませたプロセスからforkしていくというもの。同じような技がつかわれているのだろうか?

"zygote" で検索したら、7年前に書いた自分の記事を発見。
http://blog.kmckk.com/archives/3551546.html

ソースコード中のzygoteをさがす。webOS全体は一気にgrepをかけるのは大きすぎるので、なかなかさがすのに苦労した。

WebAppMgr の実行ファイルは build-webos/BUILD/work/raspberrypi3-webos-linux-gnueabi/wam 以下のディレクトリでビルドされるが、ここには"zygote"の文字列は含まれていなかった。どれかのライブラリの中のようだ。

rootfsのバイナリに対してgrep をかける

$ cd build-webos/BUILD/work/raspberrypi3-webos-linux-gnueabi/webos-image/1.0-r3/rootfs
$ grep -r zygote *
etc/init/WebAppMgr.conf:        --in-process-zygote \ "
etc/systemd/system/scripts/webapp-mgr.sh:    --in-process-zygote \ "
Binary file usr/lib/libcbe.so matches

libcbe.so がヒットした。

$ cd build-webos/BUILD/work/raspberrypi3-webos-linux-gnueabi
$ ls */*/image/usr/lib/ > /tmp/t
$ less /tmp/t

これでようやくchromium53/53.0.2785.34-1-r12.10/image/usr/lib/libcbe.soだとわかった。chromium とは。

$ cd chromium53/53.0.2785.34-1-r12.10/git
$ git grep zygote

src/docs/linux_zygote.md というドキュメントを発見。

https://github.com/webosose/chromium53/blob/master/src/docs/linux_zygote.md

A zygote process is one that listens for spawn requests from a master process
and forks itself in response. Generally they are used because forking a process
after some expensive setup has been performed can save time and share extra
memory pages.

  ...

The zygote process is triggered by the `--type=zygote` command line flag, which
causes `ZygoteMain` (in `chrome/browser/zygote_main_linux.cc`) to be run. The
zygote is launched from `chrome/browser/zygote_host_linux.cc`.

おお。まさにzygote。
しかし、ドキュメントをよく読んでみると、zygoteは起動高速化としての効果はそれほどではなくて、browserとrendererのバージョンのミスマッチを防ぐためにこうしているらしい。
なるほど、AndroidのときにはJavaのクラスロードがあったからzygote方式が有利だったけど、Javaでなければそれほどでもないのか。