电源管理之android内核suspend to disk的实现(七)--方案的选择与问题解决

五、实现android系统hibernation的方案分析:

实现方案分析:

 

    方案一: linux标准内核实现

 

    android标准内核的代码是由linux内核演变而来,只要解决android系统独特的wakelock问题,并提供交换分区的支持,就能实现android系统的hibernation。

 

    方案二: tuxonice内核补丁实现


    tuxonice是专门为实现android系统hibernation的补丁,但是由于大部分是支持arm架构的,故代码有部分存在兼容性差的问题,而且补丁本身也存在部分问题,依照网上的例程来看,对于移动设备而言,开机时间时间大约在50+秒。(后面还会介绍该方案的实现。)

 

存储方案分析:

 

      方案一、image存储在SD卡


    能够创建swap分区,支持android系统的hibernation功能;并且sd卡驱动加载靠前,能够完成resume操作。


      方案二、image存储在nand flash


    能够创建swap分区,支持android系统的hibernation功能;但是分区的创建在resume之后,现阶段还不能够resume功能。

    随后,我解决了该项问题,在内核中配置了early_init(Machineselection),让驱动的加载的时间提前了,但是问题又出来了,nand的读取速度并没有SD卡的读取速度快,且读取时超级不稳定,造成后期系统起不来的,需擦出后再烧写才能正常工作。(这就涉及到前面说的驱动加载顺序的调整问题。)


综上所述:

    优先选择在SD卡创建交换分区的linux标准内核实现方案。


六、实现过程中遇到的问题及问题的解决方案:

 

1、在冻结进程过程中由于存在非超时锁进程被终止。

 

     原因分析:Android相比标准的Linux内核,在电源管理中加入了wake lock机制。

      WakeLock在Android的电源管理系统中扮演一个核心的角色.Wake Lock是一种锁的机制,只要有人拿着这个锁,系统就无法进入休眠,可以被用户态程序和内核获得。这个锁可以是有超时的或者是没有超时的,超时的锁会在时间过去以后自动解锁。如果没有锁了或者超时了,内核就会启动休眠的那套机制来进入休眠。

      当进入到suspend_prepare()中以后, 它会给suspend分配一个虚拟终端来输出信 息, 然后广播一个系统要进入suspend的Notify, 关闭掉用户态的helper进程, 然后一次调用suspend_freeze_processes()冻结所有的进程, 这里会保存所有进程 当前的状态, 也许有一些进程会拒绝进入冻结状态, 当有这样的进程存在的时候, 会导致冻结失败,此函数就会放弃冻结进程,并且解冻刚才冻结的所有进程.


     解决方案:在冻结进程前,调用修改过的 wake_unlock(&main_wake_lock);对main锁进行解锁操作,具体操作可以询问,这里就不多讲了。

 

2、在creat image过程中出现内存不足的问题。

 

     原因分析:经检查内存中内存还足够使用,但是会报内存不足的问题,这个问题确实很纠结,找了还长时间。

     在内核中计算NORMAL_ZONE的方法与我们平台的实际情况不符合。根据bootloader传递来的“mem=...”的参数,kernel算出最大和最小的PFN范围,这部分涉及到内核高低端内存的计算与适用平台是否兼容的问题,这个问题对于JZ4780是存在的,其他平台可能兼容。(具体操作请询问)

     解决方案:根本原因在于kernel与君正的内核不兼容的缘故,我们需要调整内核中内存的布局才能解决该问题,添加了NORMALMEM_END宏,定义为256M。

 

3、创建swap分区。

     原因分析:hibernation功能是基于交换分区实现的,主要是将image写到swap分区,予以保存image,但是我们的android使用的存储介质是nand falsh,不存在交换分区,故需要在SD卡或者nand flash上创建是swap分区。

     解决方案:

     busyboxfdisk /dev/block/mmcblk0

     busyboxmkswap /dev/block/mmcblk0p1

     busyboxswapon /dev/block/mmcblk0p1


4、resume问题。

     原因分析:内核文档中“You need to appendresume=/dev/your_swap_partition to kernel command”,我们需要向内核中传递image所在的设备节点。但是又出现了问题,我直接在内核中进行了修改

     解决方案:如果在bootloader中配置resume=swap:/dev/block/mmcblk0p1

    但是问题是不能解决的,在bootloader中配置resume=swap:/dev/block/mmcblk0p4的话,会报找不到signature。不加的话,会报No image found。原因是:do_mounts.c中的name_to_dev_t()函数没有很好的机制处理“/dev/block/mmcblk0p4”这个字符窜,暂时改为”/dev/mmcblk0p4"了,从网上来看可能还存在另一个原因,MMC驱动初始化的时间比较靠后,通过blk_lookup_devt()函数去查找block设备时还没有注册呢。暂时在调用try_to_open_resume_device前加了个1s的延时。


个人观点,有问题请斧正!!

    转载请注明出处:http://blog.csdn.net/wang_zheng_kai


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。