作为一项安全研究,我正在编写一个自定义 IOKit 驱动程序。驱动程序通过电源平面向依赖的驱动程序注册。 (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;
}
答案 0 :(得分: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::serviceMatching
和IOService::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
指针。