鉴于我在开发iOS App,但是短期内还不够买macbook,所以漫漫黑苹果路。。。。
其中我用的是变色龙引导(源码参见github,这里不放链接了),但是其自带的FileNVRAM.dylib我简直是用不了,因为其是在操作系统的XNU引导早期阶段开始加载到内存中,然后直接介入内核的入口点(这点可以参见源码和一本书叫《深入解析Mac OS X & iOS操作系统》,某宝买的货架书hhhh),导致我的内核缓存没办法用启动速度慢的一B。。。。
我的想法是启动前先加载关机前保存的nvram信息,开机后启动daemon,实时监测保存。
这里我用的是:
/Library/LaunchDaemons/com.springhack.DaemonNVRAM.plist
来恢复保存的信息,
/Library/LaunchAgents/com.springhack.DaemonNVRAM.Agent.plist
用来启动一个内核模块,每隔一段时间监测nvram设备树上的信息,如果有变化就实时写入到磁盘中,如下:
bool DaemonNVRAM::start(IOService *provider){ | |
bool res = super::start(provider); | |
IOLog("DaemonNVRAM::start\n"); | |
// Register Power modes | |
PMinit(); | |
registerPowerDriver(this, sPowerStates, sizeof(sPowerStates)/sizeof(IOPMPowerState)); | |
provider->joinPMtree(this); | |
// Create the command gate. | |
mCommandGate = IOCommandGate::commandGate(this, dispatchCommand); | |
getWorkLoop()->addEventSource(mCommandGate); | |
// Create a timer task | |
mTimer = IOTimerEventSource::timerEventSource(this, timeoutOccurred); | |
if(mTimer) | |
{ | |
getWorkLoop()->addEventSource(mTimer); | |
mTimer->setTimeoutMS(50); // callback isn't being setup right, causes a panic | |
} | |
// We should be root right now... cache this for later. | |
mCtx = vfs_context_current(); | |
//A buffer in case we don't write the same content on disk | |
buffer = new char[10000]; | |
buffer[0] = '\0'; | |
registerService(); | |
return res; | |
} |
其中设置了timeoutOccurred为定时器的触发函数,buffer是为了存储上次放到磁盘中的内容,作为对比,否则会频繁写入磁盘:
void DaemonNVRAM::timeoutOccurred(OSObject *target, IOTimerEventSource* timer){ | |
DaemonNVRAM* self = OSDynamicCast(DaemonNVRAM, target); | |
if(!self) | |
IOLog("DaemonNVRAM: Failed sync to file /Extra/NVRAM/nvram.plist!\n"); | |
else { | |
IOLog("DaemonNVRAM: sync to file /Extra/NVRAM/nvram.plist\n"); | |
self->sync(); | |
} | |
timer->setTimeoutMS(5*1000); //Try sync per 5s | |
} |
其中调用的sync方法就是去比较并同步设置了,具体参见项目: DaemonNVRAM
这只是我个人的解决方案,目前来看运行稳定。写了个脚本install.sh 直接运行
sh install.sh install
就可以安装到 /Extra/NVRAM 下了,并且效果还不错的说。如果你有好方案,记得告诉我。