Android开机过程简介


一个android系统的设备开机过程总的可以分成三部分:bootloader,kernel,android。网上有张图片做的很好

对于前两个网上有太多的说明和教程,本人也没有太多的时间去研究,因此暂且搁置了,以后如果有时间的话会再补上。我们重点来开android启动的过程。 上图


1.      当linux kernel启动后,运行的第一个用户空间进程是init,,大家在设备上运行ps命令,查看这个进程的pid为1来验证这一点。这个进程是系统运行过程中一直存在的。它的代码是“\android\system\core\init\init.c”,这是一个标准的linux应用程序。它启动了系统运行做了很多初始化, 下面我们来看init的main函数

int main(int argc, char **argv)
{
    int fd_count = 0;
    struct pollfd ufds[4];
    char *tmpdev;
    char* debuggable;
    char tmp[32];
    int property_set_fd_init = 0;
    int signal_fd_init = 0;
    int keychord_fd_init = 0;
//参数argv[0]是内核传过来的ueventd的路径名,如果在路径中找到"ueventd"这个文件那
//么就执行ueventd_main(argc, argv);这个程序,否则就执行自己的代码
    if (!strcmp(basename(argv[0]),"ueventd"))
        return ueventd_main(argc, argv);
 
    /* clear the umask */
    umask(0);
 
        /* Get the basic filesystem setup weneed put
         * together in the initramdisk on / andthen we'll
         * let the rc file figure out the rest.
         */
//创建一些文件系统的目录
    mkdir("/dev", 0755);
    mkdir("/proc", 0755);
    mkdir("/sys", 0755);
//讲一些文件挂载上去
    mount("tmpfs", "/dev","tmpfs", MS_NOSUID, "mode=0755");
    mkdir("/dev/pts", 0755);
    mkdir("/dev/socket", 0755);
    mount("devpts","/dev/pts", "devpts", 0, NULL);
    mount("proc", "/proc","proc", 0, NULL);
    mount("sysfs", "/sys","sysfs", 0, NULL);
 
        /* indicate that booting is in progressto background fw loaders, etc */
    close(open("/dev/.booting",O_WRONLY | O_CREAT, 0000));
 
        /* We must have some place other than /to create the
         * device nodes for kmsg and null,otherwise we won't
         * be able to remount / read-only lateron.
         * Now that tmpfs is mounted on /dev,we can actually
         * talk to the outside world.
         */
 open_devnull_stdio();        //创建和打开"/dev/__null__" 虚拟设备(类似于 Linux //系统中的 /dev/null 设备)并将stdin/stdout/stderr 三//个文件重定向到 "/dev/__null__" 
    klog_init();//创建和打开"/dev/__kmsg__" 虚拟设备用于记录 log
 
    INFO("reading config file\n");
   init_parse_config_file("/init.rc");         //解析 并执行init.rc
 
    /* pull the kernel commandline and ramdiskproperties file in */
    import_kernel_cmdline(0, import_kernel_nv);//导入 内核的 commandline
    /* don't expose the raw commandline tononpriv processes */
    chmod("/proc/cmdline", 0440); //修改其权限
   get_hardware_name(hardware, &revision);//得到硬件名称
    snprintf(tmp, sizeof(tmp),"/init.%s.rc", hardware);//并整理好初始化这个硬件脚本名字
    init_parse_config_file(tmp);//执行这个脚本
//初始化一些命令队列。向action_list队列里面添加各种命令
   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(property_init_action,"property_init");
    queue_builtin_action(keychord_init_action,"keychord_init");
    queue_builtin_action(console_init_action,"console_init");
   queue_builtin_action(set_init_properties_action,"set_init_properties");
 
    /* execute all the boot actions to get usstarted */
    action_for_each_trigger("init",action_add_queue_tail);
 
    /* skip mounting filesystems in chargermode */
    if (strcmp(bootmode, "charger")!= 0) {
       action_for_each_trigger("early-fs", action_add_queue_tail);
        action_for_each_trigger("fs",action_add_queue_tail);
       action_for_each_trigger("post-fs", action_add_queue_tail);
       action_for_each_trigger("post-fs-data",action_add_queue_tail);
    }
 
   queue_builtin_action(property_service_init_action,"property_service_init");
    queue_builtin_action(signal_init_action,"signal_init");
    queue_builtin_action(check_startup_action,"check_startup");
 
    if (!strcmp(bootmode, "charger")){
       action_for_each_trigger("charger", action_add_queue_tail);
    } else {
        action_for_each_trigger("early-boot",action_add_queue_tail);
       action_for_each_trigger("boot", action_add_queue_tail);
    }
 
        /* run all property triggers based oncurrent state of the properties */
   queue_builtin_action(queue_property_triggers_action,"queue_propety_triggers");
 
 
#ifBOOTCHART
    queue_builtin_action(bootchart_init_action,"bootchart_init");
#endif
 
    for(;;) {
        int nr, i, timeout = -1;
 
        execute_one_command();//执行一条前面整理的命令
        restart_processes();//如果某些服务需要重启的话,就重启他们
//注册三个文件描述符,并监听他们,如果收到相应的信号,就执行相应的处理函数
        if (!property_set_fd_init &&get_property_set_fd() > 0) {
            ufds[fd_count].fd =get_property_set_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            property_set_fd_init = 1;
        }
        if (!signal_fd_init &&get_signal_fd() > 0) {
            ufds[fd_count].fd =get_signal_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            signal_fd_init = 1;
        }
        if (!keychord_fd_init &&get_keychord_fd() > 0) {
            ufds[fd_count].fd =get_keychord_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            keychord_fd_init = 1;
        }
 
        if (process_needs_restart) {
            timeout = (process_needs_restart -gettime()) * 1000;
            if (timeout < 0)
                timeout = 0;
        }
 
        if (!action_queue_empty() ||cur_action)
            timeout = 0;
 
#ifBOOTCHART
        if (bootchart_count > 0) {
            if (timeout < 0 || timeout >BOOTCHART_POLLING_MS)
                timeout = BOOTCHART_POLLING_MS;
            if (bootchart_step() < 0 ||--bootchart_count == 0) {
                bootchart_finish();
                bootchart_count = 0;
            }
        }
#endif
 
        nr = poll(ufds, fd_count, timeout);
        if (nr <= 0)
            continue;
 
        for (i = 0; i < fd_count; i++) {
            if (ufds[i].revents == POLLIN) {
                if (ufds[i].fd ==get_property_set_fd())
                    handle_property_set_fd();
                else if (ufds[i].fd ==get_keychord_fd())
                    handle_keychord();
                else if (ufds[i].fd ==get_signal_fd())
                    handle_signal();
            }
        }
    }
 
    return 0;
}


分析上面函数,除了初始化,我们主要看它建立的服务,因为这才是系统启动下一步的关键。系统建立的服务主要在init.rc中,下面列出init.rc中所有启动的服务

## Daemonprocesses to be run by init.

##

serviceueventd /sbin/ueventd

    class core

    critical

 

serviceconsole /system/bin/sh

    class core

    console

    disabled

    user shell

group log         

# adbd iscontrolled via property triggers in init.<platform>.usb.rc

service adbd /sbin/adbd

   class core

   disabled           

serviceservicemanager /system/bin/servicemanager

    class core

    user system

    group system

    critical

    onrestart restart zygote

    onrestart restart media

    onrestart restart surfaceflinger

    onrestart restart drm

 

servicevold /system/bin/vold

    class core

    socket vold stream 0660 root mount

    ioprio be 2

 

servicenetd /system/bin/netd

    class main

    socket netd stream 0660 root system

    socket dnsproxyd stream 0660 root inet

 

servicedebuggerd /system/bin/debuggerd

class main

 

serviceril-daemon /system/bin/rild

    class main

    socket rild stream 660 root radio

    socket rild-debug stream 660 radio system

    user root

    group radio cache inet misc audio sdcard_rwlog

 

servicesurfaceflinger /system/bin/surfaceflinger

    class main

    user system

    group graphics

    onrestart restart zygote

 

servicezygote /system/bin/app_process -Xzygote /system/bin --zygote--start-system-server

    class main

    socket zygote stream 666

    onrestart write/sys/android_power/request_state wake

    onrestart write /sys/power/state on

    onrestart restart media

    onrestart restart netd

 

servicedrm /system/bin/drmserver

    class main

    user drm

    group system inet drmrpc

 

servicemedia /system/bin/mediaserver

    class main

    user media

    group audio camera inet net_bt net_bt_adminnet_bw_acct drmrpc

    ioprio rt 4

 

servicebootanim /system/bin/bootanimation

    class main

    user graphics

    group graphics

    disabled

    oneshot

 

servicedbus /system/bin/dbus-daemon --system --nofork

    class main

    socket dbus stream 660 bluetooth bluetooth

    user bluetooth

    group bluetooth net_bt_admin

 

servicebluetoothd /system/bin/bluetoothd -n

    class main

    socket bluetooth stream 660 bluetoothbluetooth

    socket dbus_bluetooth stream 660 bluetoothbluetooth

    # init.rc does not yet support applyingcapabilities, so run as root and

    # let bluetoothd drop uid to bluetooth withthe right linux capabilities

    group bluetooth net_bt_admin misc

    disabled

 

serviceinstalld /system/bin/installd

    class main

    socket installd stream 600 system system

 

serviceflash_recovery /system/etc/install-recovery.sh

    class main

    oneshot

 

serviceracoon /system/bin/racoon

    class main

    socket racoon stream 600 system system

    # IKE uses UDP port 500. Racoon will setuidto vpn after binding the port.

    group vpn net_admin inet

    disabled

    oneshot

 

servicemtpd /system/bin/mtpd

    class main

    socket mtpd stream 600 system system

    user vpn

    group vpn net_admin inet net_raw

    disabled

    oneshot

 

servicekeystore /system/bin/keystore /data/misc/keystore

    class main

    user keystore

    group keystore

    socket keystore stream 666

 

servicedumpstate /system/bin/dumpstate -s

    class main

    socket dumpstate stream 0660 shell log

    disabled

    oneshot

其中最重要的两个: servicemanager                            zygote                                          

servicemanager:用来管理系统中所有的服务,不管是本地的c++实现的还是java语言实现的都需要这个进程来统一管理,最主要的管理就是,注册添加服务,获取服务。所有的Service使用前都必须先在servicemanager中进行注册。

Zygote:Zygote这个进程是非常重要的一个进程,Zygote进程的建立是真正的Android运行空间,在android运行空间上,系统又会启动很多服务属于android服务

 

对于android的服务可以分为三类:

参考:(http://blog.csdn.net/maxleng/article/details/5504485

Native服务:是init.rc建立的服务,也就是我们上面列的所有都属于这个范畴

Android服务:是在java虚拟机上建立起来的服务 在Zygote之后

Init空间的服务:主要是属性设置。

2.      Zygote

Zygote建立起了JVM(java虚拟机),也就建立了android运行空间。Zygote的代码在\frameworks\base\cmds\app_process\app_main.cpp

int main(int argc, const char* const argv[])

{

AppRuntime runtime;

 。。。。。。。。。

 

    if (zygote){

       runtime.start("com.android.internal.os.ZygoteInit",                      startSystemServer ?"start-system-server" : "");//

//建立虚拟机"com.android.internal.os.ZygoteInit",并运行

    }else if (className) {

       // Remainder of args get passed to startup class main()

       runtime.mClassName = className;

       runtime.mArgC = argc - i;

       runtime.mArgV = argv + i;

       runtime.start("com.android.internal.os.RuntimeInit",

                application ?"application" : "tool");

    }else {

       fprintf(stderr, "Error: no class name or --zygotesupplied.\n");

       app_usage();

       LOG_ALWAYS_FATAL("app_process: no class name or --zygotesupplied.");

       return 10;

    }

         runtime.start()是建立虚拟机的函数,相关代码在frameworks\base\core\jni\AndroidRuntime.cpp中,这里不做说明了。在虚拟机建立的过程中,系统注册了虚拟机建成后所运行的第一个进程即com.android.internal.os.ZygoteInit。这个进程是对android运行空间的一些初始化。所在代码

frameworks\base\core\java\com\android\internal\os\ZygoteInit.java。在代码中建立了一些socket,查了很多资料才弄明白是干什么用的。总的来讲Android系统中的socket机制是一种进程间通信的机制,在这里它用来和ActivityManagerService通讯,每当建立一个新的android应用程序是,它会通信一次。参考http://blog.csdn.net/luoshengyang/article/details/6768304

当socket建立完成后Zygote才算真正的建立完。

3.      Android空间搭建过程中,在socket进入阻塞之前,调用了startSystemServer()这个函数 代码在:frameworks\base\core\java\com\android\internal\os\ZygoteInit.java中

private static boolean startSystemServer()

           throws MethodAndArgsCaller, RuntimeException {

       /* Hardcoded command line to start the system server */

       String args[] = {

           "--setuid=1000",

           "--setgid=1000",

           "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003,3006,3007",

           "--capabilities=130104352,130104352",

           "--runtime-init",

           "--nice-name=system_server",

           "com.android.server.SystemServer",

       };

      。。。。。。。

}

在这个函数中,建立了一个进程"com.android.server.SystemServer",用来执行systemserver, systemserver得到代码在frameworks\base\services\java\com\android\server\SystemServer.java中

public static void main(String[]args) {

         。。。。。

。。。。。。。。。

。。。。。。。。

        init1(args);

    }

这里的init1(args);定义一定要仔细看

native public static voidinit1(String[] args);

前面有native关键字,这说明这个函数是在native空间实现的具体代码在

frameworks\base\services\jni\com_android_server_SystemServer.cpp中

 

static voidandroid_server_SystemServer_init1(JNIEnv* env, jobject clazz)

{

   system_init();

}

 

/*

 * JNI registration.

 */

static JNINativeMethod gMethods[]= {

   /* name, signature, funcPtr */

   { "init1", "([Ljava/lang/String;)V", (void*)android_server_SystemServer_init1 },

};

 

intregister_android_server_SystemServer(JNIEnv* env)

{

   return jniRegisterNativeMethods(env,"com/android/server/SystemServer",

            gMethods, NELEM(gMethods));

}

 

上述函数中调用了system_init函数 这个函数在\frameworks\base\cmds\system_server\library\system_init.cpp中

 

extern "C" status_tsystem_init()

{

  。。。。。。。

。。。。。。。。。。。。

   jclass clazz = env->FindClass("com/android/server/SystemServer");

   if (clazz == NULL) {

        return UNKNOWN_ERROR;

   }

   jmethodID methodId = env->GetStaticMethodID(clazz, "init2","()V");

   if (methodId == NULL) {

        return UNKNOWN_ERROR;

   }

   env->CallStaticVoidMethod(clazz, methodId);

 

   LOGI("System server: entering thread pool.\n");

   ProcessState::self()->startThreadPool();

   IPCThreadState::self()->joinThreadPool();

   LOGI("System server: exiting thread pool.\n");

 

    return NO_ERROR;

}

从这个函数中可以看到它调用了init2()这个函数,这个函数在刚才的frameworks\base\services\java\com\android\server\SystemServer.java文件中,建立了ServerThread,来为New Service和AddService来建立服务

建立完服务以后,我们看到ProcessState::self()->startThreadPool();进程在这里开始循环,也表示systemserver建立完成

4.  Init2()函数中建立的心线程

class ServerThread extends Thread {

。。。。。。。

。。。。。。。

  ActivityManagerService.self().systemReady(new Runnable()

。。。。。

。。。。。。。

。。。}

这里调用了ActivityManagerService.self().systemReady()函数 用来通知sevice已经建立完成系统可以正常运行了。我们来看这个函数

\frameworks\base\services\java\com\android\server\am\ ActivityManagerService.java中

public void systemReady(final RunnablegoingCallback) {

       synchronized(this) {

           if (mSystemReady) {

                if (goingCallback != null)goingCallback.run();

                return;

           }

  。。。。

。。。。

。。。

  mMainStack.resumeTopActivityLocked(null);

}

 

resumeTopActivityLocked在\frameworks\base\services\java\com\android\server\am\

ActivityStack.java中

final booleanresumeTopActivityLocked(ActivityRecord prev) {

       // Find the first activity that is not finishing.

       ActivityRecord next = topRunningActivityLocked(null);

。。。。。。。

。。。。。。。。

。。。。。。。

if (next == null) {

           // There are no more activities! Let's just start up the

           // Launcher...

           if (mMainStack) {

               returnmService.startHomeActivityLocked();//打开第一个应用程序 即桌面

           }

       }

。。。。。。。

。。。。。。

}

这样我们的开机过程才算真正完成

由于本人菜鸟参考了大量前辈们的资料,然后自己一点点看代码才写出来的。个人感觉水平非常一般,有很多概念没解释清楚,流程也比较乱,跟前辈们差距很大。在这里把他们的文章贴出来,大家共同学习,共同努力,争取有一天我也能写出那么深刻的文章。

参考资料:

http://blog.csdn.net/maxleng/article/details/5508372

http://blog.csdn.net/maxleng/article/details/5504485

http://blog.csdn.net/maxleng/article/details/5508488

http://www.cnblogs.com/bastard/archive/2012/08/28/2660389.html        

http://blog.csdn.net/wavemcu/article/details/7770778

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值