一般来说这个需求主要是为了应用启动时设定绑核相关操作,但是如果没有三方应用的源码想要让其绑定再其他核心上就要修改framework源码了。framework源码修改的原理是:在zygote创建应用子进程(Fork操作)时做白名单处理,针对不同的应用APP进程进行可以有不同的绑核策略。关于Zygote的初始化以及创建APP进程的流程这里就不多说了,最终创建进程回调用到这里:com_android_internal_os_Zygote.cpp中的
com_android_internal_os_Zygote_nativeForkAndSpecialize方法。代码实现如下:
- com_android_internal_os_Zygote_nativeForkAndSpecialize(...){
- //...
- if (pid == 0) {
- SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, capabilities, capabilities,
- mount_external, se_info, nice_name, false, is_child_zygote == JNI_TRUE,
- instruction_set, app_data_dir, is_top_app == JNI_TRUE, pkg_data_info_list,
- allowlisted_data_info_list, mount_data_dirs == JNI_TRUE,
- mount_storage_dirs == JNI_TRUE);
- }
- //...
- }
修改文件为:AOSP/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp,这里主要给出了3个应用xxx1、xxx2、xxx3,绑核策略分别为7,456,234,根据此需求,具体修改内容为:
- // Utility routine to specialize a zygote child process.
- static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, jint runtime_flags,
- jobjectArray rlimits, jlong permitted_capabilities,
- jlong effective_capabilities, jint mount_external,
- jstring managed_se_info, jstring managed_nice_name,
- bool is_system_server, bool is_child_zygote,
- jstring managed_instruction_set, jstring managed_app_data_dir,
- bool is_top_app, jobjectArray pkg_data_info_list,
- jobjectArray allowlisted_data_info_list, bool mount_data_dirs,
- bool mount_storage_dirs) {
- const char* process_name = is_system_server ? "system_server" : "zygote";
- auto fail_fn = std::bind(ZygoteFailure, env, process_name, managed_nice_name, _1);
- auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);
-
- auto se_info = extract_fn(managed_se_info);
- auto nice_name = extract_fn(managed_nice_name);
- auto instruction_set = extract_fn(managed_instruction_set);
- auto app_data_dir = extract_fn(managed_app_data_dir);
-
- // Keep capabilities across UID change, unless we're staying root.
- if (uid != 0) {
- EnableKeepCapabilities(fail_fn);
- }
-
- SetInheritable(permitted_capabilities, fail_fn);
-
- DropCapabilitiesBoundingSet(fail_fn);
- //...
- const char* se_info_ptr = se_info.has_value() ? se_info.value().c_str() : nullptr;
- const char* nice_name_ptr = nice_name.has_value() ? nice_name.value().c_str() : nullptr;
-
- if (selinux_android_setcontext(uid, is_system_server, se_info_ptr, nice_name_ptr) == -1) {
- fail_fn(CREATE_ERROR("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
- is_system_server, se_info_ptr, nice_name_ptr));
- }
-
- // Make it easier to debug audit logs by setting the main thread's name to the
- // nice name rather than "app_process".
-
- if (nice_name.has_value()) {
- SetThreadName(nice_name.value());
- + //xxx1应用绑定核心7
- + if(strncmp(nice_name.value().c_str(),"com.xxx.xxx1",sizeof("com.xxx.xxx1"))==0){
- + cpu_set_t mask;
- + CPU_ZERO(&mask);
- + CPU_SET(7, &mask);
- + int ret = sched_setaffinity(0, sizeof(mask), &mask);
- + if (ret != 0) {
- + ALOGE("xxx1,setSchedAffinity call failure,ret:%d,(%s)", ret,nice_name.value().c_str());
- + }else{
- + ALOGE("xxx1,setSchedAffinity call success,ret==0,(%s)", nice_name.value().c_str());
- + }
- + }
- + //xxx2应用绑定核心4、5、6
- + if(strncmp(nice_name.value().c_str(),"com.xxx.xxx2",sizeof("com.xxx.xxx2"))==0){
- + cpu_set_t mask;
- + CPU_ZERO(&mask);
- + CPU_SET(6, &mask);
- + CPU_SET(5, &mask);
- + CPU_SET(4, &mask);
- + int ret = sched_setaffinity(0, sizeof(mask), &mask);
- + if (ret != 0) {
- + ALOGE("xxx2,setSchedAffinity call failure,ret:%d,(%s)", ret,nice_name.value().c_str());
- + }else{
- + ALOGE("xxx2,setSchedAffinity call success,ret==0,(%s)", nice_name.value().c_str());
- + }
- + }
- + //xxx3应用绑定核心2、3、4
- + if(strncmp(nice_name.value().c_str(),"com.xxx.xxx3",sizeof("com.xxx.xxx3"))==0){
- + cpu_set_t mask;
- + CPU_ZERO(&mask);
- + CPU_SET(4, &mask);
- + CPU_SET(3, &mask);
- + CPU_SET(2, &mask);
- + int ret = sched_setaffinity(0, sizeof(mask), &mask);
- + if (ret != 0) {
- + ALOGE("xxx3,setSchedAffinity call failure,ret:%d,(%s)", ret,nice_name.value().c_str());
- + }else{
- + ALOGE("xxx3,setSchedAffinity call success,ret==0,(%s)", nice_name.value().c_str());
- + }
- + }
- } else if (is_system_server) {
- SetThreadName("system_server");
- }
-
- // Unset the SIGCHLD handler, but keep ignoring SIGHUP (rationale in SetSignalHandlers).
- UnsetChldSignalHandler();
-
- if (is_system_server) {
- env->CallStaticVoidMethod(gZygoteClass, gCallPostForkSystemServerHooks, runtime_flags);
- if (env->ExceptionCheck()) {
- fail_fn("Error calling post fork system server hooks.");
- }
-
- // TODO(b/117874058): Remove hardcoded label here.
- static const char* kSystemServerLabel = "u:r:system_server:s0";
- if (selinux_android_setcon(kSystemServerLabel) != 0) {
- fail_fn(CREATE_ERROR("selinux_android_setcon(%s)", kSystemServerLabel));
- }
- }
-
- if (is_child_zygote) {
- initUnsolSocketToSystemServer();
- }
-
- env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags,
- is_system_server, is_child_zygote, managed_instruction_set);
-
- // Reset the process priority to the default value.
- setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_DEFAULT);
-
- if (env->ExceptionCheck()) {
- fail_fn("Error calling post fork hooks.");
- }
- }