返回
揭秘Zygote进程启动源码,解锁Android应用进程启动机制
Android
2024-01-09 10:23:37
Zygote,Android进程启动的基石
在Android系统中,Zygote进程扮演着至关重要的角色,它是Android系统中第一个被创建的进程,也是所有其他进程的祖先。Android中的System Server进程、应用进程都是通过Zygote进程fork而来,因此了解Zygote进程的启动流程源码,对理解Android系统的进程管理和应用启动机制至关重要。
一、启动Zygote进程
Zygote进程的启动过程主要由init进程负责,init进程是Android系统启动的第一个进程,它负责初始化系统环境,启动Zygote进程是init进程的重要任务之一。
void init_set_zygote_args(const char *arg_list, int pid, int socket_pair[2])
{
char *args, *args_next, *args_prev;
char *saved_args = strdup(arg_list);
size_t len;
args = saved_args;
while (1) {
args_next = strchr(args, ' ');
if (!args_next) break;
args_prev = args;
len = args_next - args;
args = args_next + 1;
if (len == 5 && !memcmp(args_prev, "debug", 5)) {
fcntl(socket_pair[1], F_SETFD, FD_CLOEXEC);
close(socket_pair[1]);
socket_pair[1] = -1;
return;
}
}
free(saved_args);
}
在init进程中,会调用init_set_zygote_args()函数,对Zygote进程的启动参数进行设置,包括是否开启调试模式等。
int main(int argc, char **argv)
{
pid_t pid;
int socket_pair[2];
int status;
if (prctl(PR_SET_NAME, "zygote", 0, 0, 0) < 0) {
exit(1);
}
if (socketpair(AF_UNIX, SOCK_STREAM, 0, socket_pair)) {
exit(1);
}
pid = fork();
if (pid == -1) {
exit(1);
}
if (pid == 0) {
close(socket_pair[1]);
init_set_zygote_args(argv[1], getpid(), socket_pair);
if (zygote_process(socket_pair[0]) < 0) {
exit(1);
}
} else {
close(socket_pair[0]);
if (waitpid(pid, &status, 0) < 0) {
exit(1);
}
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
exit(0);
} else {
exit(1);
}
}
return 0;
}
随后,init进程会调用fork()函数,创建一个子进程,也就是Zygote进程。在Zygote进程中,会调用zygote_process()函数,正式启动Zygote进程。
二、Zygote进程的启动流程
Zygote进程启动后,会执行一系列初始化操作,包括:
- 加载系统库
- 创建线程池
- 初始化Binder系统
- 加载应用框架
- 启动System Server进程
static int zygote_process(int fd)
{
int ret;
ret = selinux_restore_domainfile("/file_contexts");
if (ret < 0) {
zygote_log(LOG_ERR, "selinux_restore_domainfile() failed: %s\n", strerror(errno));
return -1;
}
/* Load the system properties, they are needed by various components. */
ret = property_load_boot_defaults();
if (ret) {
zygote_log(LOG_ERR, "property_load_boot_defaults() failed: %s\n", strerror(errno));
return -1;
}
/* Default umask when starting applications. This can be overridden on a per-app
* basis with SELinux. */
umask(0027);
/* set the umask so that SELinux doesn't relabel the temp file created
* in zygote_read_apk_from_file() to u:object_r:apk_data_file:s0 */
umask(000);
ret = prepare_data_fd(fd);
if (ret < 0) {
zygote_log(LOG_ERR, "prepare_data_fd() failed: %s\n", strerror(errno));
return -1;
}
ret = prepare_argv0();
if (ret < 0) {
zygote_log(LOG_ERR, "prepare_argv0() failed: %s\n", strerror(errno));
return -1;
}
ret = prepare_env();
if (ret < 0) {
zygote_log(LOG_ERR, "prepare_env() failed: %s\n", strerror(errno));
return -1;
}
ret = prepare_debuggerd_zygote();
if (ret < 0) {
zygote_log(LOG_ERR, "prepare_debuggerd_zygote() failed: %s\n", strerror(errno));
return -1;
}
ret = prepare_property_service();
if (ret < 0) {
zygote_log(LOG_ERR, "prepare_property_service() failed: %s\n", strerror(errno));
return -1;
}
ret = prepare_openjdkjvm();
if (ret < 0) {
zygote_log(LOG_ERR, "prepare_openjdkjvm() failed: %s\n", strerror(errno));
return -1;
}
/* Stash a pointer to ZygoteProcess in ZygoteState so it can be retrieved by
* system_server. */
zygote_state->zygote_process = zygote_process;
ret = prepare_zygote_socket();
if (ret < 0) {
zygote_log(LOG_ERR, "prepare_zygote_socket() failed: %s\n", strerror(errno));
return -1;
}
ret = prepare_app_process_limit();
if (ret < 0) {
zygote_log(LOG_ERR, "prepare_app_process_limit() failed: %s\n", strerror(errno));
return -1;
}
ret = prepare_libraries();
if (ret < 0) {
zygote_log(LOG_ERR, "prepare_libraries() failed: %s\n", strerror(errno));
return -1;
}
ret = prepare_system_server();
if (ret < 0) {
zygote_log(LOG_ERR, "prepare_system_server() failed: %s\n", strerror(errno));
return -1;
}
zygote_atexit();
if (start_system_server() < 0) {
zygote_log(LOG_ERR, "starting system server failed: %s\n", strerror(errno));
return -1;
}
if (zygote_child_init() < 0) {
zygote_log(LOG_ERR, "zygote_child_init() failed: %s\n", strerror(errno));
return -1;
}
/* get the current umask. This is used to restore the umask of the child process
* after exec() */
umask(old_umask);
return 0;
}
在完成初始化操作后,Zygote进程会进入主循环,等待来自客户端的请求。当客户端请求启动一个新的应用进程时,Zygote进程会调用fork()函数,创建一个子进程,也就是新的应用进程。
三、Zygote进程的职责
Zygote进程在Android系统中扮演着重要的角色,主要负责以下职责:
- 加载系统库: Zygote进程会加载必要的系统库,为应用进程提供基础环境。
- 创建线程池: Zygote进程会创建线程池,为应用进程提供多线程支持。
- 初始化Binder系统: Zygote进程会初始化Binder系统,为应用进程提供跨进程通信机制。
- 加载应用框架: Zygote进程会加载应用框架,为应用进程提供基本功能和服务。
- **启动System Server进程