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大显神通了。
- Learn Some Franework-2 Story begins at Init
- Our story begins
- some url for learn
- Learn Some Framework-1
- note:some learn remark
- some link to learn as3
- Some good hyperlink for learn iOS
- Learn Some Framework-4 Binder And ServerManager
- Learn Some Framework-5 ActivityManagerService[Initialize]
- 14 things you can learn from the Google story
- some 2
- work story 2
- Story in PeopleWare: 2
- story
- Story
- Story
- story
- story
- 零基础如何系统地学习前端开发
- UI控件学习
- LeetCode 31 - Next Permutation
- 关于调用strcpy()函数时总是报错问题,5种方法解决!
- mysql 表分区技术
- Learn Some Franework-2 Story begins at Init
- redis中的基本数据类型,以及在Spring-Boot对Redis的基本使用
- tomcat-dbcp数据库连接池配置以及使用时候的一些坑
- AudioManager播放音乐
- 大型网站架构系列:20本技术书籍推荐
- zephyr-编译和运行应用
- 记录今天使用成功的GTK接口函数
- Android 简单demo kill外部应用进程、卸载外部应用、安装apk
- 三维搜索(bfs)Dungeon Master