Android系统初始化过程分析(Android 4.3)

原文链接:https://my.oschina.net/fuyajun1983cn/blog/263939

在内核初始化完成后,最后会启动第一个用户空间进程,路径名为/init,它对应的代码是在/system/core/init/init.c。

下面将从main函数开始一步步分析其中的执行过程。

 

    if (!strcmp(basename(argv[0]), "ueventd"))

        return ueventd_main(argc, argv);

 

    if (!strcmp(basename(argv[0]), "watchdogd"))

        return watchdogd_main(argc, argv);

 

首先,watchdog和uevent命令已经集成到了init。/sbin/ueventd和/sbin/watchdogd是一个链接文件,它直接链接到/init,所以当执行/sbin/eventd或/sbin/watchdogd时,将会进入相应的ueventd_main或watchdogd_main入口点。ueventd伺服程序将解析/ueventd.rc文件,并创建相应的设备结点。watchdogd伺服程序是一个看门狗程序,它的任务就是定期向看门狗设备文件执行写操作,以判断系统是否正常运行。

接下来就是创建几个必须的目录,并挂载tmpfs,devpts,proc,sysfs文件系统,将通过创建文件"/dev/.booting"来表示目前正处于启动中的状态。

 

    /* 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 */

    close(open("/dev/.booting", O_WRONLY | O_CREAT, 0000));

 

接下来,将创建两个设备结点:/dev/__null__以及/dev/__kmsg__,并打开标准输入流,输出流以及错误输出流,并将它们重定向到/dev/__null__,所以,此时是不能直接调用printf系列的函数直接打印Log输出,而是利用klog输出日志。

    open_devnull_stdio();

    klog_init();

property_init();

 

接下来,property_init初始化属性服务所需要的基本空间。首先创建一个/dev/__properties__文件,然后通过对应的文件描述映射一块共享内存,大小PA_SIZE(49152),映射的地址和相应的文件描述符保存在struct workspace中。

 

typedef struct {

    void *data;

    size_t size;

    int fd;

} workspace;

 

其中data记录了映射的共享内存的地址,而fd保存的是一个只读权限的文件描述符,size是这块映射的共享内存的大小。

 

接着获取硬件信息,将处理传递给内核的命令行参数

    get_hardware_name(hardware, &revision);

 

    process_kernel_cmdline();

 

如果启用了SELinux机制,接下来将加载selinux策略,并初始化文件安全上下文以及属性安全上下文。

 

    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");

    restorecon("/dev/__properties__");

 

如果当前启动模式不是充电模式,将/default.prop文件中加载默认的一些属性设置。

 

    INFO("property init\n");

    if (!is_charger)

        property_load_boot_defaults();

 

然后就是解析/init.rc文件中的一些action, service,等信息,并通过action_for_each_trigger执行相应的命令。同时queue_builtin_action也会增加一些内置的action,将在稍后逐条触发执行。

最后进入循环,逐条执行命令,并启动service_list中的所有服务,将其状态变为SVC_RUNNING, 最后将监听属性设置命令,按键请求以及信号等消息,并作相应处理。

转载于:https://my.oschina.net/fuyajun1983cn/blog/263939

上一篇:Centos7 iptables firewalld防火墙与selinux配置


下一篇:【我的Linux,我做主!】企业军工级安全策略--SELinux实战