Zygote 与/dev/socket/zygote

1、zygote socket 的创建

apk的启动是ams 通过socket 与zygote 通信,然后由zygote fork出来一个进程,来加载运行apk的。
ams 与zygote 通信的socket 是在系统启动时,由init.zygote*.rc 中指定创建的:

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media
    onrestart restart netd

这条init.zygote*.rc 中的配置意思为:
a、service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
去通过app_process 启动 zygote 进程
b、socket zygote stream 660 root system
创建ams 与 zygote 通信的 socket,(/dev/socket)

由配置转化为代码的具体实现是在:
system/core/init/property_service.cpp

void service_start(struct service *svc, const char *dynamic_args)
{
    int s = create_socket(si->name, socket_type,
                      si->perm, si->uid, si->gid, si->socketcon ?: scon);
    if (s >= 0) {
        publish_socket(si->name, s);  //此处name为zygote
     }
 execve(svc->args[0], (char**) arg_ptrs, (char**) ENV);
}

由init.rc 调用到此处那么:
create_socket 为创建名为zygote 的socket
publish_socket 为将创建的socket 的fd 放入 环境变量:ANDROID_SOCKET_zygote 中,以便在zygote进程中,获取此socket的fd
execve 为根据init.rc 里面的命令去创建zygote 进程。

publish_socket 将socket 的fd公布出来的具体实现为:

static void publish_socket(const char *name, int fd)            
{
    char key[64] = ANDROID_SOCKET_ENV_PREFIX;
    char val[64];
    strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
            name,
            sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
    snprintf(val, sizeof(val), "%d", fd);
    add_environment(key, val); 
    /* make sure we don't close-on-exec */
    fcntl(fd, F_SETFD, 0);
}

add_environment 以拼接的ANDROID_SOCKET_zygote 为key, socket 的fd 为val,添加进入环境变量。

变量 ANDROID_SOCKET_ENV_PREFIX 为
include/cutils/sockets.h:33:#define ANDROID_SOCKET_ENV_PREFIX “ANDROID_SOCKET_”

到此Zygote 的socket 就创建完毕,之后会去创建zygote 进程。

2、zygote 进程的创建,并与socket的关联

创建zygote
init.zygote*.rc 会通过执行app_process 命令去创建 zygote 进程

if (zygote) {
    runtime.start("com.android.internal.os.ZygoteInit", args, zygote); 
} else if (className) {
    runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} 

在AndroidRuntime.cpp 中会进行一系列的操作,然后反射调用 ZygoteInit 的main方法:

 void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
 {
    char* slashClassName = toSlashClassName(className);
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
    } else {
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
        } else {                                                                    
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
      }
    }
    free(slashClassName);
     *// 因为其他进程也是由zygote 进程fork 出来的,所有其他进程也包含这段代码,如果其他进程在java 层crash,那么也会走到这里,打印此log,所以常见此log*
    ALOGD("Shutting down VM\n");
}

zygote关联init中创建的socket
系统通过ZygoteInit的main方法进入java 世界,在此方法中,会通过之前配置的环境变量:
ANDROID_SOCKET_zygote
获取init.rc中创建的zygote socket的fd,并开始循环监听等待连接。

 public static void main(String argv[]) {
     String socketName = "zygote";
     try {
         registerZygoteSocket(socketName);
         if (startSystemServer) {
             startSystemServer(abiList, socketName);
         }
         runSelectLoop(abiList);
     } catch (MethodAndArgsCaller caller) {
        caller.run(); //此处是为了,ams 通过socket 与zygote通信,建立进程时,反射调用他的入口类。
    }
}

registerZygoteSocket 去 获取socket 的fd,并根据fd 创建出对应的LocalServerSocket 对象
startSystemServer 从zygote 中fork出,system_server 进程,并在进程启动后,连接一次 zygote的socket,由此将system_server的输入端输出端,与zygote 进程打通
runSelectLoop 开始去循环监听 socket

registerZygoteSocket
在zygote 中创建socket的服务端

private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_"
    private static void registerZygoteSocket(String socketName) {                      
            int fileDesc;
            //拼接出ANDROID_SOCKET_zygote 字符串
            final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
            //从环境变量中获取 ANDROID_SOCKET_zygote 对应的fd 值
            String env = System.getenv(fullSocketName);
            fileDesc = Integer.parseInt(env);
            FileDescriptor fd = new FileDescriptor();
            fd.setInt$(fileDesc);
            //根据fd值,创建出socket服务端。
            sServerSocket = new LocalServerSocket(fd);
            }
        }
    }

startSystemServer
会从zygote 中fork 出system_server 进程,并在system_server 进程中,通过socket 连接zygote

private static boolean startSystemServer(String abiList, String socketName)
{
    //从zygote 中fork出system_server
    pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null,  parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities);
    if (pid == 0) {
        if (hasSecondZygote(abiList)) {
            //在system_server进程中首次连接 zygote 的socket
            //waitForSecondaryZygote 中会去连接名为:zygote 的socket,如果连接不上,表示zygote 那边还没有准备好,等待一秒继续连接,直到连接成功。
            waitForSecondaryZygote(socketName);
        }
        //加载初始化 sysmte_server进程
        handleSystemServerProcess(parsedArgs);
    }
}

runSelectLoop
开始去循环监听 socket,等待system_server 的连接。

private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
        fds.add(sServerSocket.getFileDescriptor());  //将socket 服务端添加进入fds
        peers.add(null);
        //开始循环监听
        while (true) {
            StructPollfd[] pollFds = new StructPollfd[fds.size()];
            //设置参数,只监听 fd 是否有数据可读
            for (int i = 0; i < pollFds.length; ++i) {
                pollFds[i] = new StructPollfd();
                pollFds[i].fd = fds.get(i); 
                pollFds[i].events = (short) POLLIN;
            }        
            try { 
                //监听 socket 是否数据可读,如果没有那么 会在此处等待
                Os.poll(pollFds, -1); 
            } catch (ErrnoException ex) {
                throw new RuntimeException("poll failed", ex);
            }
            for (int i = pollFds.length - 1; i >= 0; --i) {
                if (i == 0) {
                    //此处对应之前,system_server 启动时,会首次与Zygote 连接, 此处将system_server 端的连接对象ZygoteConnection存储下来,以便之后读取ams 写入socket的参数
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    peers.add(newPeer);  //将连接对象添加进入 peer中,peer 数据对应为  0 ---> zygote    1---->system_server
                    fds.add(newPeer.getFileDesciptor());
                } else {
                    //当有数据传入时,会调用system_server的 ZygoteConnectiond对象的,在此runOnce方法中,会获取ams写入socket的参数,
                    boolean done = peers.get(i).runOnce();
                    if (done) {
                        peers.remove(i);
                        fds.remove(i);
                    }
                }
            }
        }
    }
}

到此:
zygote 开始循环监听 /dev/socket/zygote
system_server 与zygote 达成首次通信,
zygote 保存下 system_server 的连接对象 ZygoteConnection
都已完成,
之后如果ams 再去连接 /dev/socket/zygote 那么会调用runOnce 去fork 新进程,启动apk。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值