私たちのソリューションが内部にあるものを示します。 開発チームが解決したタスク、遭遇した困難をどのように克服したか、どのような結果が達成されたかを説明します。 この記事は2つの部分で構成されています。 1つ目は、既存のAndroid用仮想化ソリューションの簡単な概要、ソリューションアーキテクチャのわかりやすい図、すべてがどのように機能するかの短いビデオです。
はじめに:なぜこれがすべて必要なのですか?
従業員が最も便利なハードウェアで作業することを許可されている場合、Bring Your Own Device(またはBYOD)の概念は両刃の剣です。 一方では、ユーザーが自宅で使用するのに慣れているものをサービスで使用するのが便利です。 これにより、理論的には労働生産性が向上します。 一方、BYODは、システム管理者とITディレクターに頭痛の種を追加します。これは、現在スマートフォンでスピンしている企業アプリケーションとデータを保護する問題を何らかの形で解決せざるを得ません。 主な落とし穴の1つは、ユーザーの行動です。 多くの場合、ユーザーはサードパーティソフトウェアのデモのダウンロードとインストールの禁止を無視しますが、そのようなアプリケーションにはウイルスや「トロイの木馬」が隠されている場合があります。
この種の脅威から身を守るための明らかな方法は、信頼できないソフトウェア用の特別なサンドボックスを作成することです。 または、逆に、企業ソフトウェアおよびビジネスデータ用の「サンドボックス」を作成します。 両方のアプローチは、慎重に実装する必要があります。つまり、従業員の個人情報(SMS、パーティーからの写真など)を侵害することはありません。 このような「サンドボックス」は、ソフトウェア開発およびテスト業界で頻繁に見られ、仮想化を使用して作成されます。 同様のことをすることにしましたが、スマートフォンで行いました。
アナログを探しています
技術的な詳細を説明する前に、既存の仮想化ソリューションとテクノロジーの動物園全体を検討してください。 これは、当社のテクノロジーの実装にどのような特定のアプローチが興味があるかを理解するために必要です。 モバイルデバイスを仮想化する最初の既知の試みは2008年に開始され、これまでのところいくつかの成功したアプローチとプロジェクトがあります。 もちろん、最も成熟した実行可能なアプローチを検討しました。 それらはすべて、図の1つに明確にするために集められており、それぞれがいくつかの単語に分かれています。
Cellsは、Androidプラットフォーム向けのコンテナ仮想化技術を作成した最初のプロジェクトです。 (コンテナーとは何か、コンテナーを使用して仮想化するのにAndroidが最も便利な理由については、後ほど説明します。)このテクノロジーは、同時に動作するAndroid環境から入力デバイス、グラフィックアクセラレーター、セルラーモジュール、ネットワークデバイスへの同時アクセスを提供し、コンテナーアクセスをそれぞれに制限することもできますシステムデバイス。 測定によると、コンピューティングリソースに対するこのテクノロジーの要件は、デバイスのコンポーネントのバッテリー消費量と同様に無視できる程度です。
VMware Horizon Mobileは、抽象マシンのハードウェアを仮想化する本格的な2番目のタイプのハイパーバイザーです。 プロジェクト用にAndroidパッチを備えたLinuxカーネルが作成され、その上にVMwareによって作成されたAndroidユーザー環境が起動されます。 ハイパーバイザーは、ハードウェア仮想化の拡張機能を持たない一般的なタイプのARMプロセッサー上で実行され、ホスト(メイン)OSのプロセスです。たとえば、Androidデバイスにネイティブのオペレーティングシステムなどです。 明らかに、この場合、すべてのハードウェアの仮想化には多くのコンピューティングリソースが必要です。 しかし、さらに重要なことは、複数のハイパーバイザーを起動すると、バッテリーが急速に「ドロップアウト」することです。 30分で放電するタブレットは必要ありません。 さらに、VMwareのアプローチは、Cellsのアプローチよりも実装が非常に困難であると思われました。
TrustDroidは、信頼ドメインに基づいたAndroidプラットフォーム用のプロトタイプアプリケーション分離システムです。 各アプリケーション(標準のAndroidアプリケーションを含む)にはドメインが割り当てられます。 異なるドメインのアプリケーションは相互にやり取りできず、他のドメインのアプリケーションによって公開されたデータを操作できません。 TrustDroidは、ハードウェアまたはユーザー空間の仮想化を使用しません。 ドメインポリシーをサポートするために、カーネルおよび標準のAndroidシステムアプリケーションに変更が加えられています。 このシステムは、以前の2つのシステムと比較して、リソースに対する要求が最も厳しいものです。
BYODスクリプトとサンドボックスの実装は異なります。CellsとVMwareの場合、ポリシーはAndroidユーザー環境のレベルで構成されます。 TrustDroidを使用する場合、ユーザーは各アプリケーションのポリシーとドメインを手動で構成する必要があります。 複数のユーザー環境が存在する可能性があるため、これはユーザーにとってより複雑で退屈です。 TrustDroidはセキュリティ上問題ありません。 標準のAndroidシステムアプリケーションとOSカーネルが決して侵害されることはないと想定されていますが、 スーパーユーザーの権利を取得したら、それらを置き換えることができます。
欠点は、TrustDroidを大幅に改善することで克服できます。 ただし、TrustDroidはデバイスのセキュリティを確保するという問題のみを解決しますが、ユーザーは異なる環境のデータを分離する能力も重要です。
EmbeddedXENは、XENをARMプラットフォームに移植するためのプロジェクトです。 私の知る限り、プロジェクトはまだ積極的な開発の段階を去っていないため、完全なソリューションとは見なされません。 現在、LinuxカーネルバージョンHTC Desire HDは、Dom0として機能するようにプロジェクトで既に適合されています。
コンテナ仮想化が道を開く
LXCは、Linuxカーネル名前空間インフラストラクチャのアドオンです。 完全に断熱されたコンテナを作成する際に生じるすべての要件を網羅しているわけではありません。 たとえば、LXCはsysfs仮想化メカニズムと仮想端末などの標準デバイスを提供しません。 OpenVZテクノロジーは、完全に分離されたコンテナーを作成するために必要なすべての機能を提供し、ホスティング事業者によって広く使用されています。 したがって、開発者が最初にAndroidで使用されるLinuxカーネルに移植しようとしました。
- OpenVZパッチの現在の実験バージョンはカーネルバージョン2.6.32用ですが、この技術が開発およびテストされたスマートフォンはカーネルバージョン2.6.35を実行します。
- 使用されているコアの1つにOpenVZパッチをパッチしようとすると、1682から166個のファイルにパッチを適用することができませんでした。 さらに、パッチは34のx86固有のファイルを変更します。
2.6.35カーネルへの非常に多くの変更の移植は、過度に思えました。 しかし、OpenVZを放棄すると、sysfs仮想化の既成のソリューションが失われました。新しい仮想環境を作成するときに、OpenVZはルートユーザー環境のシステムオブジェクト(kobject)のツリーをコピーするため、追加の作業が必要です。
そのため、標準のLXC Linuxコンテナとカーネルインフラストラクチャ全体を使用することが決定されました。これは、名前空間の実装とリソースグループの差別化を担当します。
この図は、ソリューションのアーキテクチャを示しています。
- 制御盤 GUIからLXC; コンテナを管理できます(アクティブなコンテナの起動、停止、切り替え)。
- 図のカーネルスーパーバイザー-AndContスーパーバイザー。 ドライバの仮想状態を初期化し、コンテナが開始する瞬間をキャプチャし、コンテナ間の切り替えを実装します。
- コンテナ間メカニズム(ICC)。 Netlinkに基づくコンテナ間の通信手段。アプリケーションネットワークプロトコルのチェックをバイパスし、共有メモリに基づきます。
- 入力マネージャー。 並行して動作するAndroid入力デバイスを共有するために必要です。
- 仮想フレームバッファードライバー。 デバイス画面を同時に使用する機能を提供します。
- GPUドライバー。 GPUをすべてのコンテナで同時に使用する機能を実装します。
- バインダー。 Android Open Source Project(AOSP)の一部として作成されたIPCドライバー。
- アラーム クロックへのインターフェース。
- 無線インターフェース制御メカニズム(Radio Interface Layer、RIL)のプロキシサーバー。 複数のAndroidコンテナがモバイルネットワークへのアクセスを共有できるようにします。
- RILプロキシクライアント。 コンテナ内のアプリケーションからテレフォニーサービスへの要求を受け入れ、RILプロキシサーバーに渡します。
- プロキシクライアントオーディオ。 コンテナのオーディオストリームの制御を取得し、それらをオーディオプロキシに渡します。
- プロキシサーバーのオーディオ。 コンテナのサウンドストリームを再現します。
- 補助コンテナ。 ゲストAndroidから削除されたさまざまな理由で、システムデーモンとAndroidライブラリを実行するように設計されています。
コンテナ管理メカニズム
- CAP_SYS_BOOTフラグは無効になっています。これは、Dalvik仮想Javaマシンの初期化時に使用されるシステムを再起動する機能を担います。
- lxc_startの標準以外の開いているファイル記述子のチェックは省略されます。
- USB経由でスマートフォンにアクセスするために使用されるadbdデーモンからのファイル記述子のリークにつながるバグを修正しました。
- initプロセスを開始する前に新しいコンテナを起動するための通知がカーネルレベルのスーパーバイザーに追加されました。
バインダー
バインダーカーネルドライバーは、AOSPプロジェクトの一部として開発されたIPCエンジンです。 標準のIPCとは異なるオリジナルの存在は完全には明らかではありませんが、バインダー実装の詳細は、いくつかの仮想Android環境を起動する際の障害の1つでした。 問題は次のとおりでした。 このドライバーには、ioctlシステムコールを使用して値を設定できる静的変数があります。 このシステムコールは、Androidの初期化プロセス中に起動されるservicemanagerプログラムによって行われます。 バインダードライバーは、これらの変数が初期化されているかどうかを確認し、初期化されている場合は、servicemanagerプログラムの終了につながるエラーを返します。このプログラムはAndroidの動作に必要なため、Androidの初期化も停止します。
したがって、各コンテナに対して上記の変数のインスタンスを作成し、ioctl()システムコールが行われたコンテキスト内のコンテナに属する仮想状態インスタンスにアクセスする必要がありました。
周辺仮想化
Android仮想化の大きな課題は、周辺機器の仮想化とデータストリームの多重化です。 ほとんどすべての場所で、状態の仮想化と呼ばれる同じアプローチを使用しました。
Androidは、周辺機器のみを使用すると想定しています。 これらのデバイスのドライバーは、多くの場合、1つのOSのみが使用するという前提で記述されています。 周辺機器、ドライバー、Androidソフトウェアスタックの同じデバイスで複数のAndroidを実行すると、重大なエラーが発生します。
したがって、いくつかのAndroidがコンテナで動作するには、すべてのOSが周辺機器を同時に使用する機能を提供する必要があります。
これに必要な主なことは、周辺機器へのAndroidアクセスを制御して、周辺機器が勝手に使用できないようにすることです。
- 物理デバイスは仮想デバイスに置き換えられるため、物理デバイスへのすべてのAndroid要求は仮想デバイスにルーティングされます。
- 仮想デバイスは、物理デバイス上でAndroidリクエストの一部を実行し、たとえば、ポリシーに従って仮想状態を変更します。
- 仮想デバイスには、物理デバイスと同じインターフェースと動作があります。
- インターフェースは、利用可能なすべてのAndroidバージョンと可能な限り互換性がなければなりません。
- インターフェイスは単一で、デバイスへのアクセスのすべてのタスクに使用する必要があります。
次に、グラフィック画面の仮想化がどのように実行されるかを確認します。次の記事では、テレフォニー、サウンド、タッチスクリーンの仮想化について説明します。
ディスプレイ
画面へのコンテナアクセスを共有する必要性は明らかです。 複数のコンテナを起動すると、各コンテナが独自のUIを画面に表示し始めます。 当然、どのコンテナがスクリーンを使用する排他的な権利を持っているかについて同意しない場合、スクリーン上でピクセルとインターフェース要素が混在します。 これを防ぐには、画面を仮想化する必要があります。 物理デバイスを仮想デバイスに置き換える必要があります。
Android Porting Guideによると、 Linux Framebufferなどのドライバーを使用して画面にアクセスし、このドライバーを移植用に実装する必要があります。 Linuxフレームバッファーには、20個の関数で構成されるシンプルなインターフェイスがあり、そのほとんどにデフォルトの実装があります。 ドライバーはユーザー空間から使用されます。
MMU GPUの再プログラミング
GPUは、フレームバッファードライバーに加えて、物理画面にアクセスできます。 非アクティブなオペレーティングシステムが画面にUIを表示しないように、フレームを表示する操作を置き換える必要があります。 実験的なGoogle Nexus SとSamsung Galaxy SIIの場合、スマートフォンの画面がDMAを使用してRAMから表示するためにフレームをコピーすることが判明しました。 フレームバッファードライバーは、表示するフレームが配置されているアドレス(画面メモリ)を画面に伝えます。 したがって、画面にフレームを表示する操作は、デバイスのRAMの特定のアドレスにフレームを記録する操作のように見えます。
RAMの書き込み操作を置き換えるには、誰が実行できるかを確立する必要があります。 グラフィック処理の場合、フレームの記録はGPUまたはCPUで実行できます。 最新のGPUおよびCPUにはMMUが組み込まれています。 非アクティブなAndroidのフレームが画面メモリに記録されないようにするには、MMUのアドレスマッピングを置き換えて、画面メモリに表示される非アクティブなAndroidのアドレスが実際にデバイスのRAMの通常のバッファーを指すようにします。 シャドウバッファーと呼びましょう。
シャドウフレームバッファー
Androidは、タイマーではなく、UIが変化するとレンダリングします。 そのため、アクティブなAndroidを切り替えるときにMMUを画面メモリに単純にリダイレクトすると、アクティブなAndroidは画面上のフレームを再描画せず、その画像は前のアクティブなOSからのものになります。
各Androidのシャドウバッファーを選択した場合、アクティブなOSを切り替えるときに、画面上のフレームを以前のアクティブなAndroidのシャドウバッファーにコピーするだけです。 アクティブになったAndroidを表示するには、そのシャドウバッファーの内容を画面メモリにコピーする必要があります。 ただし、シャドウバッファーは2〜4 MBの物理メモリを使用します。 アクティブなAndroidを切り替えるときにフレームを再描画する機能を使用すると、単一のシャドウバッファーを残して、各Androidのシャドウバッファーの割り当てを取り除くことができます。
この機能は、fb_early_suspendメカニズムによって提供されます。 シャドウバッファは、Androidフレームを保存する場所ではなく、すべての非アクティブOSが画像を書き込む場所になりました。 さらに、MMUの存在により、2〜4 MBのすべてのアドレスを単一のページにマッピングすることにより、シャドウバッファーのサイズを物理メモリの1ページに減らすことができます。
Linux仮想ドライバーフレームバッファー
Linuxフレームバッファードライバーの一般的な使用例は、mmap()システムコールと標準および特別なIOCTLコールを使用して、画面メモリをユーザープロセスのアドレス空間にマップすることです。
標準IOCTLは、カーネルの標準LinuxフレームバッファーIOCTLプロセッサによって処理されます。 特別なIOCTLには非標準のセマンティクスがあり、物理Linuxフレームバッファードライバーによってのみ処理できます。 物理Linuxフレームバッファーが仮想に変更されたため、mmap()およびIOCTLは仮想Linuxフレームバッファードライバーで呼び出されます。
すべてのmmap()呼び出しは、物理Linuxフレームバッファードライバーを使用せずに仮想Linuxフレームバッファードライバーで完全に処理されます。 このシステムコールのセマンティクスは標準です。 アクティブなAndroidプロセスはmmap()を呼び出して画面メモリにアクセスします。 mmap()を呼び出すときの非アクティブなAndroidプロセスは、画面メモリの代わりにシャドウバッファーにアクセスします。 実行中のすべてのAndroidについて、Linuxフレームバッファードライバーの仮想状態が作成されます。 アクティブなAndroidの場合、仮想Linuxフレームバッファードライバーへのすべての呼び出しはすぐに物理Linuxフレームバッファードライバーにリダイレクトされ、物理Linuxフレームバッファードライバーの状態が変更されます。 非アクティブなAndroidの場合、標準IOCTLは仮想Linuxフレームバッファーの状態を変更します。 非アクティブなAndroidの非標準IOCTLはエラーを返します。 Google Nexus SおよびSamsung Galaxy SIIデバイスでは、それで十分でした。
中間結論
Linuxコンテナー上に構築されたAndroid仮想化テクノロジーは、いくつかのスマートフォンモデルで動作することが実証されています。仮想化された各携帯電話のように、音声のミキシングと着信メッセージおよび着信の受信と同時に、アプリケーションの同時実行を実現することができました。たとえば、デモスクリプトは、Andgy Birdsを同時に再生し、異なるコンテナで音楽を再生することを示しています。これは、誰かが見なかった場合に起こる方法です。
音声、テレフォニー、ユーザー入力の仮想化がどのように実装されたかについて- 次の記事で。