ピコプロセス(Pico Process)
「ピコプロセス(Pico Process)」は、WSLを構成する基盤の1つです。「ピコプロセス」の構想は、「Drawbridge」プロジェクトが起源となっています。
Drawbridge
「Drawbridge」プロジェクトは、「MSR(Microsoft Research)」で始まったプロジェクトです。Drawbridgeプロジェクトの目標
「Drawbridge」プロジェクトの目標は、隔離した環境でアプリケーションを動作させる軽量な方法を実装することです。隔離した環境とは、アプリケーションがOSに依存している部分を、ホストOSから切り離すことです。
例えば、Windows 10上でXPアプリケーションを動作させることがこれに相当します。
隔離した環境といえば仮想マシン
環境を隔離する標準的な方法は、仮想マシン内でアプリケーションとOSを動作させる方法です。ハードウェアベースの仮想マシンでは、以下の3つの優位性が得られます。
1.安全性の確保
悪意あるアプリケーションが、他のアプリケーションやホストに不正に侵入出来ないようにアプリを隔離し、安全性を確保します。2.永続的な互換性
ホストとアプリケーションは、お互い独自にバージョンアップします。ホストの機能の変更や修正等により、アプリが動作しなくなることがあります。
仮想マシンを利用すれば、ホストの機能が変更されてもアプリケーションとの互換性を維持できます。
3.アプリの継続的な実行
アプリケーションは特定のホストに頼ること無く実行することができます。実行中のアプリは、アプリを起動したコンピューターに縛られること無く、時空を超えてコンピューターからコンピューターへ移動させることができます。
負担が大きい
しかし仮想マシンを動作させるにはホストOSにそれ相応のリソースを要求し、ホストOSにとって大きなコストになります。プロセスベースのコンテナー
「Drawbridge」プロジェクトの狙いは、ホストOS上のユーザーモードアドレス空間内にプロセスを動作させ、動作対象のアプリケーションとOS(ライブラリーOS)をそのプロセス内で完全に動作させることです。この方法は仮想マシンと比較してホストにかかる負担を軽減でき、1つのホスト上でより密度が高いアプリケーションワークロードを実現できます。
加えて、同一の独立性と互換性を確保することができます。
Drawbridgeのピコプロセス(Pico Process)
「Drawbridge」において「ピコプロセス」とは、ユーザーモードのアドレス空間を確保するが、ユーザーモードアドレス空間を管理しないプロセスのことです。「ピコプロセス」にWindowsのサービスは読み込まれません。
「ピコプロセス」はホスト上で作成されるプロセスですが、ホスト上で生成される通常のプロセスよりも小型なプロセスになっています。
プロセスベースのコンテナー
「ピコプロセス」はプロセスベースのコンテナーであり、隔離された環境を提供します。また「ピコプロセス」は、最小限のカーネルAPIが提供されます。
この「ピコプロセス」内でアプリケーションと「ライブラリーOS」が動作します。
カーネルモードドライバーは「ピコプロセス」をサポートし、ホストOSのカーネルとユーザーモードで動作する「ライブラリーOS」を仲介します。
ホストOSでは「ピコプロセス」生成時、仮想アドレス空間は確保しますが、通常のプロセスのような管理は行いません。
仮想マシンのような設計
「ピコプロセス」は、仮想マシンで言うところの仮想マシン本体になります。「ピコプロセス」内で動作しているコードとOS間のABI(Application Binary Interface)は、仮想マシンの設計に倣っています。
すべてのABIの呼び出しは、「セキュリティーモニター」によって機能が提供されます。
「セキュリティーモニター」は、ハイパーバイザーやVMモニターのような役割を担います。
「ピコプロセス」のインターフェースは、高レベルのインターフェースを抽象化しています。
CPUやMMU、デバイスレジスターなど低レベルのハードウェアを抽象化する代わりに、スレッドやプライベートな仮想メモリー、I/Oストリームなど高レベルのインターフェースを抽象化しています。
DrawbridgeのライブラリーOS(library OS)
「Drawbridge」において「ライブラリーOS」とは、アプリケーションワークロードを対象にしたOSです。簡潔に言えばWindowsのサブセット
「ライブラリーOS」には、アプリが必要とするOSの機能(DLL等)が含まれています。「ライブラリーOS」を簡潔に表現すれば、WindowsのサブセットのようなOSです。
Windowsのユーザーモードやカーネルモードで使用されるWindowsのDLL群が「ライブラリーOS」に含まれます。
「ライブラリーOS」は、仮想マシンで言うところのゲストOSに相当します。
ホストOSの修正と新しいスタイルのプロセスが必要に
ホストOSとは異なる実装になっている「ライブラリーOS」をユーザーモードのプロセス内で動作させるため、プロセスのユーザーモードアドレス空間を確保するが、プロセス内部のユーザーモードアドレス空間を管理・関与しないホストOSが必要になりました。「ライブラリーOS」には、すでにアプリが必要とするOSの機能が含まれているため、通常のプロセスの作成過程では、ホストOSの不必要な機能が動作してしまいます。
DrawbridgeのピコプロセスをWindowsへ実装
「Drawbridge」プロジェクトの成果である「ピコプロセス」をWindowsに実装するにあたり、「ピコプロセス」の抽象的な概念を以下の2つのレイヤーに分割しました。- 最小プロセス(Minimal Process)
- ピコプロセス(Pico Process)
注意
「Drawbridge」での実現方針と「Windows」での実現方針は異なります。「Drawbridge」での成果を「Windows」でそのまま実装しているわけではありません。
そのため「ピコプロセス」に加え、「最小プロセス」という概念が登場しています。
同じ表現である「ピコプロセス」も、実装が異なる点に注意してください。
1.最小プロセス(Minimal Process)
「最小プロセス」は、最も基本的なプロセスです。「最小プロセス」として指定されたプロセスは、ホストOSによる通常のプロセス管理を行いません。
「最小プロセス」をWindowsカーネルから見ると、空のユーザーモードのアドレス空間です。
最小プロセス生成時、伝統的なNTプロセスと異なり、Windowsカーネルはユーザーモードアドレス空間には関与せず、プロセスを動作させるためのスレッドを生成しません。
また通常のプロセスで行われる様々なユーザーモードアドレス空間の構築処理を行いません。
2.ピコプロセス(Pico Process)
「ピコプロセス」は、「最小プロセス」にカーネルモードのドライバーである「ピコプロバイダーカーネルモードドライバー(Pico Provider Kernel-mode Driver)」を結びつけたプロセスです。「ピコプロバイダーカーネルモードドライバー」は、空のユーザーモードアドレス空間を管理します。
最小プロセスとピコプロセスの特徴
通常のプロセスと比較した「最小プロセス」と「ピコプロセス」の特徴です。1.ntdll.dllはプロセスにマップされない
ユーザーモードのバイナリーである「ntdll.dll」は、デフォルトでプロセスにマップされません。2.PEBは生成されない
プロセスの管理に使用するPEB(Process Environment Block)は生成されません。3.初期スレッドは生成されない
プロセス生成時、初期スレッド(メインスレッド)を生成しません。4.TEBは自動的に生成されない
「ピコプロセス」内でスレッドが生成されても、スレッドの管理に使用するTEB(Thread Environment Block)は自動的に生成されません。5.共有ユーザーデータセクションはマップされない
共有ユーザーデータセクションは、プロセスにマップされません。共有ユーザーデータセクションとは、すべてのユーザーモードのアドレス空間に読み込み専用でマップされ、システム共通の情報を効果的に検索するために使用されるブロックです。
6.PEB/TEBなしで動作する
従来のプロセスのようにプロセスが常にPEB/TEBを持っている前提で動作する個所は、PEB/TEBなしでもプロセスを扱えるように変更されています。7.カーネルは積極的にプロセスの管理を行わない
Windowsカーネルは、積極的にプロセスの管理を行いません。しかしスレッドのスケジューリングやメモリー管理など、ユーザーが利用したいOSのすべての基盤技術は引き続き提供されます。
なぜ最小プロセスとピコプロセスに分けたのか
「最小プロセス」と「ピコプロセス」を分けた理由は、「ピコプロセス」をサポートする機能を分離した空のプロセスである「最小プロセス」が、ある用途の役に立つだろうと考えたためです。「Windows 10」では、この「最小プロセス」を実際に活用し以下の機能を提供しています。
1.圧縮メモリー
「圧縮メモリー」は、RAM(物理メモリー)により多くのデータを配置するため、未使用のメモリーを圧縮するWindowsの機能です。「圧縮メモリー」により、ページングファイルへ書き込むデータ量やページングファイルから読み込むデータ量も削減できます。
結果、パフォーマンスが改善します。
このWindowsの「圧縮メモリー」機能は、「最小プロセス」のユーザーモードアドレス空間を活用しています。
2.仮想化ベースのセキュリティ
「仮想化ベースのセキュリティ(Visualization based Security / VBS)」は、OSやカーネル、カーネルモードドライバーの改ざんを防ぐため、危険性のあるユーザーモードプロセスのユーザーモードアドレス空間を隔離します。VBSが動作していることをタスクマネージャー等の管理ツールに示すため、「最小プロセス」が作成されます。
ピコプロセスとピコプロバイダーカーネルモードドライバー
「ピコプロセス」は、「ピコプロバイダーカーネルモードドライバー(以下ピコプロバイダー)」が結び付けられた単純な「最小プロセス」です。システムコールと例外
Windowsカーネルは、ユーザーモードの「ピコプロセス」で発生したすべてのシステムコールと例外を、「ピコプロバイダー」に渡します。従って「ピコプロセス」内で動作しているアプリのシステムコールは、「ピコプロバイダー」に渡ります。
この仕組みのおかげで、Windowsが普段提供している機能からシステムを分離させ、ユーザー/カーネル間で異なる振る舞いを実現することができます。
Windowsカーネルとピコプロバイダー
OS起動時の早いタイミングで、カーネルモードドライバーはWindowsカーネルに「ピコプロバイダー」として登録します。この時カーネルとプロバイダーは、「ピコプロバイダー」にとって必要なインターフェース群をお互いに交換します。
例えば「ピコプロセス」で発生したシステムコールと例外は、カーネルから「ピコプロバイダー」に渡されますが、この時カーネルが呼び出す「ピコプロバイダー」の関数ポインター群が登録時にカーネルに渡されます。
カーネルは「ピコプロバイダー」から渡された関数ポインター群を利用して、システムコールや例外発生時に適切な「ピコプロバイダー」の関数を呼び出します。
一方カーネルからは、「ピコプロセス」やスレッドの作成に必要な関数ポインター群が「ピコプロバイダー」に渡されます。
「ピコプロバイダー」は渡された関数ポインター群を利用して、「ピコプロセス」やスレッドを作成します。
「ピコプロバイダー」が「ピコプロセス」に対してどのような概念や振る舞い方を提供しようとも、「ピコプロバイダー」は究極的にはスレッドのスケジューリングやメモリー管理やI/Oなどをサポートするため、Windowsカーネルに頼ることになります。
Windowsカーネルに加えた変更
「WSL」サポートのためにWindowsカーネルに加えた変更点です。1.フォークのサポート改善
Windowsカーネルは、POSIXやSFUアプリケーションサポート時から長い間フォークをサポートしてきました。しかしWin32プログラミングモデルに向けてフォークを提供していませんでした。
「WSL」のサポートにあたり、「WSL」が要求する機能に応えるため、フォークの実装が改善されています。
2.メモリー管理の改善
Windowsは通常、ユーザーモードのアドレス空間を64KiBのチャンクで管理します。「ピコプロセス」サポートのために、1ページ4KiBで管理できるようになりました。
3.ファイル名の大文字・小文字の区別
WindowsカーネルとNTFSは、長い間ファイル名の大文字・小文字を区別する機能を実装しています。しかしこの区別はデフォルトでは無効になっており、Win32プログラミングモデルには提供されていない機能です。
「WSL」をサポートするため、個々のスレッドでファイル名の大文字・小文字の区別を利用できるようになりました。