3

セキュリティ研究として、カスタムIOK​​itドライバーを作成しています。ドライバーは、電源プレーンを介して、依存するドライバーに自身を登録します。(USB サービス)。setPowerState関数が呼び出され、ドライバーが正しくシャットダウンされます。

問題は、ランダムにスリープ ウェイク エラーの問題が発生し、マシンが自動的に再起動することです。実際には、スリープに入った後のマシンのウェイクアップ中にリセットが発生します(明らかに休止状態にしようとしています)

質問は、どうすればデバッグまたは解決できますか? firewire カーネル デバッグを使用して何が起こっているかを確認していますが、デバッガとブレークポイントが原因でスリープ タイミング メカニズムに遅延が生じており、すべてが混乱しています。

この問題に関するインターネットのデータはかなり弱いですが、OSX マシンがクリーンなマシンでスリープ ウェイク エラーを引き起こしているという不満がたくさんあります。

さまざまなマシンとカーネル バージョンでテストしており、持続性があります。

どんな手がかりも役立ちます。

編集:追加のコード

enum
{
    kOffPowerState, kStandbyPowerState, kIdlePowertState, kOnPowerState, kNumPowerStates
};

static IOPMPowerState gPowerStates[kNumPowerStates]   =
{
    //kOffPowerState
    {kIOPMPowerStateVersion1, 0,0,0,0,0,0,0,0,0,0,0},

    //kStandbyPowerState
    {kIOPMPowerStateVersion1, kIOPMPowerOn, kIOPMPowerOn, kIOPMPowerOn, 0,0,0,0,0,0,0,0},

    //kIdlePowerState
    {kIOPMPowerStateVersion1, kIOPMPowerOn, kIOPMPowerOn, kIOPMPowerOn, 0,0,0,0,0,0,0,0},

    //kOnPowerState
    {kIOPMPowerStateVersion1, kIOPMPowerOn | kIOPMDeviceUsable, kIOPMPowerOn, kIOPMPowerOn, 0,0,0,0,0,0,0,0}
};

bool driver::start(IOService* provider)
{
    IOLog("driver::start\n");

    if (IOService::start(provider) == false)
        return false; 

   PMinit();

   provider->joinPMtree(this);    
   makeUsable();
   changePowerStateTo(0);
   registerPowerDriver(this, gPowerStates, kNumPowerStates);
   registerService();
   return true;
}

IOReturn driver::setPowerState (unsigned long whichState, IOService * whatDevice)
{
    IOLog("driver::setPowerState (%lu)\n", whichState);

    if (whichState == 0)
        IOLog("driver: shutdown (%lu)\n", whichState);

    return kIOPMAckImplied;
}
4

1 に答える 1

1

への解放されていない参照IOServiceにより、スリープ シーケンスでデッド ロックが発生しました。

次のコードを使用してIOServiceポインターを取得しました。

mach_timespec time;
time.tv_sec = 0;
time.tv_nsec = 1000;
IOService* service = IOService::waitForService(IOService::serviceMatching(class_name, NULL), &time);
return service; 

両方とも参照カウンターIOService::serviceMatchingIOService::waitForService増やします。

次のサンプル コードに変更します。

OSDictionary *dict = IOService::serviceMatching(class_name, NULL);

if (dict == NULL)
    return NULL;

IOService* service = IOService::waitForMatchingService(dict, 1000);

dict->release();

return service;

IOService::waitForMatchingService 参照カウンターを増加させずOSDictionary、ポインターを解放します。

于 2015-02-18T08:58:17.200 に答える