请选择 进入手机版 | 继续访问电脑版
点击联系客服
客服QQ:509006671 客服微信:mengfeiseo
查看: 73|回复: 50

android8.1启动过程(6) zygote过程分析2

[复制链接]

1

主题

1

帖子

-7

积分

限制会员

积分
-7
发表于 2021-5-2 23:44:11 | 显示全部楼层 |阅读模式
子部分将继承上一句https://blog  . csdn  . net/we  1 less/article/details/116139142吗?Spm=1001.2014.3001.5501

http://www  . Sina.com/aosp/frameworks/base/core/Java/com/Android/internal/OS/zygots

Void注册表服务器套接字(string  socket  name) {

If  (mServerSocket==null) {

Int  fileDesc

final  string  full  socket  name=Android  _ socket  _ prefix  socket  name;

Try  {

stringenv=system  . getenv(full  socket  name);

FileDesc=integer  . parseint(env);

} catch(运行时执行ex) {

throw  new  runtime  exception(full  socket  name  ' unset  or  invalid  ',ex);

}

Try  {

file  descriptor  FD=new  file  descriptor();

FD  . Setint  $(Filedesc);

mserver  socket=new  local  server  socket(FD);

} catch  (IOException  ex) {

Throw  new  RuntimeException(

error  binding  to  local  socket  ' ' file  desc  ' ',ex);

}

}

}

final  string  full  socket  name=Android  _ socket  _ prefix  socket  name;

[1]连接套接字名称Android  _ socker  _ zygote

stringenv=system  . getenv(full  socket  name);

获取[2]套接字的环境变量值

mserver  socket=new  local  server  socket(FD);

[3]创建服务器端套接字,并将文件运算符作为参数传递。zygote进程启动systemserver进程后,服务器端套接字将等待AMS请求zygote进程来创建新进程

套接字信息此处附上句子3359 www  . cn  blogs.com/zijianlu/archive/2013/04/18/3028090 . html

http://www  . Sina.com/aosp/frameworks/base/core/Java/com/Android/internal/OS/zygots

static  void  preload(timings  tracelog  boottimingstracelog){

Log.d(标签,“Begin  Preload”);

.

PreloadClasses();

.

preload  resources();

.

本机prelo
adAppProcessHALs();
        ...
        preloadOpenGL();
        ...
        preloadSharedLibraries();
        ...
        preloadTextResources();
        ...
        warmUpJcaProviders();
        ...
    }
  【1】预加载位于/system/etc/preloaded-classes文件中的类

  【2】预加载drawble和color的资源信息AOSP/frameworks/base/core/res/res/values/arrays.xml   

           drawble   :    preloaded_drawables

           color    :    preloaded_color_state_lists

  【3】通过JNI调用,预加载底层相关的资源

  【4】预加载OpenGL资源

  【5】预加载共享库:"android","compiler_rt","jnigraphics"

  【6】预加载文本连接符资源

  【7】zygote中,内存共享进程

    通过【1】【2】步骤的预加载可以使继承自zygote的进程预加载系统文件从而使得进程启动更快

启动systemserver  AOSP/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

if (startSystemServer) {
    Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
    // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
    // child (system_server) process.
    if (r != null) {
        r.run();
        return;
    }
}
  【1】forkSystemServer  父进程分支返回null 子进程分支返回  handleSystemServerProcess并返回回去最终调用了run()方法 关于具体systemserver启动会在后面单独开一篇文章去分析到这里只需要知道启动了systemserver就好

  【2】Zygote.forkSystemServer  其内部会调用nativeForkSystemServer方法,这个native方法最终会通过fork()方法创建当前进程的一个子进程  对于fork()方法这里给出一篇文章有兴趣的可以参考看看

  https://www.cnblogs.com/coolgestar02/archive/2011/04/28/2032018.html  总之fork函数最终在父进程的返回值是子进程的pid,而在子进程返回的则是0

private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        ...
            /* 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) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }
            zygoteServer.closeServerSocket();
            return handleSystemServerProcess(parsedArgs);
        }
        return null;
    }
runSelectLoop(abiList)   AOSP/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

Zygote完成了Java的初始工作后,便调用runSelectLoop来让自己无限循环等待。如果收到子孙后台的请求,它便会醒来为他们工作。

Runnable runSelectLoop(String abiList) {
    ...
    fds.add(mServerSocket.getFileDescriptor());
    ...
    while (true) {
        StructPollfd[] pollFds = new StructPollfd[fds.size()];
        for (int i = 0; i = 0; --i) {
            if ((pollFds.revents & POLLIN) == 0) {
                continue;
            }
            if (i == 0) {
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                fds.add(newPeer.getFileDesciptor());
            } else {
                    try {
                        ZygoteConnection connection = peers.get(i);
                        final Runnable command = connection.processOneCommand(this);
                    ...
                        if (connection.isClosedByPeer()) {
                            connection.closeSocket();
                            peers.remove(i);
                            fds.remove(i);
                        }
                    }
                } catch (Exception e) {
                    ...
                }
            }
        }
    }
}
  【1】fds.add(mServerSocket.getFileDescriptor());  fds[0]为mServerSocket,即mServerSocket为位于zygote进程中的socket服务端

  【2】Os.poll(pollFds, -1);  查询轮训状态,当pollFdd有事件到来则往下执行,否则阻塞在这里

  【3】if (i == 0) {  ZygoteConnection newPeer = acceptCommandPeer(abiList);  peers.add(newPeer);  fds.add(newPeer.getFileDesciptor());  

           客户端第一次请求服务端,服务端调用accept与客户端建立连接,客户端在zygote以ZygoteConnection对象表示

  【4】else {   try {   ZygoteConnection connection = peers.get(i);   final Runnable command = connection.processOneCommand(this);   

          经过上个if操作后,客户端与服务端已经建立连接,并开始发送数据  peers.get(index)  取得发送数据客户端的  ZygoteConnection  对象  然后调用  processOneCommand(this)  方法来出具具体请求

          如果  i==0  表示说明服务端socket已经于客户端连接上了  换句话说就是当前zygote进程已经于AMS连接上了

          如果  i!=0  表示AMS向zygote进程发送一个创建应用进程的请求  再调用  processOneCommand(this)  方法fork出一个新的进程

  【5】fds.remove(i);  处理完则从fds中移除该文件描述符

processOneCommand() AOSP/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

在这里fork出一个子进程返回handleChildProc  父进程执行handleParentProc

pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
        parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
        parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
        parsedArgs.appDataDir);
try {
    if (pid == 0) {
        // in child
        zygoteServer.setForkChild();
        zygoteServer.closeServerSocket();
        IoUtils.closeQuietly(serverPipeFd);
        serverPipeFd = null;
        return handleChildProc(parsedArgs, descriptors, childPipeFd);
    } else {
        // In the parent. A pid
回复

使用道具 举报

1

主题

260

帖子

-38

积分

限制会员

积分
-38
发表于 2021-5-2 23:44:15 | 显示全部楼层
不错不错,很好哦
回复

使用道具 举报

2

主题

247

帖子

-18

积分

限制会员

积分
-18
发表于 2021-5-3 06:00:41 | 显示全部楼层
不错不错,楼主您辛苦了。。。
回复

使用道具 举报

1

主题

251

帖子

-35

积分

限制会员

积分
-35
发表于 2021-5-3 06:21:54 | 显示全部楼层
找到好贴不容易,我顶你了,谢了
回复

使用道具 举报

1

主题

262

帖子

-34

积分

限制会员

积分
-34
发表于 2021-5-3 06:42:01 | 显示全部楼层
写的真的很不错
回复

使用道具 举报

0

主题

253

帖子

-41

积分

限制会员

积分
-41
发表于 2021-5-3 07:02:06 | 显示全部楼层
找到好贴不容易,我顶你了,谢了
回复

使用道具 举报

1

主题

241

帖子

-49

积分

限制会员

积分
-49
发表于 2021-5-3 07:22:22 | 显示全部楼层
好帖,来顶下
回复

使用道具 举报

1

主题

265

帖子

-25

积分

限制会员

积分
-25
发表于 2021-5-3 07:42:27 | 显示全部楼层
有竞争才有进步嘛
回复

使用道具 举报

1

主题

223

帖子

-28

积分

限制会员

积分
-28
发表于 2021-5-3 08:02:33 | 显示全部楼层
相当不错,感谢无私分享精神!
回复

使用道具 举报

0

主题

235

帖子

-29

积分

限制会员

积分
-29
发表于 2021-5-3 08:23:12 | 显示全部楼层
沙发!沙发!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|无图版|手机版|小黑屋|汕头@IT精英团

Powered by Discuz! X3.4 © 2021 Comsenz Inc.

GMT+8, 2021-5-12 03:31 , Processed in 0.098954 second(s), 19 queries .

快速回复 返回顶部 返回列表