当前位置: 美高梅集团手机版 > 美高梅集团 > 正文

先放一张自己画的流程图,而下文也将对照时序

时间:2019-09-30 15:31来源:美高梅集团
0.Android的两个世界 Android系统存在两个世界:Java世界和Native(C或者C++的世界)世界,而大部分应用层开发者除了少数时候用到JNI之外,接触到的通常只是Java世界。Android系统基于Linux内
0.Android的两个世界
  • Android系统存在两个世界:Java世界和Native(C或者C++的世界)世界,而大部分应用层开发者除了少数时候用到JNI之外,接触到的通常只是Java世界。Android系统基于Linux内核,最早当然是Native世界。在启动电源将ROM加载到RAM之后,BootLoader启动系统,进入Android内核层。内核启动时,初始化进程管理、内存管理,加载Display,Camera Driver,Binder Driver等相关工作,并创建守护进程。至此即完成底层初始化,进入Native层。

先放一张自己画的流程图

图片 1WechatIMG277.jpeg

Tip

本文主要介绍Android系统重启动到Home启动的过程,下面是本人整理的时序图(由于图片比较大,你们可以保存到本地放大看):

图片 2

Android系统启动流程.jpg

而下文也将对照时序图的顺序进行分析。

首先记住一点Android系统中首先是native的世界,再由native进入到JAVA的世界!

1.init进程
  • init进程是Linux系统用户空间的第一个进程,在系统启动时会首先被启动,其对应的文件为init.c。
  • init进程的主要任务就是解析配置文件,启动zygote进程及属性服务(propertyservice),(属性服务类似于Windows系统的注册表,存储一些key/value的键值对。应用程序可以通过这个属性机制设置属性。当系统重启或应用重启时从中读取数据进行恢复,一般运用于系统应用。此处不作过多讨论)。并且在此之后进入一个死循环,等待处理来自socket和属性服务器的事件。我们重点在zygote的启动。
  • 在init.c的service_start()方法中,调用fork()函数创建一个子线程(fork是Linux创建线程的一种方式),并在此线程中进入到app_process的main函数中。实际上zygote的原名就叫做app_service,只不过在调用的过程中被改名为zygote,原型app_service对应的源文件是App_main.cpp。

Init进程的启动

图片 3

image.png

上图是Linux系统的启动流程,而Android是基于Linux开发的,所以也符合它的启动流程。我们可以看到Init进程是由内核系统fock出来的。该进程的入口文件在
init.cpp#main(/system/core/init/init.cpp)

bool waiting_for_exec = false;
int main(int argc, char** argv) {
    ...
    // 创建一些文件夹,并挂载设备,这些是和 Linux 相关的
    if (is_first_stage) {
        mount();
        mkdir();
    }
    /*解析init.rc配置文件
     *配置文件位于system/core/rootdir/init.rc中
     *在解析配置文件中会启动zygote进程
     */
    init_parse_config_file("/init.rc");
    ...
    while (true) {
        if (!waiting_for_exec) {
            execute_one_command();
            restart_processes();
        }
      ...
    //阻塞 等待事件发生
    int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, timeout));
    }
}

init.cpp的main函数会先去解析init.rc配置文件,我们这里不深入分析,反正解析完配置文件以后,我们会得到一个带启动的进程列表,然后进入死循环执行启动进程,那waiting_for_exec是在什么时候被置为true的呢?其实是在service_start()方法中,下文会分析到,现在我们先略过。
init.cpp#restart_processes

static void restart_processes()
{
    process_needs_restart = 0;
    service_for_each_flags(SVC_RESTARTING,
                           restart_service_if_needed);
}

其中service_for_each_flags的声明在init.h中,实现在init_parse.cpp中:

init.h#service_for_each_flags
void service_for_each_flags(unsigned matchflags,void (*func)(struct service *svc));

init_parse.cpp#service_for_each_flags
void service_for_each_flags(unsigned matchflags,void (*func)(struct service *svc))
{
    struct listnode *node;
    struct service *svc;
    list_for_each(node, &service_list) {
        svc = node_to_item(node, struct service, slist);
        if (svc->flags & matchflags) {
            func(svc);
        }
    }
}

检查service_list中的所有服务,对于带有SVC_RESTARTING标志的服务,则都会调用其相应的restart_service_if_needed。

init.cpp#restart_service_if_needed

//如果有必要的话重启服务
static void restart_service_if_needed(struct service *svc)
{
    time_t next_start_time = svc->time_started + 5;

    if (next_start_time <= gettime()) {
        svc->flags &= (~SVC_RESTARTING);
        //启动服务
        service_start(svc, NULL);
        return;
    }

    if ((next_start_time < process_needs_restart) ||
        (process_needs_restart == 0)) {
        process_needs_restart = next_start_time;
    }
}

init.cpp#service_start

void service_start(struct service *svc, const char *dynamic_args)
{
    ...
    //创建一个新的进程
    pid_t pid = fork();
     ...
    //启动上文中新fork出来的进程
    execve(svc->args[0], (char**) arg_ptrs, (char**) ENV);
}

通过fork和execve我们会进入app_main(zygote)进程。

zygote本身是一个native可执行程序,有init进程根据init.rc里面配置项创建而来。zygote最初名字为app_process。zygote执行程序对应的源代码为App_main.cpp,源代码中通过调用AppRuntime(继承于AndroidRuntime)的start方法继续执行。

2.App_main.cpp
  • App_main.cpp文件的入口为main(),在主方法中调用runtime.start();runtime的类型为APPRuntime,所以zygote的主要功能交给了APPRuntime处理。

阶段总结

图片 4

image.png

AppRuntime主要依次执行以下几个步骤:

3.AppRuntime
  • AppRuntime由AndroidRuntime派生而来,在start()方法中主要做了三件事情:startVm(),startReg()和CallStaticVoidMethod,即创建虚拟机,注册JNI函数,再通过JNI调用ZygoteInit.java的main()函数,由此开创了Android的Java世界。

app_main(zygote)进程的启动

该进程的入口文件位于
app_main.cpp(/frameworks/base/cmds/app_process/app_main.cpp)

int main(int argc, char* const argv[])
{
     ...
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));

   if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        }
    ...
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
       ...
    }
}

当我们的命令中包含--zygote的时候,我们就会调用到ZygoteInit。
AndroidRuntime.cpp#start(D:AndroidFrameworkSourceframeworksbasecorejni)

     ...
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
//如果java虚拟机已经被创建并启动则直接返回
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);

    /*
     * Register android functions.
     */
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android nativesn");
        return;
    }

    ...
    //指明要调用的类,这里涉及到jni调用
    jclass startClass = env->FindClass(slashClassName);
    ...
    //得到com.android.internal.os.ZygoteInit 的main方法的id
    jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
    ...
    env->CallStaticVoidMethod(startClass, startMeth, strArray);
    ...

通过上文的JNI调用我们就进入到Java的世界了
ZygoteInit#main(frameworks/base/core/java/com/android/internal/os/ZygoteInit.java)

//由app_main(zygote)进程通过jni的方式调用
public static void main(String argv[]) {
          ...
          try {
            //注册ZygoteSocket
            registerZygoteSocket(socketName);
          ...
          //预加载类和资源
            preload();
          ...
            if (startSystemServer) {
                //启动SystemServer进程,属于行的进程下文会详细分析
                startSystemServer(abiList, socketName);
            }
            runSelectLoop(abiList); //进入循环模式
            closeServerSocket();
          ...
          } catch (MethodAndArgsCaller caller) {
            caller.run();
          }

}

registerZygoteSocket

private static void registerZygoteSocket(String socketName) {
    if (sServerSocket == null) {
        int fileDesc;
        final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
        try {
            String env = System.getenv(fullSocketName);
            fileDesc = Integer.parseInt(env);
        } catch (RuntimeException ex) {
            ...
        }

        try {
            FileDescriptor fd = new FileDescriptor();
            fd.setInt$(fileDesc); //设置文件描述符
            sServerSocket = new LocalServerSocket(fd); //创建Socket的本地服务端
        } catch (IOException ex) {
            ...
        }
    }
}

preload

//预加载位于/system/etc/preloaded-classes文件中的类
    preloadClasses();
    //预加载资源,包含drawable和color资源
    preloadResources();
    //预加载OpenGL
    preloadOpenGL();
    //通过System.loadLibrary()方法,
    //预加载"android","compiler_rt","jnigraphics"这3个共享库
    preloadSharedLibraries();
    //预加载 文本连接符资源
    preloadTextResources();
    //仅用于zygote进程,用于内存共享的进程
    WebViewFactory.prepareWebViewInZygote();

zygote进程内加载了preload()方法中的所有资源,当需要fork新进程时,采用copy on write技术,如下:

图片 5

image.png

startSystemServer(略过,下文会分析,属于主流程)

runSelectLoop

private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
    ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
    ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
    //sServerSocket是socket通信中的服务端,即zygote进程。保存到fds[0]
    fds.add(sServerSocket.getFileDescriptor());
    peers.add(null);

    while (true) {
        StructPollfd[] pollFds = new StructPollfd[fds.size()];
        for (int i = 0; i < pollFds.length; ++i) {
            pollFds[i] = new StructPollfd();
            pollFds[i].fd = fds.get(i);
            pollFds[i].events = (short) POLLIN;
        }
        try {
             //处理轮询状态,当pollFds有事件到来则往下执行,否则阻塞在这里
            Os.poll(pollFds, -1);
        } catch (ErrnoException ex) {
            ...
        }

        for (int i = pollFds.length - 1; i >= 0; --i) {
            //采用I/O多路复用机制,当接收到客户端发出连接请求 或者数据处理请求到来,则往下执行;
            // 否则进入continue,跳出本次循环。
            if ((pollFds[i].revents & POLLIN) == 0) {
                continue;
            }
            if (i == 0) {
                //即fds[0],代表的是sServerSocket,则意味着有客户端连接请求;
                // 则创建ZygoteConnection对象,并添加到fds。
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                fds.add(newPeer.getFileDesciptor()); //添加到fds.
            } else {
                //i>0,则代表通过socket接收来自对端的数据,并执行相应操作
                boolean done = peers.get(i).runOnce();
                if (done) {
                    peers.remove(i);
                    fds.remove(i); //处理完则从fds中移除该文件描述符
                }
            }
        }
    }
}

Zygote采用高效的I/O多路复用机制,保证在没有客户端连接请求或数据处理时休眠,否则响应客户端的请求。

runOnce

boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {

    String args[];
    Arguments parsedArgs = null;
    FileDescriptor[] descriptors;

    try {
        //读取socket客户端发送过来的参数列表
        args = readArgumentList();
        descriptors = mSocket.getAncillaryFileDescriptors();
    } catch (IOException ex) {
        ...
        return true;
    }
    ...

    try {
        //将binder客户端传递过来的参数,解析成Arguments对象格式
        parsedArgs = new Arguments(args);
        ...
        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
                parsedArgs.appDataDir);
    } catch (Exception e) {
        ...
    }

    try {
        if (pid == 0) {
            //子进程执行
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;
            //进入子进程流程
            handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
            return true;
        } else {
            //父进程执行
            IoUtils.closeQuietly(childPipeFd);
            childPipeFd = null;
            return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
        }
    } finally {
        IoUtils.closeQuietly(childPipeFd);
        IoUtils.closeQuietly(serverPipeFd);
    }
}

(1)创建JAVA虚拟机startVm并设置虚拟机运行参数

4.zygote
  • 在ZygoteInit类的main()内部,进行了4个重要操作:

①建立IPC通信服务端:registerZygoteSocket; zygote及其他系统程序的通信并未使用Binder,而是使用Socket,此方法即是建立这个Socket的服务端。②预加载类和资源:preloadClasses和preloadResources;通过反射原理对系统所用的类和资源进行预加载,缺点是导致了Android系统启动较慢。③启动system_server进程:startSystemServer(); system_server是Java世界的核心,即framework的核心。如果system_server死亡,则zygote将会自杀。 startSystemServer()最终也是通过zygote的分裂而来(最终实现是在native层)。④等待处理请求:runSelectLoopMode();用于处理客户连接和客户请求。

  • 在处理完以上的主要任务后,zygote将暂时退出舞台等待被唤醒执行任务(fork下一个进程),而后面的任务则交给了他分裂的重要进程system_server进行执行;

阶段总结

Zygote启动过程的调用流程图

图片 6

image.png

1.解析init.zygote.rc中的参数,创建AppRuntime并调用AppRuntime.start()方法;
2.调用AndroidRuntime的startVM()方法创建虚拟机,再调用startReg()注册JNI函数;
3.通过JNI方式调用ZygoteInit.main(),第一次进入Java世界;
4.registerZygoteSocket()建立socket通道,zygote作为通信的服务端,用于响应客户端请求;
5.preload()预加载通用类、drawable和color资源、openGL以及共享库以及WebView,用于提高app启动效率;
6.zygote完毕大部分工作,接下来再通过startSystemServer(),fork得力帮手system_server进程,也是上层framework的运行载体。
7.zygote功成身退,调用runSelectLoop(),随时待命,当接收到请求创建新进程请求时立即唤醒并执行相应工作。

最后,介绍给通过cmd命令,来fork新进程来执行类中main方法的方式:(启动后进入RuntimeInit.main)

app_process [可选参数] 命令所在路径 启动的类名 [可选参数]

  (2) 注册JNI函数(JNI分为主动注册和被动注册)

5.system_server
  • system_server的产生是在native层(dalvik_system_Zygote.c中),在创建之后调用handleSystemServerProcess完成自己的使命。期间会先与Binder通信系统建立联系,这样SS就能使用Binder。辗转之后system_server最终调用了Java层的com.android.sever.SystemServer类的main函数。
  • 在SystemServer类的main函数中,分别调用了native层的init1()和Java层的init2创建了一些系统服务,并且把调用线程加入到Binder通信中;init2()启动了ServerThread线程,启动系统的各项服务,如PowerManager,WatchDog,WindowManager,ActivityManager,可谓十分重要。

SystemServer初始化

由上文可知,SystemServer由Zygote fork生成的,改进程名为system_server,该进程承载着framework的核心服务。启动SystemServer起点是调用startSystemServer(),下面是system_server的启动流程:

图片 7

image.png

上图前4步骤(即颜色为紫色的流程)运行在是Zygote进程,从第5步(即颜色为蓝色的流程)ZygoteInit.handleSystemServerProcess开始是运行在新创建的system_server,这是fork机制实现的(fork会返回2次)。
startSystemServer
startSystemServer会进入开启SystemServer进程阶段,下文会详细分析

private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
        ...
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007,3009,3010",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "com.android.server.SystemServer",
        };
          ZygoteConnection.Arguments parsedArgs = null;
    int pid;
    try {
        //用于解析参数,生成目标格式
        parsedArgs = new ZygoteConnection.Arguments(args);
        ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
        ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

        // fork子进程,该进程是system_server进程【见小节2】
        pid = Zygote.forkSystemServer(
                parsedArgs.uid, parsedArgs.gid,
                parsedArgs.gids,
                parsedArgs.debugFlags,
                null,
                parsedArgs.permittedCapabilities,
                parsedArgs.effectiveCapabilities);
    } catch (IllegalArgumentException ex) {
        throw new RuntimeException(ex);
    }
      //进入子进程system_server
    if (pid == 0) {
        if (hasSecondZygote(abiList)) {
            waitForSecondaryZygote(socketName);
        }
        // 完成system_server进程剩余的工作 【见小节5】
        handleSystemServerProcess(parsedArgs);
    }
    return true;
    }

startSystemServer函数主要的作用是准备参数并fork新进程,从上面可以看出system server进程参数信息为uid=1000,gid=1000,进程名为sytem_server,从zygote进程fork新进程后,需要关闭zygote原有的socket。另外,对于有两个zygote进程情况,需等待第2个zygote创建完成。

(3)通过JNI调用,启动JAVA世界的ZygoteInit类的main方法,从此进入JAVA的世界

编辑:美高梅集团 本文来源:先放一张自己画的流程图,而下文也将对照时序

关键词:

  • 上一篇:没有了
  • 下一篇:没有了