Use BLCR speed up the startup process of the android

Reprinted: https://blog.csdn.net/shuaiff/article/details/5894646

Abstract : The principle of using blcr android start speed optimized, steps and note that point, to obtain verification start time shorter than 10 seconds on the virtual machine.

Introduction With the google android operating system is widely used in mobile phones, tablet computers and other fields, android's slow start also for many users complain about the shortcomings. Such devices usually small compared to the phone switch, the switching frequency of the tablet relatively frequently in actual use, the boot speed is an important factor affecting customer perception. Android linux kernel is loaded into the boot process, file system mount, zygote and package scanning process starts several major processes. Zygote which took place in large classes and packages loaded two scanning process, as long as the reduction of these two time startup speed will be changed obviously. How to effectively accelerate the launch rate is the number of android technology product manufacturers are interested in. In this paper, a technique to shorten the startup process android public part of the class loader to do presentation, using this method, the actual test to obtain good results in the virtual machine.

Background Zygote heart is in the process android, android responsible for hatching other applications and services, a reason for the slow start-up process that zygote

Need to load during startup advance public class (defined by the document preloaded-classes), which is loaded android designers purposely embedded systems based on linux and characteristics of the design, it was trying to load these classes are removed to speed up boot on the network, this method is contrary to the original intention of the designer is rejected (reference 1). For a single process, if the public use of these classes, the class must be loaded and the corresponding complete initialization, since all subsequent android zygote is the parent process, the process using Class.forName Public class will be loaded into memory and complete static initialization, each sub-process is loaded in advance to avoid the need to call when a copy of a public class (linux copy-on-write characteristics), thereby reducing the memory footprint and subsequent start-up expenses of other programs. The loading process is related to the follow-up performance, it can not simply be skipped. Process is mainly loaded on the memory during the operation, which includes a number of memory allocation release process, because the process requires thousands of class time-consuming operation becomes longer. In practice, since the lower part of the upgrade framework, so these will not be a dynamic public class cut, taking into account these characteristics, the way each check point to complete the direct reduction zygote stage to avoid loading the class frequent class obviously you can improve the speed of operation.

BLCR (BerkeleyLab Checkpoint / Restart) is a check point / restore software applied under linux, it is possible to run applications on the current operating point on the linux saved as a file and can be directly restore the program as needed at a later time state to save time. The software official website: http: //ftg.lbl.gov/checkpoint. Certain restrictions BLCR saving and restoring the program according to its introduction FAQ: Unable to save and restore an open sockets (TCP / IP, Unix domain, etc.) can not be saved and restored 2 Sys V IPC objects. 3 in the parent process has not yet recovered zombie child processes that need attention. Despite some restrictions, as long as attention in the use of these restrictions when using the save and restore point and memory to run the program every time the ability to completely avoid the unnecessary initialization action. Zygote loaded before public class time in addition to heap outside use very little other resources, through careful adjustment / recovery of some state BLCR unrecoverable, it can form a check point to skip class loading to reduce start-up time. BLCR include kernel drivers and libraries in two parts, external applications to achieve the exchange to save and restore applications by linking libraries and kernel drivers. Here are just concrete process blcr for android2.2 in the emulator.

Implementation had said

A software preparation:

blcr-0.8.2

android2.2froyo

android-goldfish-2.6.29

http://sourceforge.net/projects/android-dfb/pthread patch

Compile the kernel and android will not elaborate here, it should be noted there are two points.

1 Note that when compiling the kernel loadable module support was added (Enable loadablemodule support), goldfish default kernel configuration is not supported.

2 requires a bionic android thread library extend extension method is to replace the above-described library file corresponding thread pthread software files.

Two kernel driver modules and applications compiled blcr used directly built android compiler to compile the kernel driver. Compilation process can be successfully compiled by specifying the correct path compiler and kernel path. Generating a kernel loadable module are:

cr_module/kbuild/blcr.ko

blcr_imports / kbuild / blcr_imports.ko

Smooth translation blcr applications require the use of pthread part played extended patch. Patches corresponding to the direct substitution method bionic directory file, and modifications bionic / libc / Android.mk, open switches corresponding to compile, in libc_common_cflags added -DUCLIBC_LINUXTHREAD_OLD_EXTENSTION macro.

Blcr files need to be modified in order to compile and run as normal.

Which documents libcr / cr_libinit.c:

rc = __cri_ksigaction (? signum, (act & ksa: NULL), (oact & oksa: NULL), (_NSIG / 8), & errno?); Changed to:

rc = __cri_ksigaction(signum, (act ?&ksa : NULL), (oact ? &oksa : NULL), (_NSIG/4), &errno);

The reason _NSIG / 8 alteration of _NSIG / 4 is modified in bionic NSIG = 32 defined in the core 64, resulting in kernel / signal.c in rt_sigaction call that returned an error parameter error. Non-prelink the corresponding dynamic library calls dlopen (NULL, RTLD_LAZY) in the android system; (that is, to find their own) will be abnormal, need to shield cr_libinit.c function cri_init of calls to dlopen.

Join Android.mk in blcr project, the following should be noted that several files need to be compiled for the arm instead of the default thumb instructions:. Cr_async.c cr_core.c cr_sig_sync.c cr_cs.c cr_syscall.c, otherwise unable to compile .

 Three zygote join checkpoint support when the system starts zygote service when the first checkpoint file to determine whether there is, if there is called cr_restart load a saved checkpoint files, or follow the normal process of zygote. As the zygote is other android parent process, the limiting factor of many processes that generate / thread has its socket and other checkpoint can not be restored, it will not fit into the checkpoint after the zygote starting point, we choose preloadResources in the back of the main ZygoteInit.java () after completion. This process is time-consuming public class just loaded long and basically did not use a lot of resource constraints. Native android operation has created socket before preload, can be adjusted to the back preloadResources, like adjusted (in italics reorder code section):

CheckPoint cp=newCheckPoint();

try {

   //Start profiling the zygote initialization.

SamplingProfilerIntegration.start();

  preloadClasses();

  preloadResources();

  cp.checkPoint("/data/zygote.blcr");

  registerZygoteSocket();

Wherein c is extended CheckPoint class java call interface, jni by calling library routines checkpoint checkpoint operation, part jni listed below. This section is only a reference template, the product of the process should do more exception handling and rationalization work.

android_blcr_checkpoint.cpp

#defineLOG_TAG "BLCR"

namespaceandroid {

staticint my_callback(void* arg)
{
   int rc;
    LOGV(__FUNCTION__);
    rc = cr_checkpoint(0);
    return 0;
}
staticvoid checkPoint(JNIEnv* env, jobject object,jstring file) {
    LOGV(__FUNCTION__);
    pid_t my_pid;
    int rc,fd;
    struct stat s;
    cr_checkpoint_handle_t my_handle;
    cr_callback_id_t cb_id;
    FILE *f;
    const jchar* str =env->GetStringCritical(file, 0);
    String8 filename;
    if (str) {
        filename = String8(str,env->GetStringLength(file));
        env->ReleaseStringCritical(file,str);
        }
        else {
               LOGE("checkPoint,file nameis null");
                    return;
            }
   LOGI("checkPoint,filename=%s",filename);
   //does the file exist?
    f = fopen(filename, "r");
     if(f==NULL) //create and save checkpointto it.
       {
        my_pid = cr_init();
          if(my_pid<0)
            {
               LOGE("cr_initfailed,return:%d",my_pid);
               return;
            }
        cb_id =cr_register_callback(my_callback, NULL, CR_SIGNAL_CONTEXT);
        if(cb_id < 0)
        {
           LOGV("cr_register_callback() unexpectedly returned %d/n",cb_id);
           return;
        }
       else
       {
          LOGV("cr_register_callback() correctly returned %d/n", cb_id);
       }    

      /* Request a checkpoint of ourself */
     fd =crut_checkpoint_request(&my_handle, filename);
    if (fd < 0)
      {
         LOGE("crut_checkpoint_request() unexpectedly returned 0x%x/n",fd);
         return ;
      }
    rc = stat(filename, &s);
    if (rc) {
       LOGE("stat() unexpectedly returned%d/n", rc);
       return;
    } else {
       LOGV("stat(context.%d) correctlyreturned 0/n", my_pid);
    }
    if (s.st_size == 0) {
       LOGE("context file unexpectedlyempty/n");
       return;
    } else {
       LOGV("context.%d isnon-empty/n", my_pid);
    }
    /* Reap the checkpoint request */
    rc = crut_checkpoint_wait(&my_handle,fd);
    if (rc < 0) {
       LOGE("crut_checkpoint_wait() #1unexpectedly returned 0x%x/n", rc);
       return;
    }    }}

/*
 * JNI registration.
 */
staticJNINativeMethod gMethods[] = {
    /* name, signature, funcPtr */
       {"checkPoint","(Ljava/lang/String;)V", (void *)checkPoint},
}; 
intregister_android_blcr_checkpoint(JNIEnv* env)
 {
    return jniRegisterNativeMethods(env,"android/blcr/CheckPoint",
        gMethods, NELEM(gMethods));
 }
}

Jni order to use the above interfaces, the need to register the registration function frameworks / base / core / jni / AndroidRuntime.cpp, added REG_JNI (register_android_blcr_checkpoint) in gRegJNI [] in. While creating CheckPoint.java file to the java call: 

packageandroid.blcr;
publicclass CheckPoint {
    public CheckPoint() {
    }
    public native void checkPoint(String fileName);
}

Normal start blcr also need to modify init.rc, adjust the way to start the zygote. The revised points including manned blcr kernel drivers:

insmod/system/lib/modules/blcr_imports.ko

insmod/system/lib/modules/blcr.ko

And start blcr services, will

servicezygote /system/bin/app_process -Xzygote /system/bin --zygote--start-system-server

Replace: service zygote / system / bin / quick.sh -Xzygote / system / bin --zygote --start-system-server

Quick.sh script which reads:
 

#!/system/bin/busybox sh
ec()
{
 /system/bin/busybox echo $* >/dev/console;
}
if [ -f /data/zygote.blcr ]; then
  ec"***************load saved zygote********************"
 /system/bin/cr_restart -f /data/zygote.blcr ;
else
  ec"optimised by blcr"
  ec"**************start a new zygote******************"
  ec"you can contact the author through Email:[email protected]"
  ec"this is only an original demon version"
  ec"release pid:$$."
 /system/bin/cr_checkpoint
  ec"release pid:$$."
 /system/bin/cr_checkpoint
  ec"release pid:$$."
 /system/bin/app_process  $*
fi

It should be noted that the purpose of running the above several cr_checkpoint with no parameters to the zygote behind the back of some pid, pid prevent the next checkpoint when it came to a conflict caused by checkpoint failure.

After adding this feature when the system is first started /data/zygote.blcr file is created, due to the need checkpoint, leading to slow more than the normal start-up time. Follow-up as long as the file exists, the system will cross the class load, and thus faster boot.

4 testing and certification

The following table lists the virtual machine to join start-up speed 10 times before and after blcr blcr.

Emulator startup parameters are as follows:

emulator.exe  -kernel zImage -show-kernel -partition-size200 -memory 200 -skindir ./skins -skin WQVGA432 -shell -sysdir ./ -datauserdata.img -ramdisk ramdisk.img -system system.img -sdcard sdcard.img  -sdcard sdcard.img

参考1:http://osdir.com/ml/android-platform/2009-07/msg00276.html

Part android.mk attached file

cat ./libcr/Android.mk
# Copyright 2006 The Android Open Source Project
LOCAL_PATH := $(my-dir) 

include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := libcutils
LOCAL_SHARED_LIBRARIES += libdl
LOCAL_SHARED_LIBRARIES += libc
lib_SOURCES = /
 cr_omit.c 

LOCAL_SRC_FILES:= $(lib_SOURCES)
LOCAL_C_INCLUDES := /
$(KERNEL_HEADERS) /
$(LOCAL_PATH)/../include /
$(LOCAL_PATH)/../    /
      $(LOCAL_PATH)/arch/arm/ 

LOCAL_CFLAGS := -DHAVE_CONFIG_H -DSHUAIWEN
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := libcr_omit
include $(BUILD_SHARED_LIBRARY)

#libcr_run.so
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := libcutils
LOCAL_SHARED_LIBRARIES += libdl
LOCAL_SHARED_LIBRARIES += libc
lib_SOURCES = /
             cr_run.c 
LOCAL_SRC_FILES:= $(lib_SOURCES)
LOCAL_C_INCLUDES := /
$(KERNEL_HEADERS) /
$(LOCAL_PATH)/../include /
$(LOCAL_PATH)/../    /
      $(LOCAL_PATH)/arch/arm/ 
LOCAL_CFLAGS := -DHAVE_CONFIG_H -DSHUAIWEN
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := libcr_run
include $(BUILD_SHARED_LIBRARY) 

#libcr
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := libcutils
LOCAL_SHARED_LIBRARIES += libdl
LOCAL_SHARED_LIBRARIES += libc
lib_SOURCES = /
              cr_async.c.arm /
              cr_trace.c /
              cr_core.c.arm  /
              cr_sig_sync.c.arm /
              cr_cs.c.arm  /
              cr_pthread.c /
              cr_strerror.c  /
              cr_request.c /
              cr_syscall.c.arm /
              cr_omit.c   /
              cr_run.c 

LOCAL_SRC_FILES:= $(lib_SOURCES)
LOCAL_C_INCLUDES := /
$(KERNEL_HEADERS) /
$(LOCAL_PATH)/../include /
$(LOCAL_PATH)/../    /
      $(LOCAL_PATH)/arch/arm/ 

LOCAL_CFLAGS := -DHAVE_CONFIG_H  -DSHUAIWEN -g
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := libcr
include $(BUILD_SHARED_LIBRARY)

cat ./util/cr_restart/Android.mk
LOCAL_PATH := $(my-dir)
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := libcutils
LOCAL_SHARED_LIBRARIES += libdl
LOCAL_SHARED_LIBRARIES += libc
LOCAL_SHARED_LIBRARIES += libcr_run
LOCAL_SHARED_LIBRARIES += libcr
LOCAL_SRC_FILES:=cr_restart.c
LOCAL_C_INCLUDES := /
$(KERNEL_HEADERS) /
$(LOCAL_PATH)/../../include /
      $(LOCAL_PATH)/arch/arm/
LOCAL_MODULE := cr_restart
include $(BUILD_EXECUTABLE) 

cat ./util/cr_restart/Android.mk
LOCAL_PATH := $(my-dir)
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := libcutils
LOCAL_SHARED_LIBRARIES += libdl
LOCAL_SHARED_LIBRARIES += libc
LOCAL_SHARED_LIBRARIES += libcr_run
LOCAL_SHARED_LIBRARIES += libcr
LOCAL_SRC_FILES:=cr_restart.c
LOCAL_C_INCLUDES := /
$(KERNEL_HEADERS) /
$(LOCAL_PATH)/../../include /
      $(LOCAL_PATH)/arch/arm/ 

LOCAL_MODULE := cr_restart
include $(BUILD_EXECUTABLE)

[root@wen blcr-0.8.2]# 
[root@wen blcr-0.8.2]# 
[root@wen blcr-0.8.2]# cat ./util/cr_checkpoint/Android.mk
LOCAL_PATH := $(my-dir) 

include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := libcutils
LOCAL_SHARED_LIBRARIES += libdl
LOCAL_SHARED_LIBRARIES += libc
LOCAL_SHARED_LIBRARIES += libcr_run
LOCAL_SHARED_LIBRARIES += libcr
LOCAL_SRC_FILES:=cr_checkpoint.c
LOCAL_C_INCLUDES := /
$(KERNEL_HEADERS) /
$(LOCAL_PATH)/../../include /
      $(LOCAL_PATH)/arch/arm/
LOCAL_MODULE := cr_checkpoint
include $(BUILD_EXECUTABLE)

Here is crut_util_libcr.c, placed above the same directory. You can also copy itself from blcr out.

/*
 * Berkeley Lab Checkpoint/Restart (BLCR) for Linux is Copyright (c)
 * 2008, The Regents of the University of California, through Lawrence
 * Berkeley National Laboratory (subject to receipt of any required
 * approvals from the U.S. Dept. of Energy).  All rights reserved.
 *
 * Portions may be copyrighted by others, as may be noted in specific
 * copyright notices within specific files.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * $Id: crut_util_libcr.c,v 1.5 2008/12/26 10:50:35 phargrov Exp $
 *
 * Utility functions for BLCR tests (libcr-dependent portions)
 */

#define _LARGEFILE64_SOURCE 1   /* For O_LARGEFILE */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h> 

#include "crut_util.h"
/* checkpoint request/poll wrappers for simpler code */
int
crut_checkpoint_request(cr_checkpoint_handle_t *handle_p, const char *filename) {
    int rc;
    cr_checkpoint_args_t my_args;

    if (filename) {
        /* remove existing context file, if any */
        (void)unlink(filename);
        /* open the context file */
        rc = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, 0600);
    } else {
/* NULL -> /dev/null */
        rc = open("/dev/null", O_WRONLY | O_LARGEFILE);
    }
    if (rc < 0) {
        perror("open");
        return rc;
    }

    cr_initialize_checkpoint_args_t(&my_args);
    my_args.cr_fd = rc; /* still holds the return from open() */
    my_args.cr_scope = CR_SCOPE_PROC; 

    /* issue the request */
    rc = cr_request_checkpoint(&my_args, handle_p);
    if (rc < 0) {
        (void)close(my_args.cr_fd);
        if (filename) (void)unlink(filename);
        perror("cr_request_checkpoint");
        return rc;
    }
 
    return my_args.cr_fd;
}

int
crut_checkpoint_wait(cr_checkpoint_handle_t *handle_p, int fd) {
    int rc, save_err;

    do {
        rc = cr_poll_checkpoint(handle_p, NULL);
        if (rc < 0) {
            if ((rc == CR_POLL_CHKPT_ERR_POST) && (errno == CR_ERESTARTED)) {
                /* restarting -- not an error */
                rc = 1; /* Signify RESTART to caller */
            } else if (errno == EINTR) {
                /* poll was interrupted by a signal -- retry */
                continue;
            } else {
                /* return the error to caller */
                break;
            }
        } else if (rc == 0) {
            fprintf(stderr, "cr_poll_checkpoint returned unexpected 0/n");
            rc = -1;
            goto out;
        } else {
            rc = 0; /* Signify CONTINUE to caller */
        }
    } while (rc < 0);
    save_err = errno;
#if 0 // Nothing in the testsuite needs this, but your APP might want it.
    (void)fsync(fd);
#endif
    (void)close(fd);
    errno = save_err;
out:
    return rc;
}

int
crut_checkpoint_block(const char *filename) {
    cr_checkpoint_handle_t my_handle;
    int ret, fd, save_err;
    fd = crut_checkpoint_request(&my_handle, filename);
    if (fd < 0) return fd;
    ret = crut_checkpoint_wait(&my_handle, fd);
    save_err = errno;
    (void)close(fd);
    errno = save_err;
    return ret;
}

Many people asked about the method of compiling the kernel module, and here I add, a relatively simple method is to create a script, such as call run.sh, reads as follows:

#!/bin/bash
curpath=`pwd`
#rm -rf `find ./ -name Makefile`
export PATH=$PATH:/mydroid/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin
TOOLCHAIN=/mydroid/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin
export ARCH=arm
./configure KCC=$TOOLCHAIN/arm-eabi-gcc  LD=$TOOLCHAIN/arm-eabi-ld --with-linux-src=$curpath/../../kernel-common --with-linux=$curpath/../../kernel-common  host_alias=arm-linux
cd blcr_imports/
make
echo generated kernel module:`ls kbuild/*.ko`
cd ../cr_module/
make
echo generated kernel module:`ls kbuild/*.ko`

Use real columns:

1, BLCR download source, extract
2, CD-0.8.5 blcr /
. 3, mkdir Build
. 4, CD Build
. 5, SU obtain root privileges
. 6, .. / Configure
. 7, the make
. 8, the make the install
. 9, mounted blcr kernel module:
/usr/local/lib/blcr/2.6.32-38-generic/blcr_imports.ko the insmod
the insmod /usr/local/lib/blcr/2.6.32-38-generic/blcr.ko
10, the LD_LIBRARY_PATH = $ Export the LD_LIBRARY_PATH: / usr / local / lib: / usr / local / lib6411, ldconfig

Test program test.c

#include <stdio.h>    
int main(int argc, char *argv[])  
{  
    int result = 0;  
    int i;  
  
    printf("blcr test starting with\n");    
    for (i = 0; i < 100; i++) {  
        result += 1;  
        printf("%d\n", result);  
        sleep(1);  
    }    
    return 0;  
} 

12, compile the program -o the Test test.c gcc
13, program execution ./test cr_run
14, PS -aux get PID test process
15, cr_checkpoint <PID> In this case generate a file in the current directory will context.PID
16, -9 the kill <PID>
17, cr_restart context, PID file found the program will begin execution from where it left off

Guess you like

Origin blog.csdn.net/jinron10/article/details/89313597