手足口病,暗杀教室,结肠癌早期症状

频道:体育世界 日期: 浏览:172

作为一名 Android 程序员,你有没有想过:那么复杂的 Android 系统,它是怎样运行起来的,我们的 App 又是怎样被 Android 系统加载后呈现在屏幕上的呢?Android 系统的启动是一个比较复杂的过程,涉及到了一些我们没有接触过的知识,本文将基于 Android Nougat 最新的代码上讲述 Android 系统的启动流程。

Bootloader —— 第一个程序

当按下电源键(加电)或者系统重启(复位)的时候,引导芯片会从 ROM(这里一般指 Flash ROM,即闪存)中预定义的位置将 Bootloader 载入到 RAM 中,接着陈贵贞,Bootloader 将会把 Linux 内核载入到 RAM 中并启动。

Bootloader 是在系统内核运行之前运行的一段小程序,也是系统教我国文的王先生运行的第一个程序,它的主要作用是:

  1. 初始化 RAM(一般指内存)
  2. 初始化硬件设备
  3. 加载内核和内存空间影像图
  4. 跳转到内核

init 进程 —— 1 号进程

L妻子的视频inux 内核启动过程中会创建 init 进程,init 进程是用户空间的第一个进程(pid=1),对应的可执行程序的源文件文件为 /system/core/init/Init.cpp,它的 main 方法如下:

int main(int argc, char** argv) {
if (!strcmp(basename(argv[0]), "ueventd")) {
return ueventd_main(argc, argv);
}
if (!strcmp(basename(argv[0]), "watchdogd")) {
return watchdogd_main(argc, argv);
}
umask(0);
add_environment("PATH", _PATH_DEFPATH);
bool is_first_stage = (argc == 1) || (strcmp(argv[1], "--second-stage") != 0);
// 创建文件并挂载
if (is_first_stage) {
mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
mkdir("/dev/pts", 0755);
mkdir("/dev/socket", 0755);
mount("devpts", "/dev/pts", "devpts", 0, NULL);
#define MAKE_STR(x) __STRING(x)
mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));
mount("sysfs", "/sys", "sysfs", 0, NULL);
}
open_devnull_stdio();
klog_init();
klog_set_level(KLOG_NOTICE_LEVEL);
NOTICE("init %s started!\n", is_first_stage ? "first stage" : "second stage");
if (!is_first_stage) {
// Indicate that booting is in progress to background fw loaders, etc.
close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));
// 初始化属性相关资源
property_init();
process_kernel_dt();
process_kernel_cmdline();
export_kernel_boot_props();
}
...
// 启动属性服务
start_property_service();
const BuiltinFunctionMap function_map;
Action::set_function_map(&function_map);
Parser& parser = Parser::GetInstance();
parser.AddSectionParser("service",std::make_unique());
parser.AddSectionParser("on", std::make_unique());
parser.AddSectionParser("import", std::make_unique());
// 解析init.rc配置文件
parser.ParseConfig("/init.rc");
...
while (true) {
if (!waiting_for_exec) {
am.ExecuteOneCommand();
restart_processes();
}
int timeout = -1;
if (process_needs_restart) {
timeout = (process_needs_restart - gettime()) * 1000;
if (timeout < 0)
timeout = 0;
}
if (am.HasMoreCommands()) {
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)();
}
}
return 0;
}

init 进程的职责主要有四个:

  1. 解析和运行所有 init.rc 文件
  2. 生成设备驱动节点
  3. 处理子进程的终结
  4. 提供属性服务

这里重点看第一点,init.rc 是一个配置文件,它由 Android 初始化语言编写,zygote 进程和 servicemanager 进程都是由 init 进程解析 init.rc 中特定的语句启动的,比如,启动 zygote 进程的代码格式如下:

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

事实上,在 system/core/rootdir 目录下,有多个 init.rc 文件,在不同的硬件干学生环境下,相应的 init.rc 文件会被导入,比如在 64 位操作系统中,上面启动 zygote 进程的代码是从 init.zygote64.rc 文件中导入的。

servicemanager 进程 —— Binder 服务的总管

我在文章借助 AIDL 理解 Android Binder 机制——Binder 来龙去脉中讲到“Binder 通信模型和通信过程”的时候提到过 ServerManager,它是 Binder IPC 的核心,是上下文的管理者,Binder 服务端必须先向 ServerManager 注册才能够为客户端提供服务,Binder 客户端在与服务端通信之前需要从 ServerManager 中黄釲莹查找并获取 Binder 服务端的引用。然而 ServerManager 在向 Binder 驱动申请成为上下文管理者的时候又涉及到了 Binder IPC 过程,这时候应该怎么处理呢?

servicemanager 进程是由 init 进程通过解析 init.rc 文件来启动的,对应的代码如下:

service servicemanager /system/bin/servicemanager
class core
user system
group system
critical
onrestart restart healthd
onrestart restart zygote
onrestart restart media
onrestart restart surfaceflinger
onrestart restart drm
复制代码

servicemanager 进程对应可执行程序的源文件为 framework/native/cmds/servicemanager/service_manager.c,简化后的代码如下:

int main(int argc, char **argv) {
struct binder_state *bs;
// 打开binder驱动,申请 128k 字节大小的内存空间
bs = binder_open(128*1024);
...
/黄之政/ 成为上下文管理者
if (binder_become_context_manager(bs)) {
return -1;
}
// 验证 selinux 权限,判断进程是否有权注册或查看指定服务
selinux_enabled = is_selinux_enabled();
sehandle = selinux_android_service_context_handle();
selinux_status_open(true);
if (selinux_enabled > 0) {
if (sehandle == NULL) {
abort();
}
if (getcon(&service_manager_context) != 0) {
abort();
}
}
...
// 进入无限循环,处理 client 端发来的请求
binder_loop(bs, svcmgr_handler);
return 0;
}

这里重点关注两点,首先,在申请了一块大小为 128k 的内存空间并验证 selinux 权限后,接着调用 framework/native/cmds/servicemanager/师蚕binder.c 中的 binder_become_context_manager 方法:

int binder_become_context_manager(struct binder_state *bs) {
// 通过ioctl,发送 BINDER_SET_CONTEXT_MGR 指令
return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}

然后,调用 binder_loop 高照松方法进入循环来处理 client 发来的请求,注意第二个参数是一个方法体,用于处理各种状态回调:

int svcmgr_handler(struct binder_state *bs,
struct binder_transaction_data *txn,
struct binder_io *msg,
struct binder_io *reply)
{
struct svcinfo *si;
uint16_t *s;
size_t len;
uint32_t handle;
uint32_t strict_policy;
int all富大龙饶敏莉女儿ow_isolated;
...

strict_policy = bio_get_uint32(msg);
s = bio_get_string16(msg, &len);
...
switch(txn->code) {
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
// 获取服务名
s = bio_get_string16(msg, &len);
// 根据名称查找相应服务
handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
bio_put_ref(reply, handle);
return 0;
case SVC_MGR_ADD_SERVICE:
// 获取服务名
s = bio_get_string16(msg, &len);
handle = bio_get_ref(msg);
allow_isolated = bio_get_uint32(msg) ? 化香叶1 : 0;
// 注册指定服务
if (do_add_service(bs, s, len, handle, txn->sender_euid,
allow_isolated, txn->sender_pid))
return -1;
break;
}
}

servicemanager 进程在启动过程的工作内容如下:

  1. 调用 binder_open 方法打开 Binder 驱动,并申请分配一块 128k 的内存空间
  2. 调用 binder_become_context_manager 方法发送 BINDER_SET_CONTEXT_MGR 给 Binder 驱动,使自己成为上下文管理者
  3. 验证 selinux 权限,判断进程是否有注册或查看指定服务的权限
  4. 调用 binder_loop 方法进入循环状态,等待 Client 请求
  5. 根据服务名称注册服务
  6. 接收 Binder 死亡通知

zygote 进程 —— Java 进程的始祖

通过解析 init.rc 文件, zygote 进程对应的可执行程序的源文件为 frameworks/base/cmds/app_process/App_main.cpp,它的 main 方法如下:

int main(int argc, char* const argv[])
{
...
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
...
Vector args;
if (!className.isEmpty()) {
args.add(application ? String8("application") : String8("tool"));
runtime.setClassNameAndArgs(className, argc - i, argv + i);
} else {
maybeCreateDalvikCache();
if (startSystemServer) {
args.add(String8("start-system-server"));
}
char prop[PROP_VALUE_MAX];
if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
ABI_LIST_PROPERTY);
return 11;
}
String8 abiFlag("--abi-list=");
abiFlag.append(prop);
args.add(abiFlag);
for (; i < argc; ++i) {
args.add(String8(argv[i]));
}
}
if (!niceName.isEmpty()) {
runtime.setArgv0(niceName.string());
set_process_name(niceName.string());
}
if (zygote) {
// 调用 AppRuntime 父类 AndroidRuntime 的 start 方法创建 zygote 进程switch开机
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Er愈组词ror: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
return 10;
}
}

调用 frameworks/base/core/jni/AndroidRuntime.cpp 的 start 方法:

void AndroidRuntime::start(const char* className, const Vector& options, bool zygote)
{
...
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
// 启动 DVM
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
onVmCreated(env);
// 注册 JNI 方法
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
// 创建数组
strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
assert(strArray != NULL);
// 从 app_main 的 main 函数得知 className 为 com.android.internal.os.ZygoteInit
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameS插菊花综合网tr);
for (size_t i = 0; i < options.size(); ++i) {
jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
assert(optionsStr != NULL);
env->SetObjectArrayElement(strArray, i + 1, optionsStr);
}
char* slashClassName = toSlashClassName(className);
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
// 找到 ZygoteInit 的 main 函数
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
// 通过 JNI 调用 ZygoteInit 的 main 函数
env->CallStaticVoidMethod(startClass, startMeth, strArray);
if (env->ExceptionCheck())
threadExitUncaughtException(env);
}
}
...
}

通过 JNI 的方式进入 frameworks/base/core/java/com/android/internal/os/ZygoteInit.java:

public static void main(String argv[]) {
...
try {
...
// 注册Zygote用的Socket
registerZygoteSocket(socketName);
...
// 预加载类和资源
preload();//2
...
if (startSystemServer) {
// 启动SystemServer进程
startSystemServer(abiList, socketName);
}
Log.i(TAG, "Accepting command socket connections");
// 等待客户端请求
runSelectLoop(abiList);
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}

ZygoteInit.java 的 registerZygoteSocket 方法:

private static void registerZygoteSocket(String socketName) {
if (sServerSocket == null) {
int fileDesc;
final String fullSocketName = ANDROID_SOCKET_PREFIX + socke50岁妇女tName;
try {
String env = System.getenv(fullSocketName);
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException(fullSocketName + " unset or invalid", ex);
}
try {
FileDescriptor fd = new FileDescriptor();
fd.setInt$(fileDesc);
// 创建 Socket 客户端
sServerSocket = new LocalServerSocket(fd);
} catch (IOException ex) {
throw new RuntimeException(
"Error binding to local socket '" + fileDesc + "'", ex);
}
}
}

ZygoteInit.java 的 startSystemServer 方法:

private static boolean startSystemServer(String abiList, String socketName)
throws MethodAndArgsCaller, RuntimeException {
...
/* Hardcoded command line to start the system server */
// SystemServer 启动参数
String args[] = {
"--setuid=1000",
"--setg356mmid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",艺术人生导演溺水
"--runtime-args",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
// 调用 Zygote.java fock 出新线程,名字叫 system_server
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
// pid 为 0 则为 fock 出来的子线程
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
// 启动 SystemServer 进程
handleSystemServerProcess(parsedArgs);
}
return true;
}

frameworks/base/core/java/com/android/internal/os/Zygote.java 的 forkAndSpecialize 方法:

public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
String instructionSet, String appDataDir) {
VM_HOOKS.preFork();
// 调用 Native 层的方法 fock 出子线程
int pid = nativeForkAndSpecialize(uid, gid, gids, debugFlags, rlimits,
mountExternal, seInfo, niceName, fdsToClose, instructionSet, appDataDir);
// Enable tracing as soon as possible for the child process.
if (pid == 0) {// fock 出来的子线程中执行
Trace.setTracingEnabled(true);
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
}
VM_HOOKS.postForkCommon();
return pid;
}

ZygoteInit.java 的 runSelectLoop 方法:

private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList fds = new ArrayList();
ArrayList peers = new ArrayList();
// sServerSocket 对象就是刚才在 registerZygoteSocket 方法中创建的服务端 Socket
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
// 循环读取状态
while (true) {
StructPollfd[] pollFds = new StructPollfd[fds.size()];
for (int i = 0; i < pollFds.length; ++i) {
pollFds[i] = new StructPollfd();
pollFds[i].fd = fds.get(i);
pollFds[i].events = (short) POLLIN;
}
try {
Os.poll(pollFds, -1);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
for (int i = pollFds.l软瓷砖的危害ength - 1; i >= 0; --i) {
// 读取的状态不是客户端连接或者数据请求时,进入下一次循环
if ((pollFds[i].revents & POLLIN) == 0) {
continue;
}
if (i == 0) {// i = 0 表示跟客户端 Socket 连接上了
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {// i > 0 表示接收到客户端 Socket 发送过来的请求
// runOnce 方法创建一个新的应用程序进程
boolean done = peers.get(i).runOnce();
if (done) {
peers.remove(i);
fds.remove(i);
}
}
}
}
}

frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java 的 runOnce 方法:

boolean runOnce() thr观音古洞打楞严七死人ows ZygoteInit.MethodAndArgsCaller {
String args[];
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
try {
// 读取 socket 客户端发送过来的参数列表
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
} catch (IOException ex) {
// EOF reac野猫口神龙事件hed.
closeSocket();
return true;
}
...
try {
// 将 socket 客户端传递过来的参数,解析成 Arguments 对象格式
parsedArgs = new Arguments(args);
...
// 同样调用 Zygote.java 的 forkAndSpecialize 方法 fock 出子进程
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, 手足口病,暗杀教室,结肠癌早期症状parsedArgs.instructionSet,
parsedArgs.appDataDir);
} catch (Exception e) {
...
}
try {
if (pid == 0) {
// 子进程执行
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
// 进入子进程流程
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
return true;
} else {
// 父进程执行
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}

从 App_main 开始,zygote 启动过程的时序图如下:

可以看到,这个过程中 zygote 首先启动了 AndroidRuntime 并通过它反射调用了 ZygoteInit.main() 方法,由此进入了 Java 的世界,因此 zygote 是 Java 层的第一个进程,也是其他 Java 进程的始祖,其他 Java 进程的创建必须依赖 zygote。

zygote 进程的任务分别是:

  1. 创建 AppRuntime(继承自 AndroidRuntime), 并调用它的 start 方法
  2. 调用 AndroidRuntime 的 startVM() 方法创建 DVM(Dalvik Virtual Machine),并调用 startReg() 方法为 DVM 注册 JNI
  3. 通过 JNI 调用 ZygoteInit.main() 方法,第一次进入 Java 的世界
  4. 调用 registerZygoteSocket() 函数建立 Socket 通道,使 zygote 进程成为 Socket 服务端,并通过 runSelectLoop() 函数等待 ActivityManagerService 发送请求创建新的应用程序进程
  5. 调用 startSystemServer() 函数 fock 出 system_server 进程

由于发文长度的原因,所以还有一部分放在了下一篇文章里面。

需要关于Android开发的进阶资料关注+转发+私聊“资料”即可领取~