当前位置: 代码迷 >> Android >> Android起步流程分析(四) init进程分析
  详细解决方案

Android起步流程分析(四) init进程分析

热度:54   发布时间:2016-04-28 01:47:54.0
Android启动流程分析(四) init进程分析

#############################################

本文为极度寒冰原创,转载请注明出处

#############################################
前面讲到了,我们init进程执行的话,首先执行的会是init的main函数。
那我们就先来看看init的main函数做了什么事情。
首先,我们看到init最先做的事情是创建一些文件夹,并且挂载设备,这些函数都是linux的常见函数:
    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);
这里,我们正好介绍一些这里涉及到的两个目录在linux系统中的作用:
/dev:dev这个目录非常的重要,这个目录里面存放了linux的所有外部设备的节点,提供了访问外部设备的接口
/proc: 用户和应用程序可以通过proc来得到系统的信息,并可以改变内核的某些参数。常用的命令比如我们前面介绍过的cat /proc/kmsg等

mount函数的作用也一起介绍一下吧:
比如这个:
    mount("devpts", "/dev/pts", "devpts", 0, NULL);
这个的意思就是说:将devpts挂载到/dev/pts,文件系统的类型是devpts,指定文件的读写类型是0,文件系统没有特殊的参数即为NULL,

在执行了一些根文件系统的创建和挂载之后,有一个重要的函数出现在了我们的眼前。而这个,就是我们提到的cat /proc/kmsg
来看一下:
    open_devnull_stdio();    klog_init();    property_init();
open_devnull_stdio()是将标准输入,标准输出以及错误输出都重定向到了/dev/_null_的设备节点。
也就是说,在android启动的这个过程中,屏蔽了stdin,stdout,stderror的操作。在这个过程中,禁止读取文件向屏幕输出等操作。

klog_init就是我们说的init的输出设备为kmsg了,我们来看一下klog_init的实现:
首先,klog_init的实现位于:system/core/libcutils/klog.c
39void klog_init(void)40{41    static const char *name = "/dev/__kmsg__";4243    if (klog_fd >= 0) return; /* Already initialized */4445    if (mknod(name, S_IFCHR | 0600, (1 << 8) | 11) == 0) {46        klog_fd = open(name, O_WRONLY);47        if (klog_fd < 0)48                return;49        fcntl(klog_fd, F_SETFD, FD_CLOEXEC);50        unlink(name);51    }52}
我们可以看到,这边打开了一个/dev/__kmsg__的节点,
然后调用fcntl设定init的输出设备为/dev/__kmsg__

然后会去进行如下的操作:
    get_hardware_name(hardware, &revision);    process_kernel_cmdline();    union selinux_callback cb;    cb.func_log = log_callback;    selinux_set_callback(SELINUX_CB_LOG, cb);    cb.func_audit = audit_callback;    selinux_set_callback(SELINUX_CB_AUDIT, cb);    selinux_initialize();    /* 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__");    restorecon_recursive("/sys");    is_charger = !strcmp(bootmode, "charger");    INFO("property init\n");    property_load_boot_defaults();
这里,进行的都是linux的一些系统操作。
比如get_hardware_name,是从/proc/cpuinfo里面读取的
可以简单看一下cat /cpuinfo里面的内容:
445    hw = strstr(data, "\nHardware");446    rev = strstr(data, "\nRevision");
而 cpuinfo的显示的为(笔者为nexus机器):
[email protected]:/ # cat /proc/cpuinfo                                                Processor	: ARMv7 Processor rev 2 (v7l)processor	: 0BogoMIPS	: 13.53processor	: 1BogoMIPS	: 13.53processor	: 2BogoMIPS	: 13.53processor	: 3BogoMIPS	: 13.53Features	: swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 CPU implementer	: 0x51CPU architecture: 7CPU variant	: 0x0CPU part	: 0x06fCPU revision	: 2Hardware	: QCT APQ8064 MAKORevision	: 000bSerial		: 0000000000000000
读取的Hardware即为MAKO的hardware

SELINUX这个,比较复杂。是美国国家安全局研究的增强型的linux,主要为了保护信息安全。

这里,自动忽略掉这个模块,因为并不阻碍我们的分析。

在执行完这些之后,接下来的函数映入眼帘估计大家会眼前一亮。因为我们看到了一个熟悉的名字,init.rc
    INFO("reading config file\n");    init_parse_config_file("/init.rc");

init.rc的文件是如何被解析的呢?
我们接下来慢慢分析
  相关解决方案