1.5K Views
July 28, 24
スライド概要
ブロックデバイスのドライバ を実装した後が大変だった話 junyaU 1
今作っているOS ● 対応アーキテクチャ: x64 ● 並列処理は未対応 ● 興味本位でマイクロカーネルに寄せようとしている ● IPCはメッセージパッシングで行っている ※これ以降このスライドでは、IPC = メッセージパッシング とします 3
今回作ったブロックデバイスのドライバ: Virtio-blk ~ Virtio-blkとは ~ ● 仮想ブロックデバイス ● Virtioという準仮想化フレームワークに準拠した準仮想化デバイス ● 今回はvirtio-blk-pci(pciバスを介して接続されるvirtioデバイス) ○ QEMUでの指定: -device virtio-blk-pci,drive=drive-virtio-disk0,id=virtio-disk0 ● 実装 ○ https://github.com/junyaU/uchos/tree/master/kernel/hardware/virtio 4
そもそもVirtioとは ● 仮想化環境で効率的にI/O操作を行うための準仮想化フレームワーク ● ゲストとホストで共有されるメモリ上に配置されるリングバッファを介して、 ハイパーバイザとゲストOSが直接通信を行う ● 完全仮想化と比べて、直接通信により多くのオーバーヘッドを削減できる ○ 高速なI/O操作が可能 ● Virtioデバイスには様々な種類のデバイスがある ○ virtio-net, virtio-balloon, virtio-scsi… ● ここが本題ではないので詳細は割愛します... 5
FSと今回作ったドライバの動作イメージ ● FS(FAT32)とVirtio-blkドライバのプロセスがIPCで連携する ● メッセージの送受信は非同期で行っている ● どちらのプロセスもユーザープロセスであることを想定 6
Messageの構造 ● 具体的なfield ○ type: IPCの種類 ○ sender: 送り主プロセス ○ data: typeに応じたフィールド ● FS⇔blk_device間のやり取りは、 blk_ioフィールドを使用する ● 一つのメッセージで送れるデータ は512byteにしていた 7
ここで問題が... ● メッセージに埋め込めるデータサイズが小さい(512byte) ○ 例えば4KiBのデータを取得しようとするだけで8*2のIPCが発生する ■ ○ ほしいデータのサイズが増えれば増えるほど、IPC回数も比例して増える メッセージに埋め込めるデータ領域を広げればいいのでは? ■ メッセージのサイズ自体が大きくなって、全体的なIPCの効率が低下する ● メモリコピーに時間がかかる ○ 都度、メッセージに送りたいデータをコピーしなければならないので時間がかかる ○ メッセージ内のデータ領域を広げれば広げるほど一回のコピーにかかる時間は長くなる → どうしよう... 8
Out-of-line(OOL) Dataを採用してみた ~ OOL Dataとは ~ ● GNU Mach(マイクロカーネル)で実装されているIPCの最適化技術 ○ 特に大きなデータの転送を効率化する ● メッセージの本体とは別にデータを転送する ○ out-of-line data: メッセージの外部にあるデータ ■ ○ メッセージ内のポインタから参照できる in-line data: メッセージ内に含まれるデータ ● ざっくり言うと、送信元プロセスのデータを送信先プロセスのページテーブ ルに一時的にマッピングする手法 9
OOLの流れ ● メッセージ送信システムコールを実行する ● メッセージに送りたいデータのアドレスとサイズを含める 10
OOLの流れ ● 仮想アドレスとデータサイズから該当するページテーブルエントリを特定 ● 特定されたエントリから対応する物理フレームアドレスを取得する 11
OOLの流れ ● 受信先プロセスのページテーブルから空いているエントリを探す ● ページテーブルエントリと取得した物理フレームをマッピングする 12
OOLの流れ ● マップしたページテーブルエントリの仮想アドレスを求める ● メッセージ内に設定されている(送信元の)仮想アドレスを、上で取得した (送信先の)仮想アドレスで書き換える 13
OOLの流れ ● メッセージを目的のプロセスに送信する ● 受信したプロセスはメッセージ内のアドレスからデータにアクセスできる 14
メリット ● 大きなデータを転送する際のIPC回数を大幅に削減できる ○ 4KiB場合は8 * 2回のIPCが必要 ○ OOLを用いることで1 * 2回のIPCだけで済むように 15
メリット ● メッセージのサイズが小さくなる ○ メモリの使用効率が向上する ○ より高速にIPCできる 16
メリット ● データのコピー回数を大幅に削減できる ● 必要になるまでデータのコピーを遅延することができる(読み取り だけならコピーの必要無し) 17
物理フレームと送信先の仮想アドレスをマップする部分 ● ここで書き換えたメッセージ内のアドレスを送信先プロセスが参照 することで、データを読み取ることができる 18
デメリット・懸念点 ● 転送するデータが小さい場合は逆効果になる可能性がある ○ 小さいデータをOOL dataを用いて転送する場合、メッセージと して転送する場合よりもコストがかかってしまう場合がある ○ OOLのオーバーヘッドがOOL化によって得られる利点を上回る 場合は、使用を検討する必要あり → データサイズなどに応じて従来のIPC方式とOOL方式を使い分けるの がよさそう? 19
デメリット・懸念点 ● メモリ管理が複雑になる ○ データ提供元のプロセスでは、メモリの解放タイミングがわから ない ○ データを受信したプロセスは、データの使用後に明示的にデータ 提供元プロセスにdealloc用のIPCを行う必要がある ○ ページテーブルのマッピングも片づけておく必要がある 20
ページテーブルの片づけ ● OOLの際にマッピングしたページをクリアしておく ● deallocのIPCが呼ばれたときにカーネル側で実行する 21
全体(IPC部分) ● OOL用のデータがセットされていれば、メッセージを送信する前にOOLの セットアップを行いメッセージ内の仮想アドレス書き換え ● deallocのIPCなら、メッセージを送信する前にマッピングを片づけておく 22
まとめ ● メッセージパッシングにおける、大きなデータの転送手段として Out-of-line(OOL) Dataを実装した ● 用法・用量を守って使えば便利な技術だなと思った ● もっと良い方法などあれば是非教えていただきたいです...! ● ご清聴ありがとうございました! 23
参考 ● Memory - The GNU Mach Reference Manual ● The GNU Mach Reference Manual: Inter Process Communication 24