系统启动
init进程(pid=1) Linux系统中用户空间的第一个进程
1.启动zygote服务
2.重启服务
当init子进程退出时,会产生SIGCHLD信号,并发送给init进程,通过socket套接字传递数据,调用到wait_for_one_process()方法,根据是否是oneshot,来决定是重启子进程,还是放弃启动。
3.属性服务
创建一块共享的内存空间,用于属性服务器;
解析各个rc文件,并启动相应属性服务进程;
init进程(pid=1)是Linux系统中用户空间的第一个进程,主要工作如下:
创建一块共享的内存空间,用于属性服务器;
解析各个rc文件,并启动相应属性服务进程;
初始化epoll,依次设置signal、property、keychord这3个fd可读时相对应的回调函数;
进入无限循环状态,执行如下流程:
检查action_queue列表是否为空,若不为空则执行相应的action;
检查是否需要重启的进程,若有则将其重新启动;
进入epoll_wait等待状态,直到系统属性变化事件(property_set改变属性值),或者收到子进程的信号SIGCHLD,再或者keychord 键盘输入事件,则会退出等待状态,执行相应的回调函数。
可见init进程在开机之后的核心工作就是响应property变化事件和回收僵尸进程。当某个进程调用property_set来改变一个系统属性值时,系统会通过socket向init进程发送一个property变化的事件通知,那么property fd会变成可读,init进程采用epoll机制监听该fd则会 触发回调handle_property_set_fd()方法。回收僵尸进程,在Linux内核中,如父进程不等待子进程的结束直接退出,会导致子进程在结束后变成僵尸进程,占用系统资源。为此,init进程专门安装了SIGCHLD信号接收器,当某些子进程退出时发现其父进程已经退出,则会向init进程发送SIGCHLD信号,init进程调用回调方法handle_signal()来回收僵尸子进程。
init.cpp
static int epoll_fd = -1;
int main(int argc, char** argv) {
...
//设置文件属性0777
umask(0);
//初始化内核log,位于节点/dev/kmsg【见小节1.2】
klog_init();
//设置输出的log级别
klog_set_level(KLOG_NOTICE_LEVEL);
//创建一块共享的内存空间,用于属性服务【见小节5.1】
property_init();
//初始化epoll功能
epoll_fd = epoll_create1(EPOLL_CLOEXEC);
//初始化子进程退出的信号处理函数,并调用epoll_ctl设置signal fd可读的回调函数【见小节2.1】
signal_handler_init();
//加载default.prop文件
property_load_boot_defaults();
//启动属性服务器,此处会调用epoll_ctl设置property fd可读的回调函数【见小节5.2】
start_property_service();
//解析init.rc文件
init_parse_config_file("/init.rc");
//执行rc文件中触发器为on early-init的语句
action_for_each_trigger("early-init", action_add_queue_tail);
//等冷插拔设备初始化完成
queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done");
queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
//设备组合键的初始化操作,此处会调用epoll_ctl设置keychord fd可读的回调函数
queue_builtin_action(keychord_init_action, "keychord_init");
// 屏幕上显示Android静态Logo 【见小节1.3】
queue_builtin_action(console_init_action, "console_init");
//执行rc文件中触发器为on init的语句
action_for_each_trigger("init", action_add_queue_tail);
queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
char bootmode[PROP_VALUE_MAX];
//当处于充电模式,则charger加入执行队列;否则late-init加入队列。
if (property_get("ro.bootmode", bootmode) > 0 && strcmp(bootmode, "charger") == 0)
{
action_for_each_trigger("charger", action_add_queue_tail);
} else {
action_for_each_trigger("late-init", action_add_queue_tail);
}
//触发器为属性是否设置
queue_builtin_action(queue_property_triggers_action, "queue_property_triggers");
while (true) {
if (!waiting_for_exec) {
execute_one_command();
//根据需要重启服务【见小节1.4】
restart_processes();
}
int timeout = -1;
if (process_needs_restart) {
timeout = (process_needs_restart - gettime()) * 1000;
if (timeout < 0)
timeout = 0;
}
if (!action_queue_empty() || cur_action) {
timeout = 0;
}
epoll_event ev;
//循环等待事件发生
int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, timeout));
if (nr == -1) {
ERROR("epoll_wait failed: %s\n", strerror(errno));
} else if (nr == 1) {
((void (*)()) ev.data.ptr)();
}
}
return 0;
}
Zygote进程启动
Zygote是由init进程通过解析init.zygote.rc文件而创建的,zygote所对应的可执行程序app_process,所对应的源文件是App_main.cpp,进程名为zygote。
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(),随时待命,当接收到请求创建新进程请求时立即唤醒并执行相应工作。
zygote进程内加载了preload()方法中的所有资源,当需要fork新进程时,采用copy on write技术。
zygote进程
SystemServer进程
在RuntimeInit.java中invokeStaticMain方法通过创建并抛出异常ZygoteInit.MethodAndArgsCaller,在ZygoteInit.java中的main()方法会捕捉该异常,并调用caller.run(),再通过反射便会调用到SystemServer.main()方法,该方法主要执行流程:
SystemServer.main
SystemServer.run
createSystemContext
startBootstrapServices();
startCoreServices();
startOtherServices();
Looper.loop();
Android进程创建
Zygote.forkAndSpecialize
ZygoteHooks.preFork
Daemons.stop
ZygoteHooks.nativePreFork
dalvik_system_ZygoteHooks.ZygoteHooks_nativePreFork
Runtime::PreZygoteFork
heap_->PreZygoteFork()
Zygote.nativeForkAndSpecialize
com_android_internal_os_Zygote.ForkAndSpecializeCommon
fork()
Zygote.callPostForkChildHooks
ZygoteHooks.postForkChild
dalvik_system_ZygoteHooks.nativePostForkChild
Runtime::DidForkFromZygote
ZygoteHooks.postForkCommon
Daemons.start