参考文章:

http://dingpwen.spaces.live.com/blog/cns!4CADD02D22459860!208.entry?fl=cat

http://www.eepw.com.cn/article/89567.htm

http://blog.csdn.net/guiterb/archive/2009/04/03/4047369.aspx

先来看看Android系统在手机内存中的是怎么放置的


地址最低的地方放Bootloader,

然后放Linux Kernel,

接下来的三个区域分别放置编译源码生成的三个img文件(ramdisk.img, system.img和data.image),用户在使用过程中产生的文件等都是放在最后一个Data Image区域里面(即/data/data/<package>),这部分区域大小不固定,根据手机实际内存来确定.

手机启动的时候从最低的地址开始执行(具体的可以参看转载的另一篇博文--Linux的启动过程),首先执行Bootloader,Bootloader会去加载Linux Kernel,初始化硬件,然后挂载Ram Disk(Init process放在这里面的,另:init process的PID=1),并启动一个初始化的进程,对应的初始化的源码为:system/core/init/Init.c,简单的来看看这里面到底做了些什么

int main(int argc, char **argv) { int device_fd = -1; int property_set_fd = -1; int signal_recv_fd = -1; int keychord_fd = -1; int fd_count; int s[2]; int fd; struct sigaction act; char tmp[PROP_VALUE_MAX]; struct pollfd ufds[4]; char *tmpdev; char* debuggable; act.sa_handler = sigchld_handler; act.sa_flags = SA_NOCLDSTOP; act.sa_mask = 0; act.sa_restorer = NULL; sigaction(SIGCHLD, &act, 0); /* 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", 0, "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); /* 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. */ open_devnull_stdio(); log_init(); INFO("reading config file/n"); parse_config_file("/init.rc"); /* pull the kernel commandline and ramdisk properties file in */ qemu_init(); import_kernel_cmdline(0); get_hardware_name(); snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware); parse_config_file(tmp); action_for_each_trigger("early-init", action_add_queue_tail); drain_action_queue(); INFO("device init/n"); device_fd = device_init(); property_init(); // only listen for keychords if ro.debuggable is true debuggable = property_get("ro.debuggable"); if (debuggable && !strcmp(debuggable, "1")) { keychord_fd = open_keychord(); } if (console[0]) { snprintf(tmp, sizeof(tmp), "/dev/%s", console); console_name = strdup(tmp); } fd = open(console_name, O_RDWR); if (fd >= 0) have_console = 1; close(fd); if( load_565rle_image(INIT_IMAGE_FILE) ) { fd = open("/dev/tty0", O_WRONLY); if (fd >= 0) { const char *msg; msg = "/n" "/n" "/n" "/n" "/n" "/n" "/n" // console is 40 cols x 30 lines "/n" "/n" "/n" "/n" "/n" "/n" "/n" " A N D R O I D "; write(fd, msg, strlen(msg)); close(fd); } } if (qemu[0]) import_kernel_cmdline(1); if (!strcmp(bootmode,"factory")) property_set("ro.factorytest", "1"); else if (!strcmp(bootmode,"factory2")) property_set("ro.factorytest", "2"); else property_set("ro.factorytest", "0"); property_set("ro.serialno", serialno[0] ? serialno : ""); property_set("ro.bootmode", bootmode[0] ? bootmode : "unknown"); property_set("ro.baseband", baseband[0] ? baseband : "unknown"); property_set("ro.carrier", carrier[0] ? carrier : "unknown"); property_set("ro.bootloader", bootloader[0] ? bootloader : "unknown"); property_set("ro.hardware", hardware); snprintf(tmp, PROP_VALUE_MAX, "%d", revision); property_set("ro.revision", tmp); /* execute all the boot actions to get us started */ action_for_each_trigger("init", action_add_queue_tail); drain_action_queue(); /* read any property files on system or data and * fire up the property service. This must happen * after the ro.foo properties are set above so * that /data/local.prop cannot interfere with them. */ property_set_fd = start_property_service(); /* create a signalling mechanism for the sigchld handler */ if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0) { signal_fd = s[0]; signal_recv_fd = s[1]; fcntl(s[0], F_SETFD, FD_CLOEXEC); fcntl(s[0], F_SETFL, O_NONBLOCK); fcntl(s[1], F_SETFD, FD_CLOEXEC); fcntl(s[1], F_SETFL, O_NONBLOCK); } /* make sure we actually have all the pieces we need */ if ((device_fd < 0) || (property_set_fd < 0) || (signal_recv_fd < 0)) { ERROR("init startup failure/n"); return 1; } /* execute all the boot actions to get us started */ action_for_each_trigger("early-boot", action_add_queue_tail); action_for_each_trigger("boot", action_add_queue_tail); drain_action_queue(); /* run all property triggers based on current state of the properties */ queue_all_property_triggers(); drain_action_queue(); /* enable property triggers */ property_triggers_enabled = 1; ufds[0].fd = device_fd; ufds[0].events = POLLIN; ufds[1].fd = property_set_fd; ufds[1].events = POLLIN; ufds[2].fd = signal_recv_fd; ufds[2].events = POLLIN; fd_count = 3; if (keychord_fd > 0) { ufds[3].fd = keychord_fd; ufds[3].events = POLLIN; fd_count++; } else { ufds[3].events = 0; ufds[3].revents = 0; } #if BOOTCHART bootchart_count = bootchart_init(); if (bootchart_count < 0) { ERROR("bootcharting init failure/n"); } else if (bootchart_count > 0) { NOTICE("bootcharting started (period=%d ms)/n", bootchart_count*BOOTCHART_POLLING_MS); } else { NOTICE("bootcharting ignored/n"); } #endif for(;;) { int nr, i, timeout = -1; for (i = 0; i < fd_count; i++) ufds[i].revents = 0; drain_action_queue(); restart_processes(); if (process_needs_restart) { timeout = (process_needs_restart - gettime()) * 1000; if (timeout < 0) timeout = 0; } #if BOOTCHART if (bootchart_count > 0) { if (timeout < 0 || timeout > BOOTCHART_POLLING_MS) timeout = BOOTCHART_POLLING_MS; if (bootchart_step() < 0 || --bootchart_count == 0) { bootchart_finish(); bootchart_count = 0; } } #endif nr = poll(ufds, fd_count, timeout); if (nr <= 0) continue; if (ufds[2].revents == POLLIN) { /* we got a SIGCHLD - reap and restart as needed */ read(signal_recv_fd, tmp, sizeof(tmp)); while (!wait_for_one_process(0)) ; continue; } if (ufds[0].revents == POLLIN) handle_device_fd(device_fd); if (ufds[1].revents == POLLIN) handle_property_set_fd(property_set_fd); if (ufds[3].revents == POLLIN) handle_keychord(keychord_fd); } return 0; }

对应着代码依次看下来,它主要做了以下的事情:

1. 在根目录下面创建一些文件夹,比如/sys,/dev,也会把基本的文件系统mount上去

2. 显示Android的logo,注意这个不是开机动画,开机动画在后面才会做.

3. 解析/init.rc这个脚本

4. 初始化/init.<hardware>.rc里面的硬件设备,如果是模拟器的话,这个脚本就是init.goldfish.rc

5. 读取.prop文件,并创建SystemProperties服务

6. 解析kernel命令行,并设置相应属性

7. Trigger在init.rc中定义的action

下面来看一下第三步中init.rc文件里面的内容,以及第七步是如何来trigger里面的action的.

*.rc文件是google定义的脚本文件,关于这部分内容具体可以参照文章开头给的链接,先简单说明以下

rc文件里面主要包含了action, service, option和commands,其中action和service是具体的某个动作,option和commands是他们的一些选项

Action

action其实就是一堆命令的集合,action会有一个tigger,表示如果发生了某件事的时候就执行action里面的命令

所以action的格式是

Actions take the form of:

on <trigger>

<command>

<command>

<command>

表示当trigger发生的时候就会执行下面三个操作.

例如:

on init

export PATH /sbin:/system/sbin:/system/bin

export ANDROID_ROOT /system

export ANDROID_DATA /data

symlink /system/etc /etc

mkdir /data

mkdir /cache

mount /tmp /tmp tmpfs

就表示,当在init的时候,就会执行下面这些linux commands(设置环境变量,link两个目录,创建一些目录等)

其中的triggers主要包括下面几种:

early-init – this is triggered by init process right after parsing of init. *. rc file but before the devices initialized init–action is triggered during init boot right afterearly-init early-boot – action is triggered when init process completed initialization of itself and ready to execute all commands boot – action is triggered during init boot right after early-boot property:<name>=<value> - action is triggered when the property with name is set to specific value device-added-<path> - triggered when device with specified path has been added to the system device-removed-<path> - triggered when device with specified path has been removed from the system service-exited-<name> - triggered when the service with particular name has completed its execution and exited.

Service

service表示在init的时候需要启动的一些服务,格式如下

service <name> <pathname> [ <argument> ]*

<option>

<option>

例如:

service media /system/bin/mediaserver

user media

group system audio camera graphics inet net_bt net_bt_admin

表示启动AudioFlinger, MediaPlayerService and CameraService这些服务.

从init.rc文件我们可以看到在init过程中我们依次启动了以下的服务

console: star a shell. The source is in device/system/bin/ash.

adbd: start adb daemon. The source is in device/tools/adbd. By default is disabled.

servicemanager: start binder system. The source is in device/commands/binder.

mountd: mount all fs defined in /system/etc/mountd.conf if started, receive commands through local socket to mount any fs. The source is in device/system/bin/mountd.

debuggerd: start debug system. The source is in device/system/bin/debuggerd.

rild: start radio interface layer daemon. The source is in device/commands/rind.

zygote: start Android Java Runtime and start system server. It’s the most important service. The source is in device/servers/app.

media: start AudioFlinger, MediaPlayerService and CameraService. The source is in device/commands/mediaserver.

bootsound: play the default boot sound /system/media/audio/ui/boot.mp3. The source is in device/commands/playmp3.

dbus: start dbus daemon, it’s only used by BlueZ. The source is in device/system/Bluetooth/dbus-daemon.

hcid: redirect hcid’s stdout and stderr to the Android logging system. The source is in device/system/bin/logwrapper. By default is disabled.

hfag: start Bluetooth handsfree audio gateway, it’s only used by BlueZ. The source is in device/system/Bluetooth/bluez-utils. By default is disabled.

hsag: start Bluetooth headset audio gateway, it’s only used by BlueZ. The source is in device/system/Bluetooth/bluez-utils. By default is disabled.

installd: start install package daemon. The source is in device/servers/installd.

flash_recovery: load /system/recovery.img. The source is in device/commands/recovery/mtdutils.

其中zygote启动了java runtime是这里面最重要的一个服务.

Zygoteservice does the following tasks step by step:

1.Create JAVA VM.

2.Register android native function for JAVA VM.

3.Call the main function in the JAVA class named com.android.internal.os.ZygoteInit whose source is device/java/android/com/android/internal/os/ZygoteInit.java.

a)Load ZygoteInit class

b)Register zygote socket

c)Load preload classes(the default file is device/java/android/preloaded-classes)

d)Load preload resources

e)Call Zygote::forkSystemServer (implemented in device/dalvik/vm/InternalNative.c) to fork a new process. In the new process, call the main function in the JAVA class named com.android.server.SystemServer, whose source is in device/java/services/com/android/server.

i.Load libandroid_servers.so

ii.Call JNI native init1 function implemented in device/libs/android_servers/com_android_server_SystemServers. It only calls system_init implemented in device/servers/system/library/system_init.cpp.

lIf running on simulator, instantiate AudioFlinger, MediaPlayerService and CameraService here.

lCall init2 function in JAVA class named com.android.server.SystemServer, whose source is in device/java/services/com/android/server. This function is very critical for Android because it start all of Android JAVA services.

lIf not running on simulator, call IPCThreadState::self()->joinThreadPool() to enter into service dispatcher.

Commands

commands包括一下几种:

exec <path> <argument> - executes the command under the speicified path. This command will block until execution completes export <name> <value> - Set the environment variable <name> equal to <value> in the global environment (which will be inherited by all processes started after this command is executed) import <filename> - parse init config file extending current configuration. insmod <path> - loads Linux Module into the system mount <type> <device> <dir> [ < mountoption > ]* - Attempt to mount the named device at the directory <dir>. Syntax similar to standard mount command in Linux. trigger <event> - Trigger an event. Used to queue an action from another action. Option: Full set of options is described in /system/core/init.readme.txt file Most important are listed bellow: critical - This is a device-critical service. If it exits more than four times in four minutes, the device will reboot into recovery mode. disabled – This service will not be started automatically with its class. class <name> - specify the class of the service. If not specified then service class is set to “default”. onrestart <command> - executes the command when service restarts. setenv <name> <value> - sets an enviroment variable of <name> to the <value> inside the process of the service. user <username> - runs a service with the specified username .

更多相关文章

  1. 在android media framework中添加播放器
  2. 【转】如何使用Android(安卓)Studio把自己的Android(安卓)librar
  3. Android(安卓)混淆问题排查
  4. Android之HttpURLConnection小结
  5. android系统使用Camera2 应用
  6. Android菜单定制总结
  7. Android心得8--Internet
  8. Android(安卓)多媒体扫描过程(Android(安卓)Media Scanner Proces
  9. android中添加自己的驱动

随机推荐

  1. Android(安卓)接受Home key Event
  2. Android4.4——service之bindService
  3. android AMR-NB
  4. Android(安卓)之 WebView的使用介绍
  5. Android(安卓)Run ERROR: Unknown option
  6. Android(安卓)和 H5 互调
  7. 2011.10.13(4)——— android android:layo
  8. Android中自定义水平的ProgressBar
  9. 程序小白----AndroidStudio之飞机大战
  10. Android中照相机的使用