セマフォ+共有メモリを捨て高水準ITCへ:Symbian OS開発の勘所(9)(3/3 ページ)
プリミティブなAPIに固執する態度を改め、必要に応じて高水準のITCを使うことが「車輪の再発明」を廃絶する近道だ
ITCのデザインパターン − 郵便型
一般に通信はコネクションを意識するものとしないもので大別することができます。TCP/IPもクライアントサーバ・フレームワークもコネクション指向という観点からすれば同種の通信です。ではITCの世界にはUDP相当のものはあり得るのでしょうか。コネクションを確立せずに通信ができるのは魅力的なのですが、投げたメッセージを拾うために相手のスレッドが待っていなければならないとしたら、相手がいることが保証されるコネクション指向の方がまだマシです。というわけで、ITCでコネクションレスの通信をするためには相手の不在を許容する仕掛けがもう1枚必要です(注3)。
これらの要求、
- クションレスの通信がしたい
- 相手が在不在にかかわらず通信は成功してほしい
を満たすパターンとして考えられるのが郵便(メール)です。郵便は、
- 出す側:出したいときに好きなように出せる
- 配達人:受取人の在不在にかかわらず郵便受けに投入することで配送完了とすることができる
- 受け取る側:自分の都合に合わせて郵便受けから郵便を受け取って処理できる
という性質を持っており、まさにITC用のコネクションレス通信に適切なパターンです。Symbian OSではこの郵便型のパターンの実装を「メッセージキュー」という機構で提供しています。ほかのOSでもメールボックスやメールスロットという名前で提供されていることがあるので、使ったことがある方にはあまり違和感がないと思います。
図4にあるキューが郵便受けに相当します。キューに対する操作は以下のものが用意されています。
- キューの作成(またはオープン)
- メッセージの送信
- メッセージの受信
- キューの空きスペースが利用可能になるのを待つ
- キューにデータが届くのを待つ
ただし郵便のパターンをナイーブに実現するだけではITC向けには都合の悪いことがあるので、現実の郵便受けと異なるところが何点かあります。まずキューはメッセージ(郵便)の到着順を厳密に保証するという性質を持っています。現実の郵便と違って、プログラムの場合メッセージの到着順は保証してほしいですよね。
それから上記機能の4に現れていますが、郵便受けのサイズが有限であり、かつ飽和する可能性が普通にあるという前提に立っています。PCなどではキューはメモリの限り無限に拡張するというデザインもありなのでしょうが、携帯向けのOSであるSymbian OSでは資源不足をAPIの枠組みの中で普通に扱うようにしています。
最後にメッセージキューの面白い使い方(注4)をご紹介します。メッセージキュー自身は片方向の通信モデルですが、2つ使えば簡単に全二重の通信を行うことができます(スレッド同士でプロトコルを共有しておくことは必要ですが)。通信の初期化に関して、通信相手と状態を同期させながら処理を進めるのは面倒なものです。メッセージキューを介して通信を行うことにより、相手スレッドの起動やセットアップに関する厳密な順序性から解放されることになります。
ITCのデザインパターン − ゼロコピー型
共有メモリの意義とは何でしょうか。
- メモリの寿命が単一プロセスの寿命に拘束されない
- プロセス間でデータを受け渡すときに、コピーコストが発生しない
などがまず思い付きます。どちらも性能が絡みそうなトピックですが、2はメリットの分かりやすさがより直接的ですね。確かにメモリ間のコピーはデータサイズに比例するコストが発生するので、いったん目に付くと気になって仕方がないところではあります。
このコストを嫌い、データのコピーをなくしてしまおうとするパターンをゼロコピー型と名付けましょう。そうすると共有メモリの位置付けは主客が転倒し、
ゼロコピー型のITCパターンを実現する方法
と再定義することができます。詐欺みたいですか? いやいや。
このゼロコピー型のパターン、もちろんですがITCの両側が同じ資源を扱うことを意識するため複雑度が増加し、実行性能も排他の分だけ低下することになります。だからパターンを投入しても割に合う部分を選んで適用する必要があります。クライアントサーバ間のデータ転送も、データ量によってはもちろんそうでしょう(その場合でもコントロールフローはクライアントサーバ・フレームワークに従うことを強く推奨しておきます)。
しかし一般にデータの転送量がよりシビアな部分が存在します。プログラムとデバイスドライバの間のデータ転送です。ところが通常の共有メモリ、グローバルチャンクはユーザープロセスの間でしか共有を行うことができません。もっとはっきりいうと、グローバルチャンクでは物理アドレスを直接扱うDMAの制限にうまく適合させられないため、いったんカーネル側にバッファを割り当て、そこに受けた値をグローバルチャンクにコピーすることを行う作業が必要になります。つまりSymbian OSではゼロコピー型のパターンが最も有効である部分について、改善の手段を提供できていなかったのです。
もっともこれはV9以前の話で、現在ではハードウェア、カーネルスレッド、ユーザースレッドすべてにまたがって共有を行うことができるメモリオブジェクトが提供されています。このオブジェクトを共有チャンクといいます。共有チャンクに対してDMAは直接読み書きを行うことができます。だからユーザープログラムとデバイスドライバが共有チャンクを介してインターフェイスすれば、ゼロコピー型のパターンを実現できることになります。もちろん常に共有チャンクを使え、というわけではなくて、性能上コピーコストがネックになっていることが分かった場合、Symbian OSには選択肢が用意されているのだと理解してください。
今回はITCに関する新機能を紹介するといいつつ、Symbian OSのマルチタスク・ITC関連のまとめ・おさらいも併せて行いました。ITC全体の俯瞰(ふかん)が入ったことで、見知ったプリミティブなAPIに固執するのではなく、必要に応じて高水準ITCを使おうという気分になってもらえたかと思うのですが、どうでしょう? しつこく繰り返しておきますが、生産性の向上は「車輪の再発明」の廃絶からです。原理原則を知っていることと、原理原則ですべてを記述しようとすることはまったく別のことですし、プリミティブの組み合わせで毎回一点物のソフトウェアを構築する態度は改められなければなりません。
さて、長かったこの連載もいよいよ次回で第1部の完結を迎えます。最後のネタはプラットフォームセキュリティというSymbian OSのセキュリティメカニズムです。携帯向けのネイティブソフトウェアがインストール可能になるとき、Symbianではどのようにそれらの安全性を保証するのか。PCとは違うアプローチをご紹介します。(次回に続く)
Copyright © ITmedia, Inc. All Rights Reserved.