Learn Some Franework-2 Story begins at Init

来源:互联网 发布:网络电视是什么意思 编辑:程序博客网 时间:2024/06/06 03:10

Learn Some Framework-2 Story begins at Init to Zygote


Intro

本章节主要介绍当我们按下Power键后到Zygote来到这段时间内发生的故事,主要是Android Framework都做了什么。


S1. Init

Linux启动后,Bootloader会现根据Kernel的入口地址载入Kernel(这部分如果感兴趣请参看其他资料,此处不再累述),Kernel加载成功后,会启动第一个用户进程--Init, Init会读取Init.RC的内容,并根据RC脚本的内容开始初始化系统,对于Android而言,系统即是指System Server部分。

请注意,因为Init进程是第一个用户进程,所以当我们看见/poc/1时,这个pid为1的进程就是Init,且恒真。


对于Android,Google将Init.RC文件放在 /system/core/rootdir/init.rc, 下面我们就来看一下init.rc到底做了什么(文件大家可以在之前章节提到的Androidxref上查看).

rc实质上是一个脚本文件,只是他的interpretter是Init这个进程而已,所以阅读上应该不会有障碍。

我们首先看见的是一系列的"on",譬如on early-init, on init...等等,它表示了Init的不同阶段所需要做的事情,我们可以形象地理解成类似于回调函数的标记即可,执行的顺序也是由上而下,首先:

on early-init    # Set init and its forked children's oom_adj.    write /proc/1/oom_score_adj -1000    # Set the security context of /adb_keys if present.    restorecon /adb_keys    start ueventd

我们之前讲过,一看见/proc/1就知道这是Init进程,所以现将这个进程的adj值设置为-1000,如此低的值保证了这个进程不会被Low Memory Killer杀掉,有关Low Memory Killer我们会在之后的章节介绍。

"restorecon"是标准的Linux命令,用于恢复SELinux的文件属性,所以与安全有关,这部分我们会在接下来的章节介绍到SELinux。


接下来通过start命令运行脚本ueventd,ueventd的源码位于/system/core/init/ueventd.cpp,  由于作者内核知识有限,只能带大家走马观花,大致了解一下作用:

int ueventd_main(int argc, char **argv){    /*     * init sets the umask to 077 for forked processes. We need to     * create files with exact permissions, without modification by     * the umask.     */    umask(000);    /* Prevent fire-and-forget children from becoming zombies.     * If we should need to wait() for some children in the future     * (as opposed to none right now), double-forking here instead     * of ignoring SIGCHLD may be the better solution.     */    signal(SIGCHLD, SIG_IGN);    open_devnull_stdio();    klog_init();    klog_set_level(KLOG_NOTICE_LEVEL);    NOTICE("ueventd started!\n");    selinux_callback cb;    cb.func_log = selinux_klog_callback;    selinux_set_callback(SELINUX_CB_LOG, cb);    char hardware[PROP_VALUE_MAX];    property_get("ro.hardware", hardware);    ueventd_parse_config_file("/ueventd.rc");    ueventd_parse_config_file(android::base::StringPrintf("/ueventd.%s.rc", hardware).c_str());    device_init();    pollfd ufd;    ufd.events = POLLIN;    ufd.fd = get_device_fd();    while (true) {        ufd.revents = 0;        int nr = poll(&ufd, 1, -1);        if (nr <= 0) {            continue;        }        if (ufd.revents & POLLIN) {            handle_device_fd();        }    }    return 0;}

我们可以看到,这main函数内,首先打开了kernel log,这样开发者可以在第一时间通过串口打印kernel运行时的Log。

接下来处理了ueventd.rc这个脚本,这个脚本很简单,主要是对应了挂载点的权限声明,就不累述了。

最重要的一步便是device_init()这个方法的调用:

void device_init() {   sehandle = NULL;   if (is_selinux_enabled() > 0) {       sehandle = selinux_android_file_context_handle();       selinux_status_open(true);   }   /* is 256K enough? udev uses 16MB! */   device_fd = uevent_open_socket(256*1024, true);   if (device_fd == -1) {       return;   }   fcntl(device_fd, F_SETFL, O_NONBLOCK);   if (access(COLDBOOT_DONE, F_OK) == 0) {       NOTICE("Skipping coldboot, already done!\n");       return;   }   Timer t;   coldboot("/sys/class");   coldboot("/sys/block");   coldboot("/sys/devices");   close(open(COLDBOOT_DONE, O_WRONLY|O_CREAT|O_CLOEXEC, 0000));   NOTICE("Coldboot took %.2fs.\n", t.duration());}

在Linux中,设备的挂载和卸载是kernel通过socket发送uevent给用户态的进程的,所以在这里首先打开这个socket以便于接受kernel的uevent。

之后做了coldboot,具体便是指针对在uevent收到之前已经挂载的设备再次发送uevent以便于全面的初始化,在Android上,主要针对sys下面的class, block和devices三个设备挂载点。


然后我们再回去/system/core/init/ueventd.cpp, 此时就开始通过poll方法等待socket上的uevent,一旦poll到uevent了,就进入handle_device_fd()处理。


至此,设备初始化已经完成了,这样我们就可以开始进入真正的操作系统的Init阶段了,我们再回到Init.rc文件:

on init    sysclktz 0    # Backward compatibility.    symlink /system/etc /etc    symlink /sys/kernel/debug /d    # Link /vendor to /system/vendor for devices without a vendor partition.    symlink /system/vendor /vendor    # Create cgroup mount point for cpu accounting    mkdir /acct    mount cgroup none /acct cpuacct    mkdir /acct/uid    # Create cgroup mount point for memory    mount tmpfs none /sys/fs/cgroup mode=0750,uid=0,gid=1000    mkdir /sys/fs/cgroup/memory 0750 root system    mount cgroup none /sys/fs/cgroup/memory memory    write /sys/fs/cgroup/memory/memory.move_charge_at_immigrate 1    chown root system /sys/fs/cgroup/memory/tasks    chmod 0660 /sys/fs/cgroup/memory/tasks    mkdir /sys/fs/cgroup/memory/sw 0750 root system    write /sys/fs/cgroup/memory/sw/memory.swappiness 100    write /sys/fs/cgroup/memory/sw/memory.move_charge_at_immigrate 1    chown root system /sys/fs/cgroup/memory/sw/tasks    chmod 0660 /sys/fs/cgroup/memory/sw/tasks    mkdir /system    mkdir /data 0771 system system    mkdir /cache 0770 system cache    mkdir /config 0500 root root    # Mount staging areas for devices managed by vold    # See storage config details at http://source.android.com/tech/storage/    mkdir /mnt 0755 root system    mount tmpfs tmpfs /mnt mode=0755,uid=0,gid=1000    restorecon_recursive /mnt    mkdir /mnt/secure 0700 root root    mkdir /mnt/secure/asec 0700 root root    mkdir /mnt/asec 0755 root system    mkdir /mnt/obb 0755 root system    mkdir /mnt/media_rw 0750 root media_rw    mkdir /mnt/user 0755 root root    mkdir /mnt/user/0 0755 root root    mkdir /mnt/expand 0771 system system    # Storage views to support runtime permissions    mkdir /storage 0755 root root    mkdir /mnt/runtime 0700 root root    mkdir /mnt/runtime/default 0755 root root    mkdir /mnt/runtime/default/self 0755 root root    mkdir /mnt/runtime/read 0755 root root    mkdir /mnt/runtime/read/self 0755 root root    mkdir /mnt/runtime/write 0755 root root    mkdir /mnt/runtime/write/self 0755 root root    # Symlink to keep legacy apps working in multi-user world    symlink /storage/self/primary /sdcard    symlink /mnt/user/0/primary /mnt/runtime/default/self/primary    # memory control cgroup    mkdir /dev/memcg 0700 root system    mount cgroup none /dev/memcg memory    write /proc/sys/kernel/panic_on_oops 1    write /proc/sys/kernel/hung_task_timeout_secs 0    write /proc/cpu/alignment 4    # scheduler tunables    # Disable auto-scaling of scheduler tunables with hotplug. The tunables    # will vary across devices in unpredictable ways if allowed to scale with    # cpu cores.    write /proc/sys/kernel/sched_tunable_scaling 0    write /proc/sys/kernel/sched_latency_ns 10000000    write /proc/sys/kernel/sched_wakeup_granularity_ns 2000000    write /proc/sys/kernel/sched_compat_yield 1    write /proc/sys/kernel/sched_child_runs_first 0    write /proc/sys/kernel/randomize_va_space 2    write /proc/sys/kernel/kptr_restrict 2    write /proc/sys/vm/mmap_min_addr 32768    write /proc/sys/net/ipv4/ping_group_range "0 2147483647"    write /proc/sys/net/unix/max_dgram_qlen 300    write /proc/sys/kernel/sched_rt_runtime_us 950000    write /proc/sys/kernel/sched_rt_period_us 1000000    # reflect fwmark from incoming packets onto generated replies    write /proc/sys/net/ipv4/fwmark_reflect 1    write /proc/sys/net/ipv6/fwmark_reflect 1    # set fwmark on accepted sockets    write /proc/sys/net/ipv4/tcp_fwmark_accept 1    # disable icmp redirects    write /proc/sys/net/ipv4/conf/all/accept_redirects 0    write /proc/sys/net/ipv6/conf/all/accept_redirects 0    # Create cgroup mount points for process groups    mkdir /dev/cpuctl    mount cgroup none /dev/cpuctl cpu    chown system system /dev/cpuctl    chown system system /dev/cpuctl/tasks    chmod 0666 /dev/cpuctl/tasks    write /dev/cpuctl/cpu.shares 1024    write /dev/cpuctl/cpu.rt_runtime_us 800000    write /dev/cpuctl/cpu.rt_period_us 1000000    mkdir /dev/cpuctl/bg_non_interactive    chown system system /dev/cpuctl/bg_non_interactive/tasks    chmod 0666 /dev/cpuctl/bg_non_interactive/tasks    # 5.0 %    write /dev/cpuctl/bg_non_interactive/cpu.shares 52    write /dev/cpuctl/bg_non_interactive/cpu.rt_runtime_us 700000    write /dev/cpuctl/bg_non_interactive/cpu.rt_period_us 1000000    # sets up initial cpusets for ActivityManager    mkdir /dev/cpuset    mount cpuset none /dev/cpuset    # this ensures that the cpusets are present and usable, but the device's    # init.rc must actually set the correct cpus    mkdir /dev/cpuset/foreground    write /dev/cpuset/foreground/cpus 0    write /dev/cpuset/foreground/mems 0    mkdir /dev/cpuset/foreground/boost    write /dev/cpuset/foreground/boost/cpus 0    write /dev/cpuset/foreground/boost/mems 0    mkdir /dev/cpuset/background    write /dev/cpuset/background/cpus 0    write /dev/cpuset/background/mems 0    # system-background is for system tasks that should only run on    # little cores, not on bigs    # to be used only by init, so don't change system-bg permissions    mkdir /dev/cpuset/system-background    write /dev/cpuset/system-background/cpus 0    write /dev/cpuset/system-background/mems 0    # change permissions for all cpusets we'll touch at runtime    chown system system /dev/cpuset    chown system system /dev/cpuset/foreground    chown system system /dev/cpuset/foreground/boost    chown system system /dev/cpuset/background    chown system system /dev/cpuset/tasks    chown system system /dev/cpuset/foreground/tasks    chown system system /dev/cpuset/foreground/boost/tasks    chown system system /dev/cpuset/background/tasks    chmod 0664 /dev/cpuset/foreground/tasks    chmod 0664 /dev/cpuset/foreground/boost/tasks    chmod 0664 /dev/cpuset/background/tasks    chmod 0664 /dev/cpuset/tasks    # qtaguid will limit access to specific data based on group memberships.    #   net_bw_acct grants impersonation of socket owners.    #   net_bw_stats grants access to other apps' detailed tagged-socket stats.    chown root net_bw_acct /proc/net/xt_qtaguid/ctrl    chown root net_bw_stats /proc/net/xt_qtaguid/stats    # Allow everybody to read the xt_qtaguid resource tracking misc dev.    # This is needed by any process that uses socket tagging.    chmod 0644 /dev/xt_qtaguid    # Create location for fs_mgr to store abbreviated output from filesystem    # checker programs.    mkdir /dev/fscklogs 0770 root system    # pstore/ramoops previous console log    mount pstore pstore /sys/fs/pstore    chown system log /sys/fs/pstore/console-ramoops    chmod 0440 /sys/fs/pstore/console-ramoops    chown system log /sys/fs/pstore/pmsg-ramoops-0    chmod 0440 /sys/fs/pstore/pmsg-ramoops-0    # enable armv8_deprecated instruction hooks    write /proc/sys/abi/swp 1

配合注释不难理解到,这一部就开始新建各种文件夹以及文件权限的设置了.

接下来:

# Healthd can trigger a full boot from charger mode by signaling this# property when the power button is held.on property:sys.boot_from_charger_mode=1    class_stop charger    trigger late-init

当boot_from_charger_mode这个系统属性为1的时候,表示可以在充电时启动系统,那么我们需要做的是停止charger这个脚本,并触发late-init Action。

那么charger又是干什么的呢?其实它的主要作用就是在关机充电时显示充电画面的脚本,如果需要boot,那么紧接着我们需要显示的是Android的Logo,所以自然需要停止它,有关charger的具体介绍,我们在后续章节接着讲。

紧接着我们就步入了late-init:

# Mount filesystems and start core system services.on late-init    trigger early-fs    trigger fs    trigger post-fs    # Load properties from /system/ + /factory after fs mount. Place    # this in another action so that the load will be scheduled after the prior    # issued fs triggers have completed.    trigger load_system_props_action    # Now we can mount /data. File encryption requires keymaster to decrypt    # /data, which in turn can only be loaded when system properties are present    trigger post-fs-data    trigger load_persist_props_action    # Remove a file to wake up anything waiting for firmware.    trigger firmware_mounts_complete    trigger early-boot    trigger boot

可以看出,这个时候Init连续触发了文件系统相关的3个Action,分别是early-fs, fs, post-fs,原生代码中并没有early-fs和fs的Action, 我们简单看一下post-fs做了一些什么:

on post-fs    start logd    # once everything is setup, no need to modify /    mount rootfs rootfs / ro remount    # Mount shared so changes propagate into child namespaces    mount rootfs rootfs / shared rec    # Mount default storage into root namespace    mount none /mnt/runtime/default /storage slave bind rec    # We chown/chmod /cache again so because mount is run as root + defaults    chown system cache /cache    chmod 0770 /cache    # We restorecon /cache in case the cache partition has been reset.    restorecon_recursive /cache    # Create /cache/recovery in case it's not there. It'll also fix the odd    # permissions if created by the recovery system.    mkdir /cache/recovery 0770 system cache    #change permissions on vmallocinfo so we can grab it from bugreports    chown root log /proc/vmallocinfo    chmod 0440 /proc/vmallocinfo    chown root log /proc/slabinfo    chmod 0440 /proc/slabinfo    #change permissions on kmsg & sysrq-trigger so bugreports can grab kthread stacks    chown root system /proc/kmsg    chmod 0440 /proc/kmsg    chown root system /proc/sysrq-trigger    chmod 0220 /proc/sysrq-trigger    chown system log /proc/last_kmsg    chmod 0440 /proc/last_kmsg    # make the selinux kernel policy world-readable    chmod 0444 /sys/fs/selinux/policy    # create the lost+found directories, so as to enforce our permissions    mkdir /cache/lost+found 0770 root root

首先就是启动了logd,这边是用于Log输出的模块,有关logd的知识我们会在接下来的章节介绍。

从而看出,post-fs启动了logd,并且做了一些cache和log相关设备的权限修正,我们就顺带看一下post-fs-data这个Action都做了什么:

on post-fs-data    # We chown/chmod /data again so because mount is run as root + defaults    chown system system /data    chmod 0771 /data    # We restorecon /data in case the userdata partition has been reset.    restorecon /data    # Emulated internal storage area    mkdir /data/media 0770 media_rw media_rw    # Make sure we have the device encryption key    start logd    start vold    installkey /data    # Start bootcharting as soon as possible after the data partition is    # mounted to collect more data.    mkdir /data/bootchart 0755 shell shell    bootchart_init    # Avoid predictable entropy pool. Carry over entropy from previous boot.    copy /data/system/entropy.dat /dev/urandom    # create basic filesystem structure    mkdir /data/misc 01771 system misc    mkdir /data/misc/adb 02750 system shell    mkdir /data/misc/bluedroid 02770 bluetooth net_bt_stack    # Fix the access permissions and group ownership for 'bt_config.conf'    chmod 0660 /data/misc/bluedroid/bt_config.conf    chown bluetooth net_bt_stack /data/misc/bluedroid/bt_config.conf    mkdir /data/misc/bluetooth 0770 system system    mkdir /data/misc/keystore 0700 keystore keystore    mkdir /data/misc/gatekeeper 0700 system system    mkdir /data/misc/keychain 0771 system system    mkdir /data/misc/net 0750 root shell    mkdir /data/misc/radio 0770 system radio    mkdir /data/misc/sms 0770 system radio    mkdir /data/misc/zoneinfo 0775 system system    mkdir /data/misc/vpn 0770 system vpn    mkdir /data/misc/shared_relro 0771 shared_relro shared_relro    mkdir /data/misc/systemkeys 0700 system system    mkdir /data/misc/wifi 0770 wifi wifi    mkdir /data/misc/wifi/sockets 0770 wifi wifi    mkdir /data/misc/wifi/wpa_supplicant 0770 wifi wifi    mkdir /data/misc/ethernet 0770 system system    mkdir /data/misc/dhcp 0770 dhcp dhcp    mkdir /data/misc/user 0771 root root    mkdir /data/misc/perfprofd 0775 root root    # give system access to wpa_supplicant.conf for backup and restore    chmod 0660 /data/misc/wifi/wpa_supplicant.conf    mkdir /data/local 0751 root root    mkdir /data/misc/media 0700 media media    mkdir /data/misc/vold 0700 root root    # For security reasons, /data/local/tmp should always be empty.    # Do not place files or directories in /data/local/tmp    mkdir /data/local/tmp 0771 shell shell    mkdir /data/data 0771 system system    mkdir /data/app-private 0771 system system    mkdir /data/app-asec 0700 root root    mkdir /data/app-lib 0771 system system    mkdir /data/app 0771 system system    mkdir /data/property 0700 root root    mkdir /data/tombstones 0771 system system    # create dalvik-cache, so as to enforce our permissions    mkdir /data/dalvik-cache 0771 root root    mkdir /data/dalvik-cache/profiles 0711 system system    # create resource-cache and double-check the perms    mkdir /data/resource-cache 0771 system system    chown system system /data/resource-cache    chmod 0771 /data/resource-cache    # create the lost+found directories, so as to enforce our permissions    mkdir /data/lost+found 0770 root root    # create directory for DRM plug-ins - give drm the read/write access to    # the following directory.    mkdir /data/drm 0770 drm drm    # create directory for MediaDrm plug-ins - give drm the read/write access to    # the following directory.    mkdir /data/mediadrm 0770 mediadrm mediadrm    mkdir /data/adb 0700 root root    # symlink to bugreport storage location    symlink /data/data/com.android.shell/files/bugreports /data/bugreports    # Separate location for storing security policy files on data    mkdir /data/security 0711 system system    # Create all remaining /data root dirs so that they are made through init    # and get proper encryption policy installed    mkdir /data/backup 0700 system system    mkdir /data/media 0770 media_rw media_rw    mkdir /data/ss 0700 system system    mkdir /data/system 0775 system system    mkdir /data/system/heapdump 0700 system system    mkdir /data/user 0711 system system    setusercryptopolicies /data/user    # Reload policy from /data/security if present.    setprop selinux.reload_policy 1    # Set SELinux security contexts on upgrade or policy update.    restorecon_recursive /data    # Check any timezone data in /data is newer than the copy in /system, delete if not.    exec - system system -- /system/bin/tzdatacheck /system/usr/share/zoneinfo /data/misc/zoneinfo    # If there is no fs-post-data action in the init.<device>.rc file, you    # must uncomment this line, otherwise encrypted filesystems    # won't work.    # Set indication (checked by vold) that we have finished this action    #setprop vold.post_fs_data_done 1

很明显,这一个Action名副其实,对/data下的文件进行操作

接来下在late-init中,开始了load property的操作,首先是load_system_props_action

# Load properties from /system/ + /factory after fs mount.on load_system_props_action    load_system_props

在这里调用了函数load_system_props()

void load_system_props() {    load_properties_from_file(PROP_PATH_SYSTEM_BUILD, NULL);    load_properties_from_file(PROP_PATH_VENDOR_BUILD, NULL);    load_properties_from_file(PROP_PATH_FACTORY, "ro.*");    load_recovery_id_prop();}
我们主要关注一下三个path,其他的实现都是C代码,请读者自行参考即可:

#define PROP_PATH_SYSTEM_BUILD     "/system/build.prop"#define PROP_PATH_VENDOR_BUILD     "/vendor/build.prop"#define PROP_PATH_FACTORY          "/factory/factory.prop"

至此,这边是我们常说的system props的来源。


接下来的一个Action:

on load_persist_props_action    load_persist_props    start logd    start logd-reinit

调用方法:

void load_persist_props(void) {    load_override_properties();    /* Read persistent properties after all default values have been loaded. */    load_persistent_properties();}

其实不难看出,这里加载了原生的persistent的props和制造商override的部分props,我们看实现:

static void load_override_properties() {    if (ALLOW_LOCAL_PROP_OVERRIDE) {        char debuggable[PROP_VALUE_MAX];        int ret = property_get("ro.debuggable", debuggable);        if (ret && (strcmp(debuggable, "1") == 0)) {            load_properties_from_file(PROP_PATH_LOCAL_OVERRIDE, NULL);        }    }}

#define PROP_PATH_LOCAL_OVERRIDE   "/data/local.prop"

static void load_persistent_properties() {    persistent_properties_loaded = 1;    std::unique_ptr<DIR, int(*)(DIR*)> dir(opendir(PERSISTENT_PROPERTY_DIR), closedir);    if (!dir) {        ERROR("Unable to open persistent property directory \"%s\": %s\n",              PERSISTENT_PROPERTY_DIR, strerror(errno));        return;    }    struct dirent* entry;    while ((entry = readdir(dir.get())) != NULL) {        if (strncmp("persist.", entry->d_name, strlen("persist."))) {            continue;        }        if (entry->d_type != DT_REG) {            continue;        }        // Open the file and read the property value.        int fd = openat(dirfd(dir.get()), entry->d_name, O_RDONLY | O_NOFOLLOW);        if (fd == -1) {            ERROR("Unable to open persistent property file \"%s\": %s\n",                  entry->d_name, strerror(errno));            continue;        }        struct stat sb;        if (fstat(fd, &sb) == -1) {            ERROR("fstat on property file \"%s\" failed: %s\n", entry->d_name, strerror(errno));            close(fd);            continue;        }        // File must not be accessible to others, be owned by root/root, and        // not be a hard link to any other file.        if (((sb.st_mode & (S_IRWXG | S_IRWXO)) != 0) || (sb.st_uid != 0) || (sb.st_gid != 0) ||                (sb.st_nlink != 1)) {            ERROR("skipping insecure property file %s (uid=%u gid=%u nlink=%u mode=%o)\n",                  entry->d_name, (unsigned int)sb.st_uid, (unsigned int)sb.st_gid,                  (unsigned int)sb.st_nlink, sb.st_mode);            close(fd);            continue;        }        char value[PROP_VALUE_MAX];        int length = read(fd, value, sizeof(value) - 1);        if (length >= 0) {            value[length] = 0;            property_set(entry->d_name, value);        } else {            ERROR("Unable to read persistent property file %s: %s\n",                  entry->d_name, strerror(errno));        }        close(fd);    }}

#define PERSISTENT_PROPERTY_DIR  "/data/property"

这样就完成了system和persistent这两种property的读取,对于property,会在之后的章节详细介绍.

接下来,late-init就将我们带入了early-boot和boot两个Action,由于early-boot在原生代码中没有实现,是留给制造商做客制化使用,所以我们只介绍boot:

on boot    # basic network init    ifup lo    hostname localhost    domainname localdomain    # set RLIMIT_NICE to allow priorities from 19 to -20    setrlimit 13 40 40    # Memory management.  Basic kernel parameters, and allow the high    # level system server to be able to adjust the kernel OOM driver    # parameters to match how it is managing things.    write /proc/sys/vm/overcommit_memory 1    write /proc/sys/vm/min_free_order_shift 4    chown root system /sys/module/lowmemorykiller/parameters/adj    chmod 0664 /sys/module/lowmemorykiller/parameters/adj    chown root system /sys/module/lowmemorykiller/parameters/minfree    chmod 0664 /sys/module/lowmemorykiller/parameters/minfree    # Tweak background writeout    write /proc/sys/vm/dirty_expire_centisecs 200    write /proc/sys/vm/dirty_background_ratio  5    # Permissions for System Server and daemons.    chown radio system /sys/android_power/state    chown radio system /sys/android_power/request_state    chown radio system /sys/android_power/acquire_full_wake_lock    chown radio system /sys/android_power/acquire_partial_wake_lock    chown radio system /sys/android_power/release_wake_lock    chown system system /sys/power/autosleep    chown system system /sys/power/state    chown system system /sys/power/wakeup_count    chown radio system /sys/power/wake_lock    chown radio system /sys/power/wake_unlock    chmod 0660 /sys/power/state    chmod 0660 /sys/power/wake_lock    chmod 0660 /sys/power/wake_unlock    chown system system /sys/devices/system/cpu/cpufreq/interactive/timer_rate    chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/timer_rate    chown system system /sys/devices/system/cpu/cpufreq/interactive/timer_slack    chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/timer_slack    chown system system /sys/devices/system/cpu/cpufreq/interactive/min_sample_time    chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/min_sample_time    chown system system /sys/devices/system/cpu/cpufreq/interactive/hispeed_freq    chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/hispeed_freq    chown system system /sys/devices/system/cpu/cpufreq/interactive/target_loads    chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/target_loads    chown system system /sys/devices/system/cpu/cpufreq/interactive/go_hispeed_load    chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/go_hispeed_load    chown system system /sys/devices/system/cpu/cpufreq/interactive/above_hispeed_delay    chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/above_hispeed_delay    chown system system /sys/devices/system/cpu/cpufreq/interactive/boost    chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/boost    chown system system /sys/devices/system/cpu/cpufreq/interactive/boostpulse    chown system system /sys/devices/system/cpu/cpufreq/interactive/input_boost    chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/input_boost    chown system system /sys/devices/system/cpu/cpufreq/interactive/boostpulse_duration    chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/boostpulse_duration    chown system system /sys/devices/system/cpu/cpufreq/interactive/io_is_busy    chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/io_is_busy    # Assume SMP uses shared cpufreq policy for all CPUs    chown system system /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq    chmod 0660 /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq    chown system system /sys/class/timed_output/vibrator/enable    chown system system /sys/class/leds/keyboard-backlight/brightness    chown system system /sys/class/leds/lcd-backlight/brightness    chown system system /sys/class/leds/button-backlight/brightness    chown system system /sys/class/leds/jogball-backlight/brightness    chown system system /sys/class/leds/red/brightness    chown system system /sys/class/leds/green/brightness    chown system system /sys/class/leds/blue/brightness    chown system system /sys/class/leds/red/device/grpfreq    chown system system /sys/class/leds/red/device/grppwm    chown system system /sys/class/leds/red/device/blink    chown system system /sys/class/timed_output/vibrator/enable    chown system system /sys/module/sco/parameters/disable_esco    chown system system /sys/kernel/ipv4/tcp_wmem_min    chown system system /sys/kernel/ipv4/tcp_wmem_def    chown system system /sys/kernel/ipv4/tcp_wmem_max    chown system system /sys/kernel/ipv4/tcp_rmem_min    chown system system /sys/kernel/ipv4/tcp_rmem_def    chown system system /sys/kernel/ipv4/tcp_rmem_max    chown root radio /proc/cmdline    # Define default initial receive window size in segments.    setprop net.tcp.default_init_rwnd 60    class_start core

可以看到,最开始Init对网络做了简单设置,接下来对lowmemorykiller以及各个外设,包括power,cpu,led等做了权限设置,最后启动一个叫做core的class, 对于class_start这个command,我们可以在command的映射表内查询到它对应的函数为do_class_start:

KEYWORD(class_start, COMMAND, 1, do_class_start)

此时,core这个service便被加载起来,于是/system/core/init/init.cpp便进入了main函数,其中出现了一段循环:

while (true) {    if (!waiting_for_exec) {        execute_one_command();        restart_processes();    }    int timeout = -1;    if (process_needs_restart) {        timeout = (process_needs_restart - gettime()) * 1000;        if (timeout < 0)            timeout = 0;    }    if (!action_queue_empty() || cur_action) {        timeout = 0;    }    bootchart_sample(&timeout);    epoll_event ev;    int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, timeout));    if (nr == -1) {        ERROR("epoll_wait failed: %s\n", strerror(errno));    } else if (nr == 1) {        ((void (*)()) ev.data.ptr)();    }}

这一段做的事情就是讲init.rc内的各个service启动起来,这其中就有大名鼎鼎的logd, ueventd, healthd等等,当运行到此时,native的daemon进程全部被启动,而承接Android最关键的一步便是:

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server    class main    socket zygote stream 660 root system    onrestart write /sys/android_power/request_state wake    onrestart write /sys/power/state on    onrestart restart media    onrestart restart netd    writepid /dev/cpuset/foreground/tasks

看到这里,我们便熟悉了,这样我们就正式进入了Zygote世代,接下来就会由Zygote大显神通了。


1 0