CE 5.0では、スレッド内からユーザープロセスのバッファにアクセスを行う場合はSetProcPermissions APIを使用してスレッドのパーミッションを設定する必要があります。ドライバ内のスレッドは、deviceプロセスのスレッドコンテキストで動作しています。ユーザープロセスのバッファへのアクセス権がないため、許可を得るのです。以下にサンプルのソースコードを示します。
// ドライバのIOCTL処理 gPermissions = GetCurrentPermissions(); -------------------------------------------------------------- // ISTなどのドライバ内のスレッド orgPermissions = SetProcPermissions(gPermissions); ユーザープロセスのバッファへのアクセス SetProcPermissions(orgPermissions);
まず、ユーザープロセスからのIOCTLの呼び出し時にパーミッションを取得しておきます。次に、ISTのようなスレッドでユーザープロセス内のバッファにアクセスする前に、取得しておいたパーミッションを設定することでアクセスが可能となります。アクセス終了後はパーミッションを元に戻して後処理を行っておきます。
CE 6.0では、マーシャリングのCeAllocAsynchronousBuffer APIによってパーミッションの取得や設定は必要なくなりました。GetCurrentPermissions API、SetProcPermissions APIは削除されているので、これらのAPIを利用しているドライバは変更が必要になります。
マーシャリングのセクションで「ドライバから非同期アクセスが可能」と説明しましたが、CeAllocAsynchronousBuffer APIはユーザープロセスのバッファをアクセスするためのマッピング情報をコピーすることでアクセスを可能にしているだけで、「バッファの内容をコピーしているわけではない」ことに気を付けてください。ユーザープロセスが何らかの処理を行いバッファの内容を変更した場合は、ドライバも変更されたデータを参照することになるのでタイミングによっては影響を受けます。この辺りには十分な注意が必要です。
また、非同期にデータが更新されていくことをドライバ側も意識する必要があります。より安全に非同期アクセスを行うために、CE 6.0では「セキュアコピー」という機能があります。セキュアコピーを行うため、以下のAPIが新しく提供されています。
CeAllocDuplicateBuffer APIは、カーネル空間内に呼び出し側バッファの内容をコピーする機能です。アクセスチェックの説明で使用した構造体を例にすると、ポインタpBuffからdwSize分のエリアをコピーします。これでドライバはユーザープロセスのエリアに直接アクセスするのではなく、コピーしたエリアに対して参照、更新を行うことが可能になります。同時にユーザープロセスの動作から影響を受けることもなくなるので、より安全なデータアクセスが可能となるわけです。
バッファアクセス終了時には、CeFreeDuplicateBuffer APIを使用してコピーしたエリアのデータをユーザープロセスのエリアに反映します。ユーザープロセスがこのエリアをアクセスする際はドライバ内のデータが反映されていることになります。CeFreeDuplicateBuffer APIが呼び出される前までのバッファアクセスは、ユーザープロセスのエリアには一切反映されません。
CE 5.0のドライバは、ユーザーモードのDLLとして実装します。そのためドライバ内でWin32 APIを使用し、メッセージボックスの表示といったユーザーインターフェイスを実装できます。また、ファイルシステムを利用したファイルアクセスも可能です。何でもドライバでできたので、非常に便利でした。
しかし、CE 6.0のカーネルドライバの実装からはそれができなくなります。ユーザーインターフェイスが必要な場合は、別途ユーザーモードのドライバを実装する必要があります。以下にカーネルモードドライバとユーザーモードドライバの違いをまとめます。
カーネルモードドライバ | ユーザーモードドライバ | |
---|---|---|
ロード位置 | カーネル空間 | ユーザー空間 |
利用可能APIの制限 | カーネルAPIを使用可能 | カーネルAPIは使用できない |
ユーザーインターフェイス | 実装できない | 実装できる |
障害によるOSに与える影響 | 大きい | 小さい |
パフォーマンス | クリティカル | 標準 |
カーネルモード、ユーザーモードのどちらで実装すべきか迷うかもしれません。よりクリティカルな処理を行いたいのであればカーネルモードとして、USBホストのようなバスドライバ、セキュリティや信頼性を重視するドライバはユーザーモードとして実装するとよいかと思います。
CE 6.0におけるドライバ開発では、メモリアクセスに対するケアに特に注意して実装を行う必要があります。一部APIの追加や削除も行われています。ユーザーモード、カーネルモードの選択が必要であり、ドライバの実装形態に合った開発を行うことが求められます。
本稿が皆さまの役に立てば幸いです。
Copyright © ITmedia, Inc. All Rights Reserved.