鉴于我在开发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 下了,并且效果还不错的说。如果你有好方案,记得告诉我。