Android系统启动流程(基于Android 11)

late_import_paths.emplace_back(“/odm/etc/init”);
}
if (!parser.ParseConfig(“/product/etc/init”)) {
late_import_paths.emplace_back(“/product/etc/init”);
}
} else {
parser.ParseConfig(bootscript);
}
}

加载解析rc文件并启动服务。init.rc是一个配置文件,内部由Android初始化语言编写(Android Init Language),编写的脚本 init.rc文件是在init进程启动后执行的启动脚本,文件中记录着init进程需执行的操作。init.rc主要包含五种类型语句:

  • Action
  • Command
  • Service
  • Option
  • Import

下面我们继续看看init.rc中是如何定义启动zygote进程的?

2. Zygote进程启动

首先在init.rc里改成了通过${ro.zygote}属性的值来决定引入Zygote相关的配置,如下所示:

/system/core/rootdir/init.rc/
import /system/etc/init/hw/init.${ro.zygote}.rc

on late-init

Now we can start zygote for devices with file based encryption

trigger zygote-start // 1. 触发启动zygote

on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file
wait_for_prop odsign.verification.done 1

A/B update verifier that marks a successful boot.

exec_start update_verifier_nonencrypted
start statsd
start netd
start zygote // 2.启动zygote服务
start zygote_secondary

${ro.zygote}的取值有4种,在init.rc的同级目录system/core/rootdir/下,可以看到4个Zygote相关的配置文件,表示系统所支持程序的bit位数:

  1. init.zygote32.rc,Zygote进程的执行程序路径为/system/bin/app_process
  2. init.zygote64.rc,Zygote进程的执行程序路径为/system/bin/app_process64
  3. init.zygote32_64.rc,会启动两个Zygote进程,有两个执行程序,32为主模式
  4. init.zygote64_32.rc,会启动两个Zygote进程,有两个执行程序,64为主模式(系统兼容运行64位和32位的应用)

我们看看目前最新项目设备中普遍使用的init.zygote64_32.rc文件写法:

/system/core/rootdir/init.zygote64_32.rc/
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote //启动64位的zygote
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system //创建一个名为zygote的socket
socket usap_pool_primary stream 660 root system
onrestart exec_background - system system – /system/bin/vdc volume abort_fuse
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
task_profiles ProcessCapacityHigh MaxPerformance
critical window=${zygote.critical_window.minute:-off} target=zygote-fatal

service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload //启动32位的zygote
class main
priority -20
user root
group root readproc reserved_disk
socket zygote_secondary stream 660 root system
socket usap_pool_secondary stream 660 root system
onrestart restart zygote
task_profiles ProcessCapacityHigh MaxPerformance

第一行中,service表示Zygote进程以服务的形式来启动zygote则是进程的名字,/system/bin/app_process64是执行程序的路径,后面几项则是传给执行程序的参数,其中--start-system-server表示在Zygote进程启动后需要启动system_server进程。然后是Zygote进程是使用socket来进行跨进程通信的,所以会创建一个名为zygote的socket,660表示访问权限rw-rw----,表示文件拥有者和同一群组用户具有读写权限。

init进程启动后,通过fork和execv来启动Zygote进程,如下简化代码所示:

/system/core/init/service.cpp/
Result Service::Start() {

pid_t pid = -1;
if (namespaces_.flags) {
pid = clone(nullptr, nullptr, namespaces_.flags | SIGCHLD, nullptr);
} else {
pid = fork();// 1.fork创建service进程(也就是zygote进程)
}
if (pid == 0) {

if (!ExpandArgsAndExecv(args_, sigstop_)) {
PLOG(ERROR) << “cannot execv('” << args_[0]
<< “'). See the ‘Debugging init’ section of init’s README.md for tips”;
}

}
}

static bool ExpandArgsAndExecv(const std::vectorstd::string& args, bool sigstop) {
std::vectorstd::string expanded_args;
std::vector<char*> c_strings;
expanded_args.resize(args.size());
c_strings.push_back(const_cast<char*>(args[0].data()));
for (std::size_t i = 1; i < args.size(); ++i) {
auto expanded_arg = ExpandProps(args[i]);
if (!expanded_arg.ok()) {
LOG(FATAL) << args[0] << ": cannot expand arguments’: " << expanded_arg.error();
}
expanded_args[i] = *expanded_arg;
c_strings.push_back(expanded_args[i].data()); // 封装参数
}
c_strings.push_back(nullptr);
if (sigstop) {
kill(getpid(), SIGSTOP);
}
// 2. c_strings[0]是执行程序路径,即如果启动的是zygote服务时,execve会运行/system/bin/app_process64
return execv(c_strings[0], c_strings.data()) == 0;
}

2.1 native层app_process

首先运行可执行程序app_process的入口main函数:

/frameworks/base/cmds/app_process/app_main.cpp/
int main(int argc, char* const argv[])
{

// Parse runtime arguments. Stop at first unrecognized option.
bool zygote = false;

while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, “–zygote”) == 0) {
zygote = true; // 参数标识启动zygote进程
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, “–start-system-server”) == 0) {
startSystemServer = true; //参数标识启动system_server进程
}

}

if (!niceName.isEmpty()) {
runtime.setArgv0(niceName.string(), true /* setProcName */); // 进程名app_process修改为zygote
}
if (zygote) {
// 启动Zygote,执行AndroidRuntime.start函数
runtime.start(“com.android.internal.os.ZygoteInit”, args, zygote);
} else if (className) {
runtime.start(“com.android.internal.os.RuntimeInit”, args, zygote);
} else {

}
}

我们进一步来看AndroidRuntime的start流程代码:

/frameworks/base/core/jni/AndroidRuntime.cpp/
void AndroidRuntime::start(const char* className, const Vector& options, bool zygote)
{
ALOGD(“>>>>>> START %s uid %d <<<<<<\n”,
className != NULL ? className : “(unknown)”, getuid());

/* start the virtual machine /
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv
env;
if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {// 1.启动VM虚拟机
return;
}
onVmCreated(env);

/*

  • Register android functions.
    /
    if (startReg(env) < 0) { // 2.注册框架JNI调用到虚拟机中
    ALOGE(“Unable to register all android natives\n”);
    return;
    }

    char
    slashClassName = toSlashClassName(className != NULL ? className : “”);
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
    ALOGE(“JavaVM unable to locate class ‘%s’\n”, slashClassName);
    } else {
    // 3.JNI调用进入java层执行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 {
    env->CallStaticVoidMethod(startClass, startMeth, strArray);

    }

    }

从代码中可以看到AndroidRuntime#start方法中主要完成三件事情

  1. 启动进程的VM虚拟机;

  2. 注册Android系统框架JNI调用到虚拟机中;

  3. 通过JNI调用进入java层执行ZygoteInit的main函数

2.2 java层ZyogeInit

我们继续往下看简化的代码流程:

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java/
public static void main(String[] argv) {
ZygoteServer zygoteServer = null;

try {

for (int i = 1; i < argv.length; i++) {
if (“start-system-server”.equals(argv[i])) {
// 在init.rc文件中,有–start-system-server参数,表示要创建SystemServer
startSystemServer = true;
} else if (“–enable-lazy-preload”.equals(argv[i])) {
enableLazyPreload = true;
}

}

// In some configurations, we avoid preloading resources and classes eagerly.
// In such cases, we will preload things prior to our first fork.
if (!enableLazyPreload) {

preload(bootTimingsTraceLog);// 1.预加载资源

}

zygoteServer = new ZygoteServer(isPrimaryZygote); // 2.创建Socket服务端
if (startSystemServer) {
// 3.fork启动system_server进程
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

}
//4. sokcet服务端等待AMS请求(AMS会通过socket请求Zygote来创建应用程序进程)
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, “System zygote died with exception”, ex);
throw ex;
}

}

static void preload(TimingsTraceLog bootTimingsTraceLog) {

preloadClasses();// 1.加载system/etc/preloaded-classes文件中定义的各个系统类

preloadResources(); // 2.加载系统中定义的各个drawables、color资源

}

从代码中可以看到ZygoteInit#main方法中主要fork启动system_server进程:

  1. zygote进程中预加载类、主题资源、字体资源等,基于linux的copy-on-write机制,从而加速后续zygote fork创建出的应用进程的启动速度

  2. 创建socket服务端,用于跨进程通信;

  3. fork创建启动系统system_server进程;

  4. Sokcet服务端进入循环监听等待,等待后续AMS请求(AMS会通过socket请求Zygote来创建应用程序进程)。

3. system_server进程的启动

我们接着ZygoteInit#forkSystemServer往下看:

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java/
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {

/* Hardcoded command line to start the system server */
// 1.构建启动system_server进程的相关设置参数
String[] args = {
“–setuid=1000”,
“–setgid=1000”,
“–setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,”

  • “1024,1032,1065,3001,3002,3003,3006,3007,3009,3010,3011”,
    “–capabilities=” + capabilities + “,” + capabilities,
    “–nice-name=system_server”,
    “–runtime-args”,
    “–target-sdk-version=” + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
    // system_server启动的类名
    “com.android.server.SystemServer”,
    };

    try {

    /* Request to fork the system server process */
    // 2.fork创建system_server进程,具体实现在native层
    pid = Zygote.forkSystemServer(
    parsedArgs.mUid, parsedArgs.mGid,
    parsedArgs.mGids,
    parsedArgs.mRuntimeFlags,
    null,
    parsedArgs.mPermittedCapabilities,
    parsedArgs.mEffectiveCapabilities);
    } catch (IllegalArgumentException ex) {
    throw new RuntimeException(ex);
    }

/* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}

zygoteServer.closeServerSocket();
// 3.pid为0代表在新创建的system_server进程中,继续通过handleSystemServerProcess进一步处理
return handleSystemServerProcess(parsedArgs);
}

return null;
}

/**

  • Finish remaining work for the newly forked system server process.
    /
    private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {

    if (parsedArgs.mInvokeWith != null) {

    } else {

    /
  • Pass the remaining arguments to SystemServer.
    */
    // 调用ZygoteInit#zygoteInit函数具体处理
    return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
    parsedArgs.mDisabledCompatChanges,
    parsedArgs.mRemainingArgs, cl);
    }
    }

public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {

// 1.RuntimeInit初始化,通过setDefaultUncaughtExceptionHandler设置默认的异常处理机制
RuntimeInit.commonInit();
// 2.触发启动进程的Binder线程池
ZygoteInit.nativeZygoteInit();
// 3.内部经过层层调用,最终通过反射创建"com.android.server.SystemServer"类对象并执行其main函数
return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
classLoader);
}

继续结合代码看看RuntimeInit#applicationInit是如何实现反射创建"com.android.server.SystemServer"类对象并执行其main函数的:

/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java/
protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {

return findStaticMain(args.startClass, args.startArgs, classLoader);
}

protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
Class<?> cl;

try {
// 1.通过反射加载构建"com.android.server.SystemServer"类对象
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}

Method m;
try {
//2.访问获取"com.android.server.SystemServer"的main方法
m = cl.getMethod(“main”, new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
throw new RuntimeException(
"Missing static main on " + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException(
"Problem getting static main on " + className, ex);
}

/*

  • This throw gets caught in ZygoteInit.main(), which responds
  • by invoking the exception’s run() method. This arrangement
  • clears up all the stack frames that were required in setting
  • up the process.
    */
    // 3.通过抛异常触发执行main函数并清除调用栈
    return new MethodAndArgsCaller(m, argv);
    }

static class MethodAndArgsCaller implements Runnable {
/** method to call */
private final Method mMethod;

/** argument array */
private final String[] mArgs;

public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}

public void run() {
try {
// 通过反射调用main函数
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
Throwable cause = ex.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
throw (Error) cause;
}
throw new RuntimeException(ex);
}
}
}

从上面的分析中可以看到,system_server进程创建后,会通过反射创建"com.android.server.SystemServer"入口类对象并执行其main方法,我们继续往下看代码简化流程:

/frameworks/base/services/java/com/android/server/SystemServer.java/
public static void main(String[] args) {
new SystemServer().run();
}

private void run() {

// 1.创建主线程Looper
Looper.prepareMainLooper();
// 2.创建系统Context上下文
createSystemContext();
// 3.创建SystemServiceManager,用于后续系统服务(AMS、WMS等)的创建、启动和生命周期管理
mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager.setStartInfo(mRuntimeRestart, mRuntimeStartElapsedTime, mRuntimeStartUptime);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// 4.服务根据优先级被分成3批来启动:
try {
t.traceBegin(“StartServices”);
//启动引导服务,如AMS、PMS等
startBootstrapServices(t);
//启动核心服务
startCoreServices(t);
//启动其他服务
startOtherServices(t);
} catch (Throwable ex) {
Slog.e(“System”, “******************************");
Slog.e(“System”, "
Failure starting system services”, ex);
throw ex;

文末

当你打算跳槽的时候,应该把“跳槽成功后,我能学到什么东西?对我的未来发展有什么好处”放在第一位。这些东西才是真正引导你的关键。在跳槽之前尽量“物尽其用”,把手头上的工作做好,最好是完成了某个项目或是得到提升之后再走。跳槽不是目的,而是为了达到最终职业目标的手段

最后祝大家工作升职加薪,面试拿到心仪Offer



《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
******************************");
Slog.e(“System”, "
Failure starting system services", ex);
throw ex;

文末

当你打算跳槽的时候,应该把“跳槽成功后,我能学到什么东西?对我的未来发展有什么好处”放在第一位。这些东西才是真正引导你的关键。在跳槽之前尽量“物尽其用”,把手头上的工作做好,最好是完成了某个项目或是得到提升之后再走。跳槽不是目的,而是为了达到最终职业目标的手段

最后祝大家工作升职加薪,面试拿到心仪Offer

[外链图片转存中…(img-c4ePnhgo-1714835644860)]
[外链图片转存中…(img-K0PtdNnC-1714835644860)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值