android启动之init启动

本文探讨了Android系统的init启动过程,重点分析了init进程的main函数以及.init.rc配置文件的解析。init进程是Android的第一个进程,其main函数位于system/core/init/init.c。init.rc文件包含了Actions和服务的定义,服务被添加到service_list列表,而以on开头的动作则进入action_list。解析init.rc文件的关键在于init_parse_config_file函数,它调用parse_config逐行处理脚本,通过parse_new_section解析service和on关键字。
摘要由CSDN通过智能技术生成
整个Android系统的启动分为Linux kernel的启动和Android系统的启动。Linux kernel启动起来后,然后就运行第一个用户程序,在Android中,就是init程序,上一博文 android启动之linux内核启动已经介绍。

Init进程始终是第一个进程。Init进程的对应的代码的main函数在目录system/core/init/init.c,先来总体看一下这个main函数。

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;
    bool is_charger = false;

    //对传入的argv[0]进行判断,决定程序的执行分支
    if (!strcmp(basename(argv[0]), "ueventd"))
        return ueventd_main(argc, argv);

    if (!strcmp(basename(argv[0]), "watchdogd"))
        return watchdogd_main(argc, argv);

    /* clear the umask */
    umask(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.
         */
    //建立各种用户空间的目录,挂载与内核空间交互的文件
    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 progress to background fw loaders, etc */
    //创建打开/dev/.booting文件,然后关闭
    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 later on.
         * Now that tmpfs is mounted on /dev, we can actually
         * talk to the outside world.  
         */
    //system/core/init/util.c。创建设备节点/dev/__null__,利用dup2函数把标准输入、标准输出、标准错误输出重定向到这个设备文件中(0标准输入、1标准输出、2标准错误输出)。重定向操作完成后,就关闭掉fd。
    open_devnull_stdio();
    //system/core/libcutils/klog.c。初始化log系统/dev/__kmsg__
    klog_init();
    //system/core/init/property_service.c。初始化资源/dev/__properties__,主要是映射一些内存空间
    property_init();
    //取得硬件名,hardware通过内核命令行提供或/proc/cpuinfo文件中提供。import /init.${ro.hardware}.rc
    get_hardware_name(hardware, &revision);
    //使用import_kernel_cmdline函数导入内核变量,调用export_kernel_boot_props函数通过属性设置内核变量。就是来回设置一些属性值,包括hardware变量,在此处又通过ro.boot.hardware属性设置了一次值。
    process_kernel_cmdline();

#ifdef HAVE_SELINUX
    //SELinux(Security-Enhanced Linux) 是美国国家安全局(NSA)对于强制访问控制的实现,它是个经过安全强化的Linux操作系统,很多时候是被关闭的。
    union selinux_callback cb;
    cb.func_log = klog_write;
    selinux_set_callback(SELINUX_CB_LOG, cb);

    cb.func_audit = audit_callback;
    selinux_set_callback(SELINUX_CB_AUDIT, cb);

    INFO("loading selinux policy\n");
    if (selinux_enabled) {
        if (selinux_android_load_policy() < 0) {
            selinux_enabled = 0;
            INFO("SELinux: Disabled due to failed policy load\n");
        } else {
            selinux_init_all_handles();
        }
    } else {
        INFO("SELinux:  Disabled by command line option\n");
    }
    /* 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.
     */
    restorecon("/dev");
    restorecon("/dev/socket");
#endif

    is_charger = !strcmp(bootmode, "charger");
    INFO("property init\n");
    if (!is_charger)
  
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值