Android 启动系统综述

系统启动

系统启动架构图
image.png

init进程(pid=1) Linux系统中用户空间的第一个进程

1.启动zygote服务
服务启动 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;
}

init进程

Zygote进程启动

Zygote是由init进程通过解析init.zygote.rc文件而创建的,zygote所对应的可执行程序app_process,所对应的源文件是App_main.cpp,进程名为zygote。

Zygote启动流程

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 fork新进程

zygote进程

SystemServer进程

SystemServer启动流程

在RuntimeInit.java中invokeStaticMain方法通过创建并抛出异常ZygoteInit.MethodAndArgsCaller,在ZygoteInit.java中的main()方法会捕捉该异常,并调用caller.run(),再通过反射便会调用到SystemServer.main()方法,该方法主要执行流程:

SystemServer.main
    SystemServer.run
        createSystemContext
        startBootstrapServices();
        startCoreServices();
        startOtherServices();
        Looper.loop();
system_server服务启动流程

Android进程创建

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
forkAndSpecialize时序图

ServiceManager启动流程图
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。