android7.1.2启动流程分析之init程序

android7.1.2启动流程分析之init程序
板子平台ROC_RK3328_CC

安卓源码树Android7.1.2–>kernel/init/main.c 文件
asmlinkage void __init start_kernel(void){
/* Do the rest non-__init’ed, we’re now alive */
rest_init();//在start_kernel函数最后一行
}
安卓源码树Android7.1.2–>kernel/init/main.c 文件
static noinline void __init_refok rest_init(void)
{

/*
 * We need to spawn init first so that it obtains pid 1, however
 * the init task will end up wanting to create kthreads, which, if
 * we schedule it before we create kthreadd, will OOPS.
 */
kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);

}
安卓源码树Android7.1.2–>kernel/init/main.c 文件
static int __ref kernel_init(void unused)
{
kernel_init_freeable();//有ramdisk_execute_command = “/init”;
/
need to finish all async __init code before freeing the memory */
async_synchronize_full();
free_initmem();
mark_rodata_ro();
system_state = SYSTEM_RUNNING;
numa_default_policy();

flush_delayed_fput();

/*内核启动信息“Kernel command line: root=/dev/mtdblock4 rootfstype=yaffs2 rootflags=inband-tags console=ttyS0,115200n8 rdinit=/sbin/init ro mem=64M” 而我的android 7.1.2的板子里kernel comman line 里是init=/init

如果ramdisk_execute_command变量指定了要运行的程序,启动它。

ramdisk_execute_command的取值分为三种情况:
   a.如果命令行参数中指定了“rdinit=…”,则ramdisk_execute_command等于这个参数指定的程序。
   b.否则,如果/init程序存在,ramdisk_execute_command就等于/init
   c.否则,ramdisk_execute_command为空

本main.c文件 kernel_init_freeable(void)函数有
    if (!ramdisk_execute_command) 
    ramdisk_execute_command = "/init";
*/

if (ramdisk_execute_command) {
    if (!run_init_process(ramdisk_execute_command))
        return 0;
    pr_err("Failed to execute %s\n", ramdisk_execute_command);
}

/*
 * We try each of these until one succeeds.
 *
 * The Bourne shell can be used instead of init if we are
 * trying to recover a really broken machine.
 */

if (execute_command) {
    if (!run_init_process(execute_command))
        return 0;
    pr_err("Failed to execute %s.  Attempting defaults...\n",
        execute_command);
}
if (!run_init_process("/sbin/init") ||
    !run_init_process("/etc/init") ||
    !run_init_process("/bin/init") ||
    !run_init_process("/bin/sh"))
    return 0;

panic("No init found.  Try passing init= option to kernel. "
      "See Linux Documentation/init.txt for guidance.");

}

安卓系统跟目录下的init.rc初始化脚本配置文件默认放置在android源码树的system/core/rootdir目录(类同于传统linux系统下使用busybox生成的/sbin/init程序去解析/etc/inittab文件)

android中的/init程序会通过解析/init.rc和init.rc里面包含的
import /init.${ro.hardware}.rc这两个文件中的相关的命令来完成相应的初始化流程,<ro.hardware>是当前android系统运行时所依赖的相关硬件平台的名字,/proc/cmdline命令行脚本有androidboot.hardware=rk30board,此处的ro.hardware应该就是rk30board

/init.rc初始化脚本配置文件是提供通用的相关初始化指令,/init.<ro.hardware>.rc脚本配置文件是提供特定的硬件平台的机器相关的初始化指令

init.rc初始化配置脚本的语言语法规则 有说明文档android源码树system/core/init/readme.txt.

当平台启动时,kernel中的引导参数将会被设置成init=/init.从而当挂载文件系统成功后,便会开始执行/init初始化程序。init的入口点在源码树的system/core/init/init.cpp的main函数

<system/core/init/init.cpp>

int main(int argc, char** argv) {
//创建我们需要的基础文件系统/dev,/dev/pts,/dev/socket,/proc,/sys到initramdisk中的根目录,然后由*.rc脚本配置文件来解决余下的目录节点的创建
    // Get the basic filesystem setup we need put together in the initramdisk
    // on / and then we'll let the rc file figure out the rest.
    if (is_first_stage) {
        mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
        mkdir("/dev/pts", 0755);
        mkdir("/dev/socket", 0755);
        mount("devpts", "/dev/pts", "devpts", 0, NULL);
        #define MAKE_STR(x) __STRING(x)
        mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));
        mount("sysfs", "/sys", "sysfs", 0, NULL);
    }

NOTICE(“init %s started!\n”, is_first_stage ? “first stage” : “second stage”);

if (!is_first_stage) {
//此处是init: init second stage started! 
    // Indicate that booting is in progress to background fw loaders, etc.
    close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));

    property_init();

    // If arguments are passed both on the command line and in DT,
    // properties set in DT always have priority over the command-line ones.
    ///操作proc/device-tree/firmware/android里面的设备树描述
    process_kernel_dt();
    //跟踪进去,发现是操作/proc/cmdline里面的内核命令行参数信息的
   
    process_kernel_cmdline();

    // Propagate the kernel variables to internal variables
    // used by init as well as the current required properties.
    export_kernel_boot_props();
//add by xzj to set ro.rk.soc read from /proc/cpuinfo if not set
set_soc_if_need();
}

    // If we're in the kernel domain, re-exec init to transition to the init domain now
    // that the SELinux policy has been loaded.
    if (is_first_stage) {
        if (**restorecon("/init")** == -1) {
            ERROR("restorecon failed: %s\n", strerror(errno));
            security_failure();
        }
        char* path = argv[0];
        char* args[] = { path, const_cast<char*>("--second-stage"), nullptr };
        if (execv(path, args) == -1) {
            ERROR("execv(\"%s\") failed: %s\n", path, strerror(errno));
            security_failure();
        }
    }

    // These directories were necessarily created before initial policy load
    // and therefore need their security context restored to the proper value.
    // This must happen before /dev is populated by ueventd.
    NOTICE("Running restorecon...\n");
    restorecon("/dev");
    restorecon("/dev/socket");
    restorecon("/dev/__properties__");
    restorecon("/property_contexts");
    restorecon_recursive("/sys");

    epoll_fd = epoll_create1(EPOLL_CLOEXEC);
    if (epoll_fd == -1) {
        ERROR("epoll_create1 failed: %s\n", strerror(errno));
        exit(1);
    }

    signal_handler_init();

    property_load_boot_defaults();
    export_oem_lock_status();
    start_property_service();

    const BuiltinFunctionMap function_map;
    Action::set_function_map(&function_map);

    Parser& parser = Parser::GetInstance();
    parser.AddSectionParser("service",std::make_unique<ServiceParser>());
    parser.AddSectionParser("on", std::make_unique<ActionParser>());
    parser.AddSectionParser("import", std::make_unique<ImportParser>());

//解析/init.rc配置文件
parser.ParseConfig(“/init.rc”);

    ActionManager& am = ActionManager::GetInstance();
//遍历链表并执行所有标志为early-init的活动Action
        am.QueueEventTrigger("early-init");

    // Queue an action that waits for coldboot done so we know ueventd has set up all of /dev...
    am.QueueBuiltinAction(wait_for_coldboot_done_action, "wait_for_coldboot_done");
    // ... so that we can start queuing up actions that require stuff from /dev.
    am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
    am.QueueBuiltinAction(set_mmap_rnd_bits_action, "set_mmap_rnd_bits");
    am.QueueBuiltinAction(keychord_init_action, "keychord_init");
    am.QueueBuiltinAction(console_init_action, "console_init");

    // Trigger all the boot actions to get us started.
    am.QueueEventTrigger("init");

    // Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
    // wasn't ready immediately after wait_for_coldboot_done
    am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");

    // Don't mount filesystems or start core system services in charger mode.
    std::string bootmode = property_get("ro.bootmode");
    if (bootmode == "charger") {
        am.QueueEventTrigger("charger");
    } else {
        am.QueueEventTrigger("late-init");
    }

    // Run all property triggers based on current state of the properties.
    am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");

    while (true) {
        if (!waiting_for_exec) {
            am.ExecuteOneCommand();
            restart_processes();
        }


    return 0;
}

/proc/cmdline 文件里信息如下
earlyprintk=uart8250-32bit,0xff130000 console=ttyFIQ0 androidboot.baseband=N/A androidboot.selinux=permissive androidboot.hardware=rk30board androidboot.console=ttyFIQ0 init=/init mtdparts=rk29xxnand:0x00002000@0x00002000(uboot),0x00004000@0x00004000(trust),0x00002000@0x00008000(misc),0x00000800@0x0000A000(baseparamer),0x00007800@0x0000A800(resource),0x00010000@0x00012000(kernel),0x00010000@0x00022000(boot),0x00010000@0x000c

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Android 7.1.2(也被称为Nougat)是Android操作系统的一个版本,它的源代码是公开可用的。源码包含了构建和运行Android操作系统所需的所有代码文件和资源。 Android操作系统是一个基于Linux内核的开源平台,用于移动设备和嵌入式系统。它提供了一个统一的操作系统环境,使开发者能够轻松地构建和定制自己的Android设备。 Android 7.1.2源码提供了一套开发工具和框架,使开发者能够创建功能丰富、稳定和安全的应用程序。该版本中引入了一些新的功能和改进,例如通知栏的增强、多任务处理的改进、Doze模式的优化等,以提供更好的用户体验。 通过查看源代码,开发者可以深入了解Android操作系统的内部工作原理,并理解其中的各个组件和模块是如何相互协作的。例如,开发者可以研究Android的用户界面框架、应用程序生命周期管理、通信和存储机制等。 修复和优化Android 7.1.2源码也是可能的,因为它是开源的。开发者可以根据自己的需求和想法对操作系统进行修改,并参与到Android社区中,与其他开发者分享和贡献代码。 总之,Android 7.1.2源码为开发者提供了一个定制和构建Android应用的平台。通过深入了解源码,开发者能够创建出更加出色和创新的应用程序,同时也有机会参与到Android开源社区中,为整个生态系统的发展做出贡献。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xx-xx-xxx-xxx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值