Android之Zygote(下)--- SystemServer详解
创始人
2024-03-27 19:43:36
0

SystemServer是由zygote.forkSystemServer函数fork出来的子进程,forkSystemServer是一个native函数,

/dalvik/vm/native/dalvik_system_Zygote.c

static void Dalvik_dalvik_system_Zygote_forkSystemServer(const u4* args, JValue* pResult)
{pid_t pid;pid = forkAndSpecializeCommon(args, true);//fork一个子进程if (pid > 0) {int status;LOGI("System server process %d has been created", pid);gDvm.systemServerPid = pid; //保存了system_server进程的idif (waitpid(pid, &status, WNOHANG) == pid) { //检查刚才创建的子进程是否退出了LOGE("System server process %d has died. Restarting Zygote!", pid);kill(getpid(), SIGKILL); //system_server推出了}}
RETURN_INT(pid);static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer)
{setSignalHandler();   //设置信号处理函数
}
static void setSignalHandler() 
{sa.sa_handler = sigchldHandler;err = sigaction (SIGCHLD, &sa, NULL); //子进程死亡的信号
}
static void sigchldHandler(int s)
{if (pid == gDvm.systemServerPid) {LOG(LOG_INFO, ZYGOTE_LOG_TAG,"Exit zygote because system server (%d) has terminated\n", (int) pid);kill(getpid(), SIGKILL); //死去的进程是SS zygote直接自杀}
}
}

SystemServer的使命(以下简称SS)

 可以看到在创建SS后,SS便会调用该方法

    private static void handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs)throws ZygoteInit.MethodAndArgsCaller {//关闭从zygote继承下来的socketcloseServerSocket();RuntimeInit.zygoteInit(parsedArgs.remainingArgs); //调用此函数}

Framworks\base\core\java\com.android.internal.os\RuntimeInit.java

zygoteInitNative在AndroidRuntime.cpp中,AndroidRuntime的构造函数getCurRuntime调用了onZygoteInit函数(/frameworks/base/cmds/app_process/app_main.cpp)

public static final void zygoteInit(String[] argv)throws ZygoteInit.MethodAndArgsCaller {zygoteInitNative();//①native层的初始化invokeStaticMain(startClass, startArgs); //②调用systemServer的main函数
}
  • invokeStaticMain,在RunTimeInit中,
    virtual void onZygoteInit(){sp proc = ProcessState::self();if (proc->supportsProcesses()) {LOGV("App process: starting thread pool.\n");proc->startThreadPool();//启动一个线程 用于binder通信}       }private static void invokeStaticMain(String className, String[] argv)throws ZygoteInit.MethodAndArgsCaller { //classname是SStry { //找到SS的main函数m = cl.getMethod("main", new Class[] { String[].class });} //最后抛出了一个异常    throw new ZygoteInit.MethodAndArgsCaller(m, argv);
    }

    在zygoteInit函数中,捕获到了这个函数,然后直接调用caller.run函数

 

在run函数中调用了SS的main函数

但是为什么要抛出异常后再调用??

这是因为在zygoteInit.main中调用,相当于native的main函数,即入口函数,位于堆栈的顶层,如果不采用抛出异常的方式,就会直接在 invokeStaticMain里调用,就会浪费之前函数调用所占用的一些调用堆栈

Zygote的分裂就是为了调用SS的main函数

public static void main(String[] args) {
System.loadLibrary("android_servers");//加载libandroid_server.so库init1(args);
}

init1是native函数,调用了system_init方法,

 frameworks/base/cmds/system_server/library

extern "C" status_t system_init()
{
sp proc(ProcessState::self());sp sm = defaultServiceManager();    sm->asBinder()->linkToDeath(grim, grim.get(), 0);//binder通信AndroidRuntime* runtime = AndroidRuntime::getRuntime();
runtime->callStatic("com/android/server/SystemServer", "init2");//init2
}

Init2在SS.java中,

class ServerThread extends Thread {
//启动Entropy Service
ServiceManager.addService("entropy", new EntropyService());
//启动电源管理服务
power = new PowerManagerService();
ServiceManager.addService(Context.POWER_SERVICE, power);
//启动电池管理服务
battery = new BatteryService(context);
ServiceManager.addService("battery", battery);
//启动windowsManger服务wm = WindowManagerService.main(context, power,factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL);ServiceManager.addService(Context.WINDOW_SERVICE, wm);
//启动activityManger服务等 Java核心service
...
//进行消息循环
Looper.loop();
}

Zygote的分裂

Zygote第四步,在分裂出SS后,就通过runSelectLoopMode等待并处理来自客户的消息了,谁会给zygote发消息呢?

ActivityManagerService(以下简称AMS)

AMS是由SS创建的,以启动一个Activity为例,而这个Activity属于一个还未启动的进程中,AMS.java中代码量很多,看其中一个方法startProcessLocked。

private final void startProcessLocked(ProcessRecord app,String hostingType, String hostingNameStr) {int pid = Process.start("android.app.ActivityThread",mSimpleProcessManagement ? app.processName : null, uid, uid,gids, debugFlags, null);}

 调用了framework/base/core/java/android/os/Process.java里的start方法。

public static final int start(final String processClass,final String niceName,int uid, int gid, int[] gids,int debugFlags,String[] zygoteArgs){
if (supportsProcesses()) {return startViaZygote(processClass, niceName, uid, gid, gids,debugFlags, zygoteArgs);
}
}
private static int startViaZygote(final String processClass, final String niceName, final int uid, final int gid,final int[] gids,int debugFlags,String[] extraArgs) throws ZygoteStartFailedEx {argsForZygote.add("--runtime-init");//做一些参数处理
pid = zygoteSendArgsAndGetPid(argsForZygote); //调用如下函数
return pid;
}private static int zygoteSendArgsAndGetPid(ArrayList args) throws ZygoteStartFailedEx {openZygoteSocketIfNeeded();//打开和zygote通信的socketsZygoteWriter.write(Integer.toString(args.size()));//把要请求的参数发到zygote
sZygoteWriter.newLine();
sZygoteWriter.write(arg);
sZygoteWriter.newLine();
pid = sZygoteInputStream.readInt();//读取zygote处理完的结果便可知是某个进程的pid
}

根绝zygote(上)的介绍中可以ZygoteInit中是通过ZygoteConnection的runOnce函数进行处理,

boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {args = readArgumentList();//读取SS发过来的参数pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,//分裂出一个子进程if (pid == 0) {handleChildProc(parsedArgs, descriptors, newStderr); //处理子进程return true;} else {return handleParentProc(pid, descriptors, parsedArgs); //zygote进程}
}
private void handleChildProc(Arguments parsedArgs,FileDescriptor[] descriptors, PrintStream newStderr)throws ZygoteInit.MethodAndArgsCaller {
if (parsedArgs.runtimeInit) {//之前SS传入的参数有runtimeInit 为trueRuntimeInit.zygoteInit(parsedArgs.remainingArgs);} 
}

最后在RuntimeInit.zygoteInit中还是调用了invokeStaticMain 函数。这个函数上文讲过

 

相关内容

热门资讯

保存时出现了1个错误,导致这篇... 当保存文章时出现错误时,可以通过以下步骤解决问题:查看错误信息:查看错误提示信息可以帮助我们了解具体...
汇川伺服电机位置控制模式参数配... 1. 基本控制参数设置 1)设置位置控制模式   2)绝对值位置线性模...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
表格中数据未显示 当表格中的数据未显示时,可能是由于以下几个原因导致的:HTML代码问题:检查表格的HTML代码是否正...
本地主机上的图像未显示 问题描述:在本地主机上显示图像时,图像未能正常显示。解决方法:以下是一些可能的解决方法,具体取决于问...
表格列调整大小出现问题 问题描述:表格列调整大小出现问题,无法正常调整列宽。解决方法:检查表格的布局方式是否正确。确保表格使...
不一致的条件格式 要解决不一致的条件格式问题,可以按照以下步骤进行:确定条件格式的规则:首先,需要明确条件格式的规则是...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...