Android Runtime Environment Setup Process

本文详细介绍了Android系统启动过程,从init脚本执行后的环境构建,到Native System Service的启动,特别是Zygote服务的角色。Zygote作为所有Java程序的始祖,其启动涉及AndroidRuntime的构造、Dalvik VM创建以及Android Java程序的执行。文章深入探讨了Zygote如何解析参数、创建Dalvik VM并启动系统服务,以及如何通过Zygote启动system_server和systemUI进程,最后概述了其他Java程序的启动方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Copyright:http://blog.youkuaiyun.com/myzhzygh/article/details/7721857


1Introduction

在文档“Android boot and init”中我们已经研究了Android系统的引导和加载过程。本章描述了在Kernel启动完成之后,Android系统执行了根文件系统目录下的init脚本,通过init脚本建立Android系统最初运行的环境。可以看出在这篇文章中,我们更多的侧重于内核启动和init脚本所完成的功能。而在本文中,我们将更多的讨论系统init脚本执行完之后,Android系统是如何完成后续启动过程,包括虚拟机创建,系统服务加载,系统应用程序启动等内容。

Android系统是基于Linux kernel的,抛开Linux kernel启动的过程,从另一个角度,我们可以认为Android的启动过程是从进程init开始的,也就是init脚本执行完成之后第一个执行的程序,所以它是后续所有进程的祖先进程。

2Native System Service

如果说init程序之前的操作是在为Android系统的启动做准备工作,那么从Android系统的init程序开始,我们就是在真正的创建Android系统运行的环境。在这个过程中,我们要完成文件系统节点的创建,设置系统环境变量和启动相应的系统服务等操作。Android系统提供了灵活的init.rc配置文件,能够实现对这个阶段系统操作进行灵活的配置。在每次系统启动的时候,init程序都会对init.rc配置文件进行解析,完成系统基本参数设置和基本服务的加载。下面我们看看在init.rc文件中所描述的的服务。

init.rc 文件里面的服务有2种, class coreclass main。对 init.rc文件中描述 service 按照 class <name>分类如下:

class core:

 

service ueventd /sbin/ueventd

service console /system/bin/sh

service adbd /sbin/adbd

service servicemanager /system/bin/servicemanager

service vold /system/bin/vold

 

class main:

 

service netd /system/bin/netd

service debuggerd /system/bin/debuggerd

service ril-daemon /system/bin/rild

service surfaceflinger /system/bin/surfaceflinger

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

service drm /system/bin/drmserver

service media /system/bin/mediaserver

service bootanim /system/bin/bootanimation

service dbus /system/bin/dbus-daemon --system --nofork

service bluetoothd /system/bin/bluetoothd -n

service installd /system/bin/installd

service flash_recovery /system/etc/install-recovery.sh

service racoon /system/bin/racoon

service mtpd /system/bin/mtpd

service keystore /system/bin/keystore /data/misc/keystore

service dumpstate /system/bin/dumpstate -s

上面列出了init.rc中描述的所有服务,针对具体的vendor,这些服务并不是都需要启动。在 class core服务启动以后, class main开始启动。下面列出针对Service的一些Options


1:init.rc service options

Options for Service

Description

setenv <name> <value>

在启动服务时设置环境变量

user <username>                    

运行服务之前切换用户

oneshot

如果服务已经存在,将不再启动

class <classname>                             

为服务设置名字,具有相同名字的服务将一起启动或者关闭

socket <name> <type> <perm> [ <user> [ <group> ] ]

创建以<name>命名的 socket,并将该 socket的文件描述符返回给启动的服务

onrestart <command>

在服务重新启动的时候执行<command>

对于init程序及init.rc其它规则我们在这里不再做详细的描述。具体可参考Android init language Spec

3Zygote Service

下面我们将研究Android系统最重要的服务zygote的启动流程。首先我们必须清楚zygote服务在init.rc配置文件中的描述形式:

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

         class main

         socket zygote stream 666

         onrestart write /sys/android_power/request_state wake

         onrestart write /sys/power/state on

         onrestart restart media

         onrestart restart netd

Zygote服务是标志进入 android系统的最重要服务之一,从上面的描述可以看到,服务名字为 zygote,实际的执行体是 ‘/system/bin/app_process’程序;同时zygote服务带有--zygote--start-system-server参数,这些参数对zygote服务的启动具有非常重要的作用。zygote服务相关选项所表示的含义如表1所示:


2zygote service sample

Option

Description

class main

说明service zygote属于main类型的service

socket zygote stream 666

在服务启动之前,需要创建一个命名为zygotesocket,该socket访问权限标示为666.

onrestart write /sys/android_power/request_state wake

该服务重启的时候,需要向电源管理中写入wake参数,电源管理请求为wake

onrestart restart media

该服务重启的时候,需要重新启动media服务

onrestart restart netd

该服务重启的时候,需要重新启动netd服务

从本文之前的内容我们知道,zygote服务只是init程序在系统启动阶段启动的服务之一,具体的说是main类型服务成员之一。但由于Android系统作为特殊的Linux系统,它所有应用程序都是运行在Java语言的基础上,所以为了支持这种特性,Android系统就必须构建支持Java程序运行的Runtime环境。而Zygote服务就是构建Java Runtime环境的起点,换句话说它是所有Java程序的始祖。所以我们有必要详细的研究,最终清楚Android Runtime构建的流程,并了解在这个过程中所进行的其它操作,如2D display环境的初始化等。

Zygote服务的执行实体为 ’/system/bin/app_process’,所以我们以app_process程序为研究的入口点,具体是以app_process程序的main方法为入口点,通过对main方法的代码实现进行宏观的分析,从分析的结果我们得出其实现的主要逻辑功能如下:

1.     构造AndroidRuntime类的实例

AppRuntime runtime;

系统的AndroidRuntime类定义了基本的Android Runtime接口,但AndroidRuntime类作为一个抽象类,不能实例化自己的对象。在app_process程序中定义了AppRuntime, AppRuntime类作为AndroidRuntime类的派生类,继承了AndroidRuntime类的部分接口实现,同时实现了AndroidRuntime类所定义的抽象接口,所以zygote服务的启动,我们首先实例化了一个AppRuntime类的对象,作为Runtime实例。接下来我们分析AppRuntime类和AndroidRuntime类的构造函数,从AppRuntime类的构造函数实现我们知道AppRuntime类在构造函数并没有做什么事,所以我们重点研究了AndroidRuntime类的构造函数。

AndroidRuntime::AndroidRuntime()

{

   SkGraphics::Init();

   // this sets our preference for 16bit images during decode

   // in case the src is opaque and 24bit

   SkImageDecoder::SetDeviceConfig(SkBitmap::kRGB_565_Config);

   // This cache is shared between browser native images, and java "purgeable"

   // bitmaps. This globalpool is for images that do not either use the java

   // heap, or are not backed by ashmem. See BitmapFactory.cpp for the key

   // java call site.

   SkImageRef_GlobalPool::SetRAMBudget(512 * 1024);

   // There is also a global font cache, but its budget is specified in code

   // see SkFontHost_android.cpp

 

   // Pre-allocate enough space to hold a fair number of options.

   mOptions.setCapacity(20);

 

   assert(gCurRuntime == NULL);        // one per process

   gCurRuntime = this;

}

从上面AndroidRuntime类的构造函数实现来看,构造函数最重要的任务就是初始化负责系统2D DisplaySkia库,指定系统默认颜色格式,设置images共享缓冲区的大小。

SkImageDecoder::SetDeviceConfig(SkBitmap::kRGB_565_Config);

SkImageRef_GlobalPool::SetRAMBudget(512 * 1024);

2.     解析init.rc中zygote传递的启动参数,设置Runtime启动参数

while (i < argc) {

       const char* arg = argv[i++];

       if (!parentDir) {

           parentDir = arg;

       } else if (strcmp(arg, "--zygote") == 0) {

           zygote = true;

           niceName = "zygote";

       } else if (strcmp(arg, "--start-system-server") == 0) {

           startSystemServer = true;

       } else if (strcmp(arg, "--application") == 0) {

           application = true;

       } else if (strncmp(arg, "--nice-name=", 12) == 0) {

           niceName = arg + 12;

       } else {

           className = arg;

           break;

        }

}

3.     解析Runtime启动参数,启动Runtime

runtime.start("com.android.internal.os.ZygoteInit", "start-system-server");

在完成Android Runtime对象构造,zygote服务的参数解析之后,系统将调用AndroidRuntime对象的start方法开始建立Java Runtime环境。根据zygote服务的定义, Android Runtime的类型为StartMode::Zygotestart方法接收的参数分别为"com.android.internal.os.ZygoteInit""start-system-server"。下面是start方法的代码实现,用红色斜体标示的区域是我们重点研究的部分:

void AndroidRuntime::start(const char* className, const char* options)

{

   LOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n",

           className != NULL ? className : "(unknown)")

   ...

   /* start the virtual machine */

   //设置 dalvik虚拟机参数,创建并启动虚拟机 JNIEnv* env;

   if (startVm(&mJavaVM, &env) != 0) {

       return;

   }

   onVmCreated(env);

   /*

    * Register android functions.

    */

   if (startReg(env) < 0) {

       LOGE("Unable to register all android natives\n");

       return;

   }

   ...

   /*

    * Start VM.  This thread becomes the main thread of the VM, and will

    * not return until the VM exits.

    */

   //将类名 com.xxx.xxx转换成 com/xxx/xxx

   char* slashClassName = toSlashClassName(className);

   jclass startClass = env->FindClass(slashClassName);

   if (startClass == NULL) {

       LOGE("JavaVM unable to locate class '%s'\n", slashClassName);

       /* keep going */

   } else {

// jni调用 java方法,获取对应类名的 class,然后调用静态 main方法

       jmethodID startMeth = env->GetStaticMethodID(startClass, "main",

           "([Ljava/lang/String;)V");

       if (startMeth == NULL) {

           LOGE("JavaVM unable to find main() in '%s'\n", className);

           /* keep going */

       } else {

           env->CallStaticVoidMethod(startClass, startMeth, strArray);

       }

   }

   free(slashClassName);

   //销毁Java VM

   LOGD("Shutting down VM\n");

   if (mJavaVM->DetachCurrentThread() != JNI_OK)

       LOGW("Warning: unable to detach main thread\n");

   if (mJavaVM->DestroyJavaVM() != 0)

       LOGW("Warning: VM did not shut down cleanly\n");

}

通过分析AndroidRuntime类的start方法实现,start方法实现的逻辑功能主要包含两个部分:创建Android Dalvik VM;执行Android Java 程序,包括启动Java层系统核心服务和系统核心应用程序。

①创建Android Dalvik VM:调用startVm方法创建Dalvik VM,并构建JNI Environment;随后调用startReg方法向Runtime注册系统的所有JNI Native Methods

②执行Android Java程序:调用执行参数className类的main方法。根据传递的参数,最终执行的是"com.android.internal.os.ZygoteInit"类的main方法。

通过对zygote服务启动的分析,我用图1给出了zygote服务启动的整体流程,以及应用程序启动的框架。同时我们通过图2给出了启动过程中各阶段所处的进程空间。接下来我们将结合图1和图2start函数的逻辑功能进行详细的分析。

com/android/os/ZygoteInit作为Runtime的参数,在Java运行环境建立好之后,ZygoteInit是系统运行的第一个Java程序,Runtime调用了ZygoteInit类的main方法,在main方法中,由于app_process启动的时候是带有—start-system-server参数的,在这个时候系统调用了starServerSystem方法,在该方法中,fork一个子进程来处理SystemServer启动请求,在子进程中首先调用RuntimeInit类的zygoteInit方法。

 




4Creating Android Dalvik VM

从图2我们可以看到,在app_process创建AndroidRuntime的实例之后,就会调用start方法。start方法首要任务就是创建Android Dalvik VM

创建Android Dalvik VM主要包含三个方面:创建JavaVM构建JNI Environment,注册Android系统Native JNI Method

创建JavaVM和构建JNI Environment就是分别实现JNIInvokeInterface接口和JNINativeInterface接口中的函数,然后用实现的接口实例初始化JavaVMExt类和JNIEnvExt类中相应的接口指针,完成JavaVMJNI Environment的创建。一个AndroidRuntime包含一个JavaVM实例,一个JavaVM实例理论上可以包含多个JNIEnv实例,但通常一个JavaVM实例只有一个JNIEnv实例,Dalvik也不例外。

在完成JavaVMJNI Enviroment创建之后,为了使虚拟机支持Android系统Java程序的运行,还必须注册Android系统的所有Native JNI Method。所谓Android系统的Native JNI Method,就是Android系统中所有JNI库中实现的导出方法,通过这些方法,Native层向Java Framework层提供服务,支撑整个Android Java Framework层。到此,整个Dalvik VM已创建完成。

5Booting Android Java Program

Start方法完成Android Dalvik VM创建之后,接下来任务就是执行参数指示的Java程序。根据start方法接收的参数,我们将在本地层调用执行ZygoteInit类的main方法,这也是zygote服务启动过程中第一次由本地层调用Java层的方法。一定程度上,从此zygote服务将进入以JAVA程序为主导的运行阶段。接下来我们将从ZygoteInit类的main方法开始分析。值得注意的是,到目前为止我们仍处于zygote服务进程空间,也就是图2中绿色标示的区域。下面是ZygoteInit类的main方法实现代码:

public static void main(String argv[]) {

       try {

           // Start profiling the zygote initialization.

           SamplingProfilerIntegration.start();

           registerZygoteSocket();

           EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,

               SystemClock.uptimeMillis());

            //预加载资源,有 preloadClasses() preloadResources(),加载的开始和结束会被记录在 /system/etc/event-log-tags文件中

           preload();

           EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,

               SystemClock.uptimeMillis());

              

           // Finish profiling the zygote initialization.

           SamplingProfilerIntegration.writeZygoteSnapshot();

 

           // Do an initial gc to clean up after startup

           gc();

 

           // If requested, start system server directly from Zygote

           if (argv.length != 2) {

               throw new RuntimeException(argv[0] + USAGE_STRING);

           }

           if (argv[1].equals("start-system-server")) {

              startSystemServer();

           } else if (!argv[1].equals("")) {

               throw new RuntimeException(argv[0] + USAGE_STRING);

           }

           Log.i(TAG, "Accepting command socket connections");

 

           if (ZYGOTE_FORK_MODE) {

               runForkMode();

           } else {

               runSelectLoopMode();

           }

        

           closeServerSocket();

       } catch (MethodAndArgsCaller caller) {

           caller.run();

       } catch (RuntimeException ex) {

           Log.e(TAG, "Zygote died with exception", ex);

           closeServerSocket();

           throw ex;

       }

   }

接下来我们将对"com.android.internal.os.ZygoteInit"类的main方法中红色标示的的区域按序号顺序进行分析:

①调用registerZygoteSocket方法注册socket server按照init.rc中的描述,在启动zygote服务之前,我们先创建了一个命名为zygotesocket,在zygote socket创建成功之后,会将创建zygote socket的文件描述符存放在ANDROID_SOCKET_zygote环境变量中。这里实际上是将zygote服务与zygote socket进行绑定,是zygote服务作为zygote socket的服务端;

②调用preload预加载系统的类库和资源。这样其他程序启动将不再加载系统资源,只需加载自己程序的资源,这样就达到系统资源在程序之间共享;

③对main参数进行判断,是否有"start-system-server"选项存在。在调用 ZygoteInit main 函数时,已经传入 start-system-server,接下来将调用startSystemServer方法。如下是startSystemServer的代码实现:

   private static boolean startSystemServer()

           throws MethodAndArgsCaller, RuntimeException {

       /* Hardcoded command line to start the system server */

       String args[] = {

           "--setuid=1000",

           "--setgid=1000",

           "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,

                        1010,1018,3001,3002,3003,3006,3007",

           "--capabilities=130104352,130104352",

           "--runtime-init",

           "--nice-name=system_server",

           "com.android.server.SystemServer",

       };

       ZygoteConnection.Arguments parsedArgs = null;

       int pid;

       try {

           parsedArgs = new ZygoteConnection.Arguments(args);

           ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);

           ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

 

           /* Request to fork the system server process */

           pid = Zygote.forkSystemServer(parsedArgs.uid, parsedArgs.gid,

                   parsedArgs.gids, parsedArgs.debugFlags,

                   null, parsedArgs.permittedCapabilities,

                   parsedArgs.effectiveCapabilities);

       } catch (IllegalArgumentException ex) {

           throw new RuntimeException(ex);

       }

       /* For child process */

       if (pid == 0) {

           handleSystemServerProcess(parsedArgs);

       }

       return true;

   }

startSystemServer的目的就是通过调用Zygote类的forkSystemServer方法在zygote服务主进程中派生一个命名为“system_server”的子进程,如图2中黄色标示的区域。从startSystemServer的代码中我们可以看到在system_server子进程创建成功之后,在system_server进程空间中会调用handleSystemServerProcess方法。

   private static void handleSystemServerProcess(

           ZygoteConnection.Arguments parsedArgs)

           throws ZygoteInit.MethodAndArgsCaller {

 

       closeServerSocket();

 

       // set umask to 0077 so new files and directories will default to owner-only permissions.

       FileUtils.setUMask(FileUtils.S_IRWXG | FileUtils.S_IRWXO);

 

       if (parsedArgs.niceName != null) {

           Process.setArgV0(parsedArgs.niceName);

       }

 

       if (parsedArgs.invokeWith != null) {

           WrapperInit.execApplication(parsedArgs.invokeWith,

                   parsedArgs.niceName, parsedArgs.targetSdkVersion,

                   null, parsedArgs.remainingArgs);

       } else {

           /*

            * Pass the remaining arguments to SystemServer.

            */

           RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);

       }

 

       /* should never reach here */

   }

handleSystemServerProcess方法中首先调用closeServerSocket()关闭zygote socket system_server作为zygote服务派生的子进程,继承了父进程的所有资源,包括它打开的文件描述符,因为zygote主进程之前注册了zygote socket,所以system_server子进程也继承了zygote socket资源,但在system_server子进程中并不需要对zygote socket进行监听,所以zygote socket对于system_server子进程并没有什么用途,需要将zygote socket关闭。在这里关闭zygote socket并不是必须的,也不影响system_server子进程,但从ZygoteInit类的main方法角度出发,在这里关闭zygote socket是有必要的,如果在这里不关闭zygote socket,当在子进程中发生RuntimeException时,会有可能产生死锁。

最后调用RuntimeInit.zygoteInit的方法,然后由该方法调用com.android.server.SystemServer类的main方法,但事实并非这样,而只是仅仅抛出了一个MethodAndArgsCaller异常。调用SystemServermain方法的动作最后交给ZygoteInitcatch模块来执行。为什么这样,只是因为system_server派生于zygote进程,继承了zygote的所有资源,包括代码,但在system_server进程中要避免执行try模块中后续的代码,所以通过异常的方式跳过try模块中后续代码,这里是通过异常的方式控制代码的执行流程,是对异常的一种特殊应用。

SystemServer类的mail方法,完成系统的初始化,初始化的过程分为两步init1init2,如图3所示。



 

如下是SystemServermail方法的代码实现:

public class SystemServer {

   ……

   native public static void init1(String[] args);

 

   public static void main(String[] args) {

       if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {

           // If a device's clock is before 1970 (before 0), a lot of

           // APIs crash dealing with negative numbers, notably

           // java.io.File#setLastModified, so instead we fake it and

           // hope that time from cell towers or NTP fixes it

           // shortly.

           Slog.w(TAG, "System clock is before 1970; setting to 1970.");

           SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);

       }

 

       if (SamplingProfilerIntegration.isEnabled()) {

           SamplingProfilerIntegration.start();

           timer = new Timer();

           timer.schedule(new TimerTask() {

               @Override

               public void run() {

                   SamplingProfilerIntegration.writeSnapshot("system_server", null);

               }

           }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);

       }

 

       // Mmmmmm... more memory!

       dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();

 

       // The system server has to run all of the time, so it needs to be

       // as efficient as possible with its memory usage.

       VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);

 

       System.loadLibrary("android_servers");

       init1(args);

   }

 

   public static final void init2() {

       Slog.i(TAG, "Entered the Android system server!");

       Thread thr = new ServerThread();

       thr.setName("android.server.ServerThread");

       thr.start();

   }

}

首先调用init1,完成本地服务的初始化。该方法的Native JNI实现位于libandroid_servers库中,该库通过调用了本地libsystem_server库中的system_init方法实现。在该方法中以线程的形式启动本地Service,例如SensorService线程等,SurfaceFlinger也可以以线程的形式启动。

extern "C" status_t system_init()

{

   LOGI("Entered system_init()");

   sp<ProcessState> proc(ProcessState::self());

   sp<IServiceManager> sm = defaultServiceManager();

   LOGI("ServiceManager: %p\n", sm.get());

   sp<GrimReaper> grim = new GrimReaper();

   sm->asBinder()->linkToDeath(grim, grim.get(), 0);

   char propBuf[PROPERTY_VALUE_MAX];

   property_get("system_init.startsurfaceflinger", propBuf, "1");

   if (strcmp(propBuf, "1") == 0) {

       // Start the SurfaceFlinger

       SurfaceFlinger::instantiate();

   }

   property_get("system_init.startsensorservice", propBuf, "1");

   if (strcmp(propBuf, "1") == 0) {

       // Start the sensor service

       SensorService::instantiate();

   }

   // And now start the Android runtime.  We have to do this bit

   // of nastiness because the Android runtime initialization requires

   // some of the core system services to already be started.

   // All other servers should just start the Android runtime at

   // the beginning of their processes's main(), before calling

   // the init function.

   LOGI("System server: starting Android runtime.\n");

   AndroidRuntime* runtime = AndroidRuntime::getRuntime();

 

   LOGI("System server: starting Android services.\n");

   JNIEnv* env = runtime->getJNIEnv();

   if (env == NULL) {

       return UNKNOWN_ERROR;

   }

   jclass clazz = env->FindClass("com/android/server/SystemServer");

   if (clazz == NULL) {

       return UNKNOWN_ERROR;

   }

   jmethodID methodId = env->GetStaticMethodID(clazz, "init2", "()V");

   if (methodId == NULL) {

       return UNKNOWN_ERROR;

   }

   env->CallStaticVoidMethod(clazz, methodId);

 

   LOGI("System server: entering thread pool.\n");

   ProcessState::self()->startThreadPool();

   IPCThreadState::self()->joinThreadPool();

   LOGI("System server: exiting thread pool.\n");

   return NO_ERROR;

}

根据系统参数,Init1完成本地Service线程的启动之后,在init1方法中会回调Java层的init2方法,启动支持Android Java程序运行的所有上层服务。

init2方法中,在ServerThread线程中启动Android Java层的所有核心服务,每个核心服务以线程的方式为系统提供服务。

启动的所有核心服务见文档Android frameworks service.docSteven Fu

ActivityManagerServicesystem_server进程启动的最重要的服务之一,在ActivityManagerService服务的支持下,我们可以启动系统的应用程序。

如果说system_serverAndroid启动的第一个Java进程,那么systemUI是系统启动的第二个Java进程。从前面分析我们知道,system_server进程的创建是zygote service派生的。而systemUI进程的的创建与system_server的创建有很大的不同。它的创建过程代表了Android系统中一般Java程序的创建过程。下面是system_server中启动systemUI进程的实现:

   static final void startSystemUi(Context context) {

       Intent intent = new Intent();

       intent.setComponent(new ComponentName("com.android.systemui",

                   "com.android.systemui.SystemUIService"));

       Slog.d(TAG, "Starting service: " + intent);

       context.startService(intent);

   }

    ActivityManagerService.self().systemReady(new Runnable() {

           public void run() {

               Slog.i(TAG, "Making services ready");

               startSystemUi(contextF);

               try {

                   if (batteryF != null) batteryF.systemReady();

               } catch (Throwable e) {

                   reportWtf("making Battery Service ready", e);

               }

               try {

                   if (networkManagementF != null) networkManagementF.systemReady();

               } catch (Throwable e) {

                   reportWtf("making Network Managment Service ready", e);

               }

               try {

                   if (networkStatsF != null) networkStatsF.systemReady();

               } catch (Throwable e) {

                   reportWtf("making Network Stats Service ready", e);

               }

               try {

                   if (networkPolicyF != null) networkPolicyF.systemReady();

               } catch (Throwable e) {

                   reportWtf("making Network Policy Service ready", e);

               }

               try {

                   if (connectivityF != null) connectivityF.systemReady();

               } catch (Throwable e) {

                   reportWtf("making Connectivity Service ready", e);

               }

               try {

                   if (dockF != null) dockF.systemReady();

               } catch (Throwable e) {

                   reportWtf("making Dock Service ready", e);

               }

               try {

                   if (usbF != null) usbF.systemReady();

               } catch (Throwable e) {

                   reportWtf("making USB Service ready", e);

               }

               try {

                   if (uiModeF != null) uiModeF.systemReady();

               } catch (Throwable e) {

                   reportWtf("making UI Mode Service ready", e);

               }

               try {

                   if (recognitionF != null) recognitionF.systemReady();

               } catch (Throwable e) {

                   reportWtf("making Recognition Service ready", e);

               }

               Watchdog.getInstance().start();

 

               // It is now okay to let the various system services start their

               // third party code...

 

               try {

                   if (appWidgetF != null) appWidgetF.systemReady(safeMode);

               } catch (Throwable e) {

                   reportWtf("making App Widget Service ready", e);

               }

               try {

                   if (wallpaperF != null) wallpaperF.systemReady();

               } catch (Throwable e) {

                   reportWtf("making Wallpaper Service ready", e);

               }

               try {

                   if (immF != null) immF.systemReady(statusBarF);

               } catch (Throwable e) {

                   reportWtf("making Input Method Service ready", e);

               }

               try {

                   if (locationF != null) locationF.systemReady();

               } catch (Throwable e) {

                   reportWtf("making Location Service ready", e);

               }

               try {

                   if (countryDetectorF != null) countryDetectorF.systemReady();

               } catch (Throwable e) {

                   reportWtf("making Country Detector Service ready", e);

               }

               try {

                   if (throttleF != null) throttleF.systemReady();

               } catch (Throwable e) {

                   reportWtf("making Throttle Service ready", e);

               }

               try {

                   if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemReady();

               } catch (Throwable e) {

                   reportWtf("making Network Time Service ready", e);

               }

               try {

                   if (textServiceManagerServiceF != null) textServiceManagerServiceF.systemReady();

               } catch (Throwable e) {

                   reportWtf("making Text Services Manager Service ready", e);

               }

           }

     });

通过对上的代码进行分析,systemUI进程的创建过程如图4所示:



ServerThread线程最后,通过ActivityManagerServiceSystemReady方法启动systemUI进程。通过在SystemReady Runable 接口的Run方法中调用ActivityManagerService类的startService方法启动systemUI进程。在startService方法中会调用startProcessLocked方法,该方法会调用Process类的start方法创建新的进程。ActivityManagerService通过向之前注册的zygote socket发送创建进程请求。当zygote服务接收到请求之后,会fork新的子进程实例,并返回给ActivityManagerService,最终完成systemUI进程的创建。

   /**

    * Start a new process.

    *

    * <p>If processes are enabled, a new process is created and the

    * static main() function of a <var>processClass</var> is executed there.

    * The process will continue running after this function returns.

    *

    * <p>If processes are not enabled, a new thread in the caller's

    * process is created and main() of <var>processClass</var> called there.

    *

    * <p>The niceName parameter, if not an empty string, is a custom name to

    * give to the process instead of using processClass.  This allows you to

    * make easily identifyable processes even if you are using the same base

    * <var>processClass</var> to start them.

    *

    * @param processClass The class to use as the process's main entry

    *                     point.

    * @param niceName A more readable name to use for the process.

    * @param uid The user-id under which the process will run.

    * @param gid The group-id under which the process will run.

    * @param gids Additional group-ids associated with the process.

    * @param debugFlags Additional flags.

    * @param targetSdkVersion The target SDK version for the app.

    * @param zygoteArgs Additional arguments to supply to the zygote process.

    *

    * @return An object that describes the result of the attempt to start the process.

    * @throws RuntimeException on fatal start failure

    *

    * {@hide}

    */

   public static final ProcessStartResult start(final String processClass,

                                 final String niceName,

                                 int uid, int gid, int[] gids,

                                 int debugFlags, int targetSdkVersion,

                                 String[] zygoteArgs) {

       try {

           return startViaZygote(processClass, niceName, uid, gid, gids,

                   debugFlags, targetSdkVersion, zygoteArgs);

       } catch (ZygoteStartFailedEx ex) {

           Log.e(LOG_TAG,

                   "Starting VM process through Zygote failed");

           throw new RuntimeException(

                   "Starting VM process through Zygote failed", ex);

       }

   }

 

   private static ProcessStartResult startViaZygote(final String processClass,

                                 final String niceName,

                                 final int uid, final int gid,

                                 final int[] gids,

                                 int debugFlags, int targetSdkVersion,

                                 String[] extraArgs)

                                 throws ZygoteStartFailedEx {

           argsForZygote.add("--runtime-init");

           argsForZygote.add("--setuid=" + uid);

           argsForZygote.add("--setgid=" + gid);

           ……

           return zygoteSendArgsAndGetResult(argsForZygote);

}

 

同样在ActivityManagerServiceSystemReady方法最后会调用resumeTopActivityLocked(Launcher, home)方法启动Launcher进程。HOME启动以后,ActivityManagerService finishBooting 方法会发出 Intent.ACTION_BOOT_COMPLETED广播,随后系统会启动其它的Java程序。

调用resumeTopActivityLocked方法的地方有很多,resume activity的时候或者出错的时候,调用一次以后就不再调用。

系统其它Java程序的启动和systemUI的启动过程类似,不同的是,systemUI是在system_server进程空间内,直接调用ActivityManagerService Context的方法启动的;其它一般Java程序的启动一般是在Launcher环境下启动的,需要通过Android系统向应用程序层提供的接口间接获取ActivityManagerService提供的服务,而不是直接直接获取,最后通过ActivityManagerService Java层核心服务完成进程的创建。

zygotesystem_server进程序列。startSystemServer开始我们分析了system_server子进程中进行的逻辑处理,system_server子进程为系统Java进程的创建提供了必要的支持。ZygoteInit类中ZYGOTE_FORK_MODE被赋值为false,所以在zygote启动的主进程中,在fork调用返回之后,主进程中将调用runSelectLoopMode,开始监听之前通过 registerZygoteSocket() 函数调用注册的 zygote socket连接。我们知道在system_server子进程中最终通过抛出 MethodAndArgsCaller异常,跳过try语句块中后续代码的执行,所以system_server子进程中不会执行runSelectLoopMode方法调用,最后在 catch语句块中调用 com.android.server.SystemServer类的main方法。main方法的执行过程在上文中已经描述。

 

### ONNX Runtime GPU Inference Using C++ To perform GPU inference with ONNX Runtime using C++, several components and configurations are necessary to ensure that the environment is set up correctly, including CUDA support and proper linking of libraries. #### Environment Setup For setting up an environment capable of performing GPU-based inference: - Ensure installation of NVIDIA drivers compatible with your hardware. - Install CUDA Toolkit version matching the requirements of ONNX Runtime. For instance, when working under specific versions like CUDA 10.2 as mentioned previously[^3]. - Installation or update of cuDNN library which works alongside CUDA for optimized deep learning operations. - Building ONNX Runtime from source might be required to enable GPU providers such as TensorRT or CUDA depending on needs. This can involve configuring build options specifically enabling these features during compilation[^1]. #### Code Example for Performing GPU Inference Below demonstrates a simplified example illustrating how one could initialize ONNX Runtime session configured for GPU execution in C++. Note this assumes all prerequisites have been met regarding software installations and environmental variables properly set pointing towards installed binaries/libraries paths. ```cpp #include "onnxruntime_cxx_api.h" #include <iostream> #include <vector> int main() { Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "test"); // Specify use of CUDA Execution Provider std::vector<const char*> providers{"CUDAExecutionProvider", "CPUExecutionProvider"}; Ort::SessionOptions so; so.SetIntraOpNumThreads(1); so.AddExecutableModelPath("path_to_your_model.onnx"); Ort::Session session(env, "path_to_your_model.onnx", so); // Set preferred providers (GPU first then fallback CPU) session.DisableFallback(); session.SetProviders(providers); // Prepare input data... // Perform actual inference here... return 0; } ``` This code snippet initializes an `Ort::Env` object representing the global state shared across multiple sessions within the same process. The key part lies in specifying `"CUDAExecutionProvider"` before `"CPUExecutionProvider"` ensuring attempts at utilizing available GPUs over CPUs whenever possible. Additionally disabling fallback prevents automatic switching back to less efficient alternatives should initialization fail unexpectedly. #### Linking Libraries During Compilation When compiling applications intended to leverage ONNX Runtime's capabilities along with OpenCV functionalities, it becomes crucial to link against both sets of libraries accurately. Within project settings concerning linker inputs, adding dependencies explicitly includes but not limited to `opencv_world480.lib`, besides those provided by ONNX Runtime itself[^2]. --related questions-- 1. What considerations must be taken into account while choosing between different execution providers offered by ONNX Runtime? 2. How does one troubleshoot common issues encountered during setup involving CUDA compatibility checks? 3. Can you provide guidance on optimizing performance parameters related to threading inside ORT Session Options? 4. Are there any notable differences observed running models originally trained elsewhere through ONNX format conversion processes?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值