您的位置:首页 > 运维架构 > Linux

Linux启动流程-bootloader至kernel的过程--android系统启动流程

2013-12-10 20:55 891 查看
1 Bootloader

对于一般的ARM处理器,CPU上电或复位执行第一条指令所在地址,即第一段程序Bootloader的开始地址,Bootloader一般存于Nor-flash(XIP),支持芯片内执行。

Bootloader的功能可总结为:1)初始化CPU时钟,内存,串口等。2)设置Linux启动参数。3)加载Linux内核镜像。Android源码位于根目录下的/bootable文件夹。

系统正常启动,运行Bootloader,初始化芯片,根据设置的启动参数cmdline,加载Linux内核镜像,将控制权交给内核。

系统在Bootloader模式下(非正常启动模式),可使用fastboot, mmcboot等工具烧写内核和文件系统,顺便提一下,Android手机分区一般分为内核区boot.img,系统区system.img,用户数据区userdata.img,数据恢复区recovery.img等。

2 Linux内核镜像

内核镜像被加载到内存,首先进行自解压,zImage, bzImage或uImage的头部都内嵌有解压缩程序,最终将内核解压到内存的指定位置,开始运行内核。

3 启动内核

源码位于/kernel/init/main.c,线索可归纳为:启动内核start_kernel() => 初始化Linux各大模块 + rest_init() => 开启内核线程kthreadd和kernel_init() => 初始化设备驱动程序do_basic_setup() + init_post() => 开启第一个用户进程init。

3.1 start_kernel()

源码位于/kernel/init/main.c的start_kernel()函数,完成初始化Linux系统的进程管理,内存管理,文件系统等工作,可以说个个都是重量级的工作。

这里有必要解释下内核选项,因为Linux各个子系统的初始化都建立在内核选项的解析之后。

parse_early_param();

parse_args("Booting kernel", static_command_line, __start___param,

__stop___param - __start___param, &unknown_bootoption);

1) 内核选项的注册

通过__early_parm(str, fn)或__setup(str, fn)宏来注册。两者都调用__setup_param宏实现,它将注册的内核选项str所关联的函数fn存放到.init.setup节。






2) 内核选项的解析

两次注册对应两次解析,即parse_early_param()和parse_param(),解析时,会在__setup_start和__setup_end之间查找内核选项,当识别有内核选项时,即会调用相应的处理函数。内核解析完后,各个子系统的初始化就可通过kernel_init()=>do_basic_setup()=>do_initcalls()来完成。

3.2 reset_init()

开启内核线程kthreadd和kernel_init,kthreadd用来运行kthread_create_list全局链表中的kthread,然后创建idle线程来占用掉cpu空闲的时间片。

内核线程又叫守护进程,关于内核线程和Linux普通进程的区别,归纳为以下三点:

内核线程执行的是内核中的函数,而普通进程只有通过系统调用才能执行内核中的函数。
内核线程只运行在内核态,而普通进程既可以运行在用户态,也可以运行在内核态。
因为内核线程指只运行在内核态,因此,它只能使用大于PAGE_OFFSET(3G)的地址空间。另一方面,不管在用户态还是内核态,普通进程可以使用4GB的地址空间。

3.3 kernel_init()

此时与体系相关的部分已经初始化完成,do_basic_setup()开始初始化设备,完成外设及驱动程序(直接编译进内核的模块)的加载和初始化。

3.4 init_post()

开启init用户进程,所谓Android的启动流程从这里才刚刚开始。

Android部分的启动流程参考http://blog.csdn.net/qianjin0703/article/details/8468312

Android启动流程

1. init进程

2. zygote进程

2.1 AndroidRuntime

2.2 ZygoteInit

3. system_server进程

3.1 init1阶段

3.2 init2阶段

接着Linux启动部分 http://blog.csdn.net/qianjin0703/article/details/6881107
1. init进程



系统在内核空间初始化进程,内存,文件系统,驱动模块之后,调用init_post()函数,开启第一个用户进程init,进入用户空间。

/kernel/init/main.c (仅截取部分重要代码)

[plain]
view plaincopyprint?

static noinline int init_post(void)
{

run_init_process("/sbin/init");
run_init_process("/etc/init");
run_init_process("/bin/init");
run_init_process("/bin/sh");
}

static noinline int init_post(void)
{

	run_init_process("/sbin/init");
	run_init_process("/etc/init");
	run_init_process("/bin/init");
	run_init_process("/bin/sh");
}


终端下查看1号进程,



可见,init是系统守护进程和zygote的父进程。

/system/core/init/init.c

[plain]
view plaincopyprint?

int main(int argc, char **argv)
{

mkdir("/dev", 0755);
mkdir("/proc", 0755);
mkdir("/sys", 0755);

mount("devpts", "/dev/pts", "devpts", 0, NULL);
mount("proc", "/proc", "proc", 0, NULL);
mount("sysfs", "/sys", "sysfs", 0, NULL);

open_devnull_stdio();
klog_init();
property_init();

get_hardware_name(hardware, &revision);
process_kernel_cmdline();

init_parse_config_file("/init.rc");
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(keychord_init_action, "keychord_init");
queue_builtin_action(console_init_action, "console_init");
action_for_each_trigger("init", action_add_queue_tail);

for(;;) {

execute_one_command();
restart_processes();

nr = poll(ufds, fd_count, timeout);

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;
}

int main(int argc, char **argv)
{

    mkdir("/dev", 0755);
    mkdir("/proc", 0755);
    mkdir("/sys", 0755);

    mount("devpts", "/dev/pts", "devpts", 0, NULL);
    mount("proc", "/proc", "proc", 0, NULL);
    mount("sysfs", "/sys", "sysfs", 0, NULL);

    open_devnull_stdio();
    klog_init();
    property_init();

    get_hardware_name(hardware, &revision);
    process_kernel_cmdline();

    init_parse_config_file("/init.rc");
    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(keychord_init_action, "keychord_init");
    queue_builtin_action(console_init_action, "console_init");
    action_for_each_trigger("init", action_add_queue_tail);

    for(;;) {

        execute_one_command();
        restart_processes();

        nr = poll(ufds, fd_count, timeout);

        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进程归纳如下

解析init.rc和init.*.rc
挂载文件系统,建立文件夹和文件,设置权限,为一些文件写入初值
初始化property属性
启动系统守护进程如adbd, vold, rild等
启动zygote进程







2. zygote进程

zygote既是Android系统创建java世界的盘古,又是繁殖system_server和所有应用程序的女娲。

终端下查看zygote进程,



2.1 AndroidRuntime

/frameworks/base/cmds/app_process/app_main.cpp

[cpp]
view plaincopyprint?

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

AppRuntime runtime;

if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer ? "start-system-server" : "");
}

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

    AppRuntime runtime;

    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit",
                startSystemServer ? "start-system-server" : "");
}

AppRuntime是从AndroidRuntime类派生的,最后由runtime.start()进入Java世界。

/frameworks/base/core/jni/AndroidRuntime.cpp

[cpp]
view plaincopyprint?

void AndroidRuntime::start(const char* className, const char* options)
{

/* start the virtual machine */
JNIEnv* env;
if (startVm(&mJavaVM, &env) != 0) {
return;
}
onVmCreated(env);

/*
* Register android functions.
*/
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}

/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
char* slashClassName = toSlashClassName(className);
jclass startClass = env->FindClass(slashClassName);

jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");

env->CallStaticVoidMethod(startClass, startMeth, strArray);

}

void AndroidRuntime::start(const char* className, const char* options)
{

    /* start the virtual machine */
    JNIEnv* env;
    if (startVm(&mJavaVM, &env) != 0) {
        return;
    }
    onVmCreated(env);

    /*
     * Register android functions.
     */
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }

    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
    char* slashClassName = toSlashClassName(className);
    jclass startClass = env->FindClass(slashClassName);

    jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");

    env->CallStaticVoidMethod(startClass, startMeth, strArray);

}

-> 创建虚拟机

注意这里会设置虚拟机的heapsize,默认16M,一般32M,不能太小,否则在操作大尺寸图片时无法分配所需内存。

-> 注册jni函数

这里注册了本地方法,这些方法最终被编译进动态链接库libandroid_runtime.so,供上层Java调用。

[cpp]
view plaincopyprint?

static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_debug_JNITest),
REG_JNI(register_com_android_internal_os_RuntimeInit),
REG_JNI(register_android_os_SystemClock),
REG_JNI(register_android_util_Log),
REG_JNI(register_android_os_Process),
REG_JNI(register_android_os_SystemProperties),
REG_JNI(register_android_os_Binder),
REG_JNI(register_android_view_Display),
REG_JNI(register_android_graphics_Bitmap),
REG_JNI(register_android_graphics_Camera),
REG_JNI(register_android_database_SQLiteDatabase),
REG_JNI(register_android_os_Power),
REG_JNI(register_android_os_StatFs),
REG_JNI(register_android_net_NetworkUtils),
REG_JNI(register_android_nfc_NdefMessage),
REG_JNI(register_com_android_internal_os_ZygoteInit),
REG_JNI(register_android_hardware_Camera),
REG_JNI(register_android_hardware_SensorManager),
REG_JNI(register_android_hardware_UsbDevice),
REG_JNI(register_android_media_AudioRecord),
REG_JNI(register_android_media_AudioSystem),
REG_JNI(register_android_media_AudioTrack),
REG_JNI(register_android_opengl_classes),
REG_JNI(register_android_bluetooth_BluetoothSocket),
REG_JNI(register_android_server_BluetoothService),

REG_JNI(register_android_app_ActivityThread),
REG_JNI(register_android_app_NativeActivity),
REG_JNI(register_android_view_InputChannel),
REG_JNI(register_android_view_InputQueue),
REG_JNI(register_android_view_KeyEvent),
REG_JNI(register_android_view_MotionEvent),
REG_JNI(register_android_view_PointerIcon),

};

static const RegJNIRec gRegJNI[] = {
    REG_JNI(register_android_debug_JNITest),
    REG_JNI(register_com_android_internal_os_RuntimeInit),
    REG_JNI(register_android_os_SystemClock),
    REG_JNI(register_android_util_Log),
    REG_JNI(register_android_os_Process),
    REG_JNI(register_android_os_SystemProperties),
    REG_JNI(register_android_os_Binder),
    REG_JNI(register_android_view_Display),
    REG_JNI(register_android_graphics_Bitmap),
    REG_JNI(register_android_graphics_Camera),
    REG_JNI(register_android_database_SQLiteDatabase),
    REG_JNI(register_android_os_Power),
    REG_JNI(register_android_os_StatFs),
    REG_JNI(register_android_net_NetworkUtils),
    REG_JNI(register_android_nfc_NdefMessage),
    REG_JNI(register_com_android_internal_os_ZygoteInit),
    REG_JNI(register_android_hardware_Camera),
    REG_JNI(register_android_hardware_SensorManager),
    REG_JNI(register_android_hardware_UsbDevice),
    REG_JNI(register_android_media_AudioRecord),
    REG_JNI(register_android_media_AudioSystem),
    REG_JNI(register_android_media_AudioTrack),
    REG_JNI(register_android_opengl_classes),
    REG_JNI(register_android_bluetooth_BluetoothSocket),
    REG_JNI(register_android_server_BluetoothService),

    REG_JNI(register_android_app_ActivityThread),
    REG_JNI(register_android_app_NativeActivity),
    REG_JNI(register_android_view_InputChannel),
    REG_JNI(register_android_view_InputQueue),
    REG_JNI(register_android_view_KeyEvent),
    REG_JNI(register_android_view_MotionEvent),
    REG_JNI(register_android_view_PointerIcon),

};


2.2 ZygoteInit

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

[java]
view plaincopyprint?

public static void main(String argv[]) {
try {
SamplingProfilerIntegration.start();

registerZygoteSocket();

preload();

SamplingProfilerIntegration.writeZygoteSnapshot();

if (argv[1].equals("start-system-server")) {
startSystemServer();
}

runSelectLoopMode();

closeServerSocket();
}
}

public static void main(String argv[]) {
        try {
            SamplingProfilerIntegration.start();

            registerZygoteSocket();

            preload();

            SamplingProfilerIntegration.writeZygoteSnapshot();

            if (argv[1].equals("start-system-server")) {
                startSystemServer();
            } 

                runSelectLoopMode();

            closeServerSocket();
        } 
    }


-> 建立服务端Socket

zygote及系统中其他程序的通信没有使用Binder,而是采用了基于AF_UNIX类型的Socket.

-> 预加载类和资源

预加载的类可以在 /frameworks/base/preloaded-classes 查看。预加载的资源生成framewrok-res.apk,主要是一些图标,刷机达人经常修改它。

-> 启动system_server进程

zygote进程fork出system_server子进程,把任务繁重的系统服务全部托管出去,自己负责循环监听所有应用程序的请求。

-> 等待应用程序的请求

zygote通过runSelectLoopMode()处理应用程序客户端的请求,由ZygoteConnection的runOnce()孵化出新的应用程序。

综上所述,zygote进程归纳如下

创建虚拟机
注册jni函数
预加载类和资源
启动system_server进程
监听应用程序请求



3. system_server进程

/frameworks/base/services/java/com/android/SystemServer.java

[java]
view plaincopyprint?

public static void main(String[] args) {

System.loadLibrary("android_servers");
init1(args);
}

public static void main(String[] args) {

        System.loadLibrary("android_servers");
        init1(args);
    }

3.1 init1阶段

加载libandriod_server.so库,实现init1

/frameworks/base/cmds/system_server/library/system_init.cpp

[cpp]
view plaincopyprint?

extern "C" status_t system_init()
{

sp<GrimReaper> grim = new GrimReaper();
sm->asBinder()->linkToDeath(grim, grim.get(), 0);

char propBuf[PROPERTY_VALUE_MAX];
property_get("system_init.startsurfaceflinger", propBuf, "1");
if (strcmp(propBuf, "1") == 0) {
// Start the SurfaceFlinger

SurfaceFlinger::instantiate();
}

property_get("system_init.startsensorservice", propBuf, "1");
if (strcmp(propBuf, "1") == 0) {
// Start the sensor service

SensorService::instantiate();
}

AndroidRuntime* runtime = AndroidRuntime::getRuntime();

jclass clazz = env->FindClass("com/android/server/SystemServer");
jmethodID methodId = env->GetStaticMethodID(clazz, "init2", "()V");
env->CallStaticVoidMethod(clazz, methodId);

return NO_ERROR;
}

extern "C" status_t system_init()
{

    sp<GrimReaper> grim = new GrimReaper();
    sm->asBinder()->linkToDeath(grim, grim.get(), 0);

    char propBuf[PROPERTY_VALUE_MAX];
    property_get("system_init.startsurfaceflinger", propBuf, "1");
    if (strcmp(propBuf, "1") == 0) {
        // Start the SurfaceFlinger
        SurfaceFlinger::instantiate();
    }

    property_get("system_init.startsensorservice", propBuf, "1");
    if (strcmp(propBuf, "1") == 0) {
        // Start the sensor service
        SensorService::instantiate();
    }

    AndroidRuntime* runtime = AndroidRuntime::getRuntime();

    jclass clazz = env->FindClass("com/android/server/SystemServer");
    jmethodID methodId = env->GetStaticMethodID(clazz, "init2", "()V");
    env->CallStaticVoidMethod(clazz, methodId);

    return NO_ERROR;
}




3.2 init2阶段

init2回到Java层,启动一个ServerThread线程,启动系统的各项服务。





Android应用(4)

Android系统(17)

Linux驱动(9)

Media系统(6)

Block系统(4)

Input系统(4)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: