4

私は、 Wagerlabsコード(ドライバー-ユーザークライアント-アプリケーションモデルを使用)にある程度基づいて、ホットプラグSCSIデバイス用のデバイスドライバーkextを作成しましたが、すべてが機能します。残っている唯一の懸念は、特にアプリケーションがクラッシュした場合に、ドライバーが一貫して解放されていないように見えることです。たとえば、デバイスを切断してアプリケーションを閉じた場合でも、kextをアンロードしようとすると、ドライバーとユーザークライアントの未処理のインスタンスがまだ存在します(ドライバーは通常、ユーザークライアントよりも数が多い)。

のようなドライバー関数にログインしていfree()ますが、コンピューターをシャットダウンすると、これらが実行されていることがわかります。そのため、インスタンスは明らかに終了できます。ホストアプリケーションがクラッシュしたり、不適切に終了したり、通常は計画どおりに進まなかったりした場合でも、ドライバーインスタンスが終了して解放されるようにするための「正しい」方法は何ですか?

4

1 に答える 1

5

ユーザークライアントアプリが実行されていないときにユーザークライアントクラスインスタンスがある場合は、リリースするよりも頻繁にユーザークライアントインスタンスを確実に保持します。たとえば、メインドライバクラスのクライアントインスタンスへの保持された参照を保持している場合があります。ユーザークライアントクラスのstop()メソッドで、必ずそのクライアントインスタンスをドライバーから削除してください。

注意すべきもう1つの点は、オーバーライドされたバージョンの組み込みIOServiceメソッドなどからスーパークラス実装を呼び出すようにすることですstop()free()そうしないと、通常、IOキットが不整合な状態になります。

最後に、I / Oキットドライバーの保持リークをデバッグするための便利な手法は、ログバージョンでメソッドをオーバーライドすることにより、保持とリリースを実際にログに記録することです。

void MyClass::taggedRetain(const void* tag) const
{
    OSReportWithBacktrace(
        "MyClass" CLASS_OBJECT_FORMAT_STRING "::taggedRetain(tag=%p)\n", CLASS_OBJECT_FORMAT(this), tag);
    IOService::taggedRetain(tag);
}
void MyClass::taggedRelease(const void * tag) const
{
    OSReportWithBacktrace(
        "MyClass" CLASS_OBJECT_FORMAT_STRING "::taggedRelease(tag=%p)\n", CLASS_OBJECT_FORMAT(this), tag);
    int count = getRetainCount();
    IOService::taggedRelease(tag);
    if (count == 1)
        printf(
            "MyClass::taggedRelease(tag=%p) final done\n", tag);
    else
        printf(
            "MyClass" CLASS_OBJECT_FORMAT_STRING "::taggedRelease(tag=%p) done\n", CLASS_OBJECT_FORMAT(this), tag);
}

このコードのマクロは、ヘッダーで次のように定義されています。

#define CLASS_OBJECT_FORMAT_STRING "[%s@%p:%dx]"
#define CLASS_OBJECT_FORMAT(obj) myClassName(obj), obj, myRefCount(obj)

inline int myRefCount(const OSObject* obj)
{
    return obj ? obj->getRetainCount() : 0;
}

inline const char* myClassName(const OSObject* obj)
{
    if (!obj) return "(null)";
    return obj->getMetaClass()->getClassName();
}
#endif

とは実際の基本的な実装でtaggedRetain()あり、後者をオーバーライドすると、タグ付きバージョン(null以外のタグ付き)を使用するため、OSCollectionsからの保持とリリースは表示されません。taggedRelease()retain()release()

によって生成されるバックトレースは、OSReportWithBacktrace()残念ながら16進ポインターの集まりにすぎませんが、gdbを使用してそれらを検索できます。

いずれの場合も、オブジェクトの保持と解放をログに記録することで、すべての保持を調べて、適切な場所の解放と一致していることを確認できます。サイクルに気をつけろ!

于 2012-11-20T10:44:07.473 に答える