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。