Android Init进程源码分析

本文详细分析了Android系统的init进程,作为内核启动的第一个用户级进程。init主要负责设置环境变量,创建必要的目录,初始化设备节点,加载SELinux策略,启动property服务等。通过解析init.rc文件,init执行了一系列动作,如挂载文件系统、启动服务等。同时,init还处理设备节点、日志系统以及权限控制等关键操作。
摘要由CSDN通过智能技术生成
一 Init

init进程,它是内核启动的第一个用户级进程。
代码路径system/core/init/

1.0 main
init程序的入口函数是init.cpp中的main函数
int main(int argc, char** argv) {
    if (!strcmp(basename(argv[0]), "ueventd")) { //  ln -sf ../init /sbin/ueventd
        return ueventd_main(argc, argv); // ueventd软链接到了init,当运行ueventd时,执行ueventd_main函数
    }

    if (!strcmp(basename(argv[0]), "watchdogd")) { // ln -sf ../init /sbin/watchdogd
        return watchdogd_main(argc, argv); // watchdogd软链接到了init,当运行watchdogd时,执行watchdogd_main函数
    }

    // Clear the umask.
    umask(0); // 清除umask值

    add_environment("PATH", _PATH_DEFPATH); // 设置环境变量PATH=/usr/local/bin:/bin:/usr/bin

    bool is_first_stage = (argc == 1) || (strcmp(argv[1], "--second-stage") != 0);

    // 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) { // 第一次启动init,创建或挂载一些linux根文件系统中的目录
        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);
        mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);
    }

    // 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
    // later on. Now that tmpfs is mounted on /dev, we can actually talk
    // to the outside world.
    open_devnull_stdio(); // init的标准输入,标准输出,标准错误文件描述符定向到/dev/__null__
    klog_init(); // 打开/dev/kmsg,init进程的log,打印到内核printk的log buffer
    klog_set_level(KLOG_NOTICE_LEVEL); // 设置log级别为5

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

    if (!is_first_stage) {
        // Indicate that booting is in progress to background fw loaders, etc.
        close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));

        property_init(); // 创建/dev/__properties__文件,大小128KB,并映射进内存

        // If arguments are passed both on the command line and in DT,
        // properties set in DT always have priority over the command-line ones.
        process_kernel_dt();
        process_kernel_cmdline(); // 解析cmdline中以androidboot.开头的参数,并设置相应的property属性

        // Propagate the kernel variables to internal variables
        // used by init as well as the current required properties.
        export_kernel_boot_props(); 设置"ro.serialno", "ro.bootmode", "ro.baseband", "ro.bootloader","ro.hardware", "ro.revision"的property属性
    }

    // Set up SELinux, including loading the SELinux policy if we're in the kernel domain.
    selinux_initialize(is_first_stage); // 初始化SEAndroid

    // 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) { // 恢复/init的SELinux文件属性
            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) { // execv会停止执行当前的进程,并且以progname应用进程替换被停止执行的进程,进程ID没有改变,这里是运行init,将其从kernel域变成用户域
            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是个空函数? 
    restorecon("/dev/socket");
    restorecon("/dev/__properties__");
    restorecon("/property_contexts");
    restorecon_recursive("/sys");

    epoll_fd = epoll_create1(EPOLL_CLOEXEC); // 表示生成的epoll fd具有“执行后关闭”特性
    if (epoll_fd == -1) {
        ERROR("epoll_create1 failed: %s\n", strerror(errno));
        exit(1);
    }

    signal_handler_init(); // 子进程退出处理

    property_load_boot_defaults(); // 加载/default.prop文件
    export_oem_lock_status(); // 设置ro.boot.flash.locked的property属性
    start_property_service(); // 启动property属性服务
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值