当前位置: 首页 > news >正文

网站如何清除百度收录/长春网长春关键词排名站设计

网站如何清除百度收录,长春网长春关键词排名站设计,轻松学html css网站开发,wordpress 隐藏播放器本文已授权微信公众号《鸿洋》原创首发,转载请务必注明出处。 Zygote进程是Android和Java世界的开创者。在android系统中,所有的应用进程和SystemServer进程都是由Zygote进程fork而来。其重要性由此可见一斑。虽然Zygote进程相当于Android系统的根进程&a…

本文已授权微信公众号《鸿洋》原创首发,转载请务必注明出处。

Zygote进程是AndroidJava世界的开创者。在android系统中,所有的应用进程和SystemServer进程都是由Zygote进程fork而来。其重要性由此可见一斑。虽然Zygote进程相当于Android系统的根进程,但是事实上它也是由Linux系统的init进程启动的。各个进程的先后顺序为:

init进程 –-> Zygote进程 –> SystemServer进程 –>应用进程

其中Zygote进程由init进程启动,SystemServer进程和应用进程由Zygote进程启动。本文依据6.0源码,主要分析Zygote进程的启动流程。init进程在启动Zygote进程时会调用ZygoteInit#main()。以此为切入点,一步步分析。

源码位置:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

流程概览

ZygoteInit#main();

public static void main(String argv[]) {try {// 设置DDMS可用RuntimeInit.enableDdms();// 初始化启动参数boolean startSystemServer = false;String socketName = "zygote";String abiList = null;for (int i = 1; i < argv.length; i++) {if ("start-system-server".equals(argv[i])) {startSystemServer = true;} else if (argv[i].startsWith(ABI_LIST_ARG)) {abiList = argv[i].substring(ABI_LIST_ARG.length());} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {socketName = argv[i].substring(SOCKET_NAME_ARG.length());} else {throw new RuntimeException("Unknown command line argument: " + argv[i]);}}// 注册socketregisterZygoteSocket(socketName);// 预加载各种资源preload();...if (startSystemServer) {// 启动SystemServer进程startSystemServer(abiList, socketName);}// 监听socket,启动新的应用进程。--后文会讲runSelectLoop(abiList);closeServerSocket();} catch (MethodAndArgsCaller caller) {// 通过反射调用SystemServer#main()--后文会讲caller.run();} catch (RuntimeException ex) {closeServerSocket();throw ex;}
}

上面是个大概流程,下面会依据源码一步步解释。设置DDMS可用之后初始化各种参数,在此之后注册为Zygote进程注册Socket,预加载各种资源,但这些都不是重点!同学们,重点在于startSystemServer(abiList, socketName)(手敲黑板状)!下面简单贴下registerZygoteSocket(socketName)preload()源码,不感兴趣的同学可直接略过下面两段代码。

ZygoteInit#registerZygoteSocket()

private static void registerZygoteSocket(String socketName) {if (sServerSocket == null) {int fileDesc;final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;...FileDescriptor fd = new FileDescriptor();fd.setInt$(fileDesc);// 不是使用IP和端口、而是使用fd创建socketsServerSocket = new LocalServerSocket(fd);...}
}

ZygoteInit#registerZygoteSocket()

static void preload() {preloadClasses(); // 加载所需的各种class文件preloadResources(); // 加载资源文件preloadOpenGL(); // 初始化OpenGLpreloadSharedLibraries(); // 加载系统LibrariespreloadTextResources(); //加载文字资源WebViewFactory.prepareWebViewInZygote(); // 初始化WebView
}

启动SystemServer进程

跟进startSystemServer()

private static boolean startSystemServer(String abiList, String socketName) throws MethodAndArgsCaller, RuntimeException {long capabilities = posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND,OsConstants.CAP_KILL,...);/* Hardcoded command line to start the system server */String args[] = {"--setuid=1000","--setgid=1000","--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007","--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);// 请求fork SystemServer进程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表示子进程,即SystemServer进程,从此SystemServer进程与Zygote进程分道扬镳if (pid == 0) {if (hasSecondZygote(abiList)) {waitForSecondaryZygote(socketName);}handleSystemServerProcess(parsedArgs);}return true;
}

前面一大段都在构造参数,直接进到try中的代码块。首先根据args数组构造了一个ZygoteConnection.Arguments,然后根据parsedArgs对象的各种参数调用Zygote#forkSyatemServer()方法fork出第一个子进程,也就是SystemServer进程。最后通过执行handleSystemServerProcess反射调用SystemServer#main()。可以看到,这段代码最主要的作用就是forkSystemServer进程。这里还看不出反射调用的具体细节,下文会一一分析。

首先看下构造ZygoteConnection.Arguments对象时,具体都做了哪些工作,尤其关注Zygote#forkSystemServer()中几个参数的值。

源码位置:frameworks/base/core/java/com/android/internal/os/ZygoteConnection$Arguments.java

    Arguments(String args[]) throws IllegalArgumentException {parseArgs(args);}private void parseArgs(String args[]) throws IllegalArgumentException {int curArg = 0;boolean seenRuntimeArgs = false;for ( /* curArg */ ; curArg < args.length; curArg++) {String arg = args[curArg];if (arg.equals("--")) {curArg++;break;} else if (arg.startsWith("--setuid=")) {if (uidSpecified) {throw new IllegalArgumentException("Duplicate arg specified");}uidSpecified = true;uid = Integer.parseInt(arg.substring(arg.indexOf('=') + 1));} else if (arg.startsWith("--setgid=")) {if (gidSpecified) {gidSpecified = true;gid = Integer.parseInt(arg.substring(arg.indexOf('=') + 1));} else if (arg.startsWith("--target-sdk-version=")) {targetSdkVersionSpecified = true;targetSdkVersion = Integer.parseInt(arg.substring(arg.indexOf('=') + 1));} ...else if (arg.equals("--runtime-args")) {seenRuntimeArgs = true;} else if (arg.startsWith("--capabilities=")) {capabilitiesSpecified = true;String capString = arg.substring(arg.indexOf('=')+1);String[] capStrings = capString.split(",", 2);if (capStrings.length == 1) {effectiveCapabilities = Long.decode(capStrings[0]);permittedCapabilities = effectiveCapabilities;} else {permittedCapabilities = Long.decode(capStrings[0]);effectiveCapabilities = Long.decode(capStrings[1]);}} else if (arg.startsWith("--setgroups=")) {String[] params = arg.substring(arg.indexOf('=') + 1).split(",");gids = new int[params.length];for (int i = params.length - 1; i >= 0 ; i--) {gids[i] = Integer.parseInt(params[i]);}} else if (arg.startsWith("--nice-name=")) {niceName = arg.substring(arg.indexOf('=') + 1);} else {break;}}// 保存没有被解析的参数remainingArgs = new String[args.length - curArg];System.arraycopy(args, curArg, remainingArgs, 0, remainingArgs.length);    }

对比传入的args数组,可以发现:parsedArgs.uid=1000parsedArgs.gid=1000parsedArgs.gids={"1001","1002",..."3007"}parsedArgs.gid=1000parsedArgs.niceName=system_serverparsedArgs.seenRuntimeArgs=true。如果中途结束,保存未解析的参数至remainingArgs数组。
获得Arguments对象之后,就开始请求创建SystemServer进程。

源码位置:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

ZygoteInit#handleSystemServerProcess()

  private static void handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs)throws ZygoteInit.MethodAndArgsCaller {closeServerSocket();if (parsedArgs.niceName != null) {Process.setArgV0(parsedArgs.niceName);}...// 默认为nullif (parsedArgs.invokeWith != null) {...} else {...RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);}/* should never reach here */
}

Zygote创建的子进程默认拥有Zygote进程的Socket对象,而子进程又用不上,所以先调用closeServerSocket()关闭它。上一段参数解析时写道:parsedArgs.niceName=system_server,在这里调用Process.setArgV0()设置进程名为:system_server。由于parsedArgs.invokeWith属性默认为null,最后调用RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl)来进一步启动SystemServer,这里的参数parsedArgs.remainingArgs就是上文中保存没有被解析对象的数组。

源码位置:frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

RuntimeInit#zygoteInit()

public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller {// 重定向Log输出redirectLogStreams();//初始化运行环境commonInit();//启动Binder线程池nativeZygoteInit();//调用程序入口函数applicationInit(targetSdkVersion, argv, classLoader);
}

RuntimeInit#applicationInit()

private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)throws ZygoteInit.MethodAndArgsCaller {// 初始化虚拟机环境VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);final Arguments args;try {args = new Arguments(argv);} catch (IllegalArgumentException ex) {return;}// Remaining arguments are passed to the start class's static maininvokeStaticMain(args.startClass, args.startArgs, classLoader);
}

RuntimeInit#invokeStaticMain()

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)throws ZygoteInit.MethodAndArgsCaller {Class<?> cl;try {cl = Class.forName(className, true, classLoader);} catch (ClassNotFoundException ex) {throw new RuntimeException("Missing class when invoking static main " +    className, ex);}Method m;try {// 获取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);}// 判断修饰符int modifiers = m.getModifiers();if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {throw new RuntimeException("Main method is not public and static on " + className);}throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}

这里传入的className就是com.android.server.SystemServer,然后获取main方法,接着判断修饰符,必须是static而且必须是public类型。最有意思的莫过于做完这一切之后,抛出了个MethodAndArgsCaller异常。辛苦辛苦各种初始化,各种变着法儿的调用,最后你居然给我抛个异常!!先别急,这个异常在Zygote#main()方法中捕获。这么做的作用是清除应用程序进程创建过程的调用栈。

 public static void main(String argv[]) {try {...startSystemServer(abiList, socketName);...} catch (MethodAndArgsCaller caller) {caller.run();}
}

跟进MethodAndArgsCaller#run(),感觉要出大事情!!

  public void run() {try {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);}}

我就说要出大事情!我就说要出大事情!!我就说要出大事情!!!可以看到在这里通过反射调用了com.android.server.SystemServer#main(String[] args)。至此,Zygote进程forSystemServer进程,并成功调用SystemServer#main()

现在SystemServer进程也创建了,main方法也调用了。Zygote进程的使命就此完结了吗?上文我们说道:所有的应用进程和SystemServer进程都是由Zygote进程fork而来。现在有关SystemServer进程的已经告一段落,那有关应用进程呢?

让我们再次回到ZygoteInit#main()

public static void main(String argv[]) {...startSystemServer(abiList, socketName);runSelectLoop(abiList);closeServerSocket();
}

main方法中前面所有的代码好像都和应用进程没有关系,最后一行又是关闭socket,看来和应用进程相关的设置都在runSelectLoop()中,跟进。

监听Socket,启动应用进程

ZygoteInit#runSelectLoop()、ZygoteInit#acceptCommandPeer()

private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();FileDescriptor[] fdArray = new FileDescriptor[4];fds.add(sServerSocket.getFileDescriptor());peers.add(null);int loopCount = GC_LOOP_COUNT;while (true) {int index;if (loopCount <= 0) {gc();loopCount = GC_LOOP_COUNT;} else {loopCount--;}try {fdArray = fds.toArray(fdArray);index = selectReadable(fdArray);} catch (IOException ex) {throw new RuntimeException("Error in select()", ex);}if (index < 0) {throw new RuntimeException("Error in select()");} else if (index == 0) {ZygoteConnection newPeer = acceptCommandPeer(abiList);peers.add(newPeer);fds.add(newPeer.getFileDescriptor());} else {boolean done;done = peers.get(index).runOnce();if (done) {peers.remove(index);fds.remove(index);}}}
}private static ZygoteConnection acceptCommandPeer(String abiList) {try {return new ZygoteConnection(sServerSocket.accept(), abiList);} catch (IOException ex) {throw new RuntimeException("IOException during accept()", ex);}
}

这里有个死循环,一直监听socket,然后调用ZygoteConnection#runOnce(),从函数名runOnce上感觉真相就要呼之欲出了,跟进。

源码位置:frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

ZygoteConnection#runOnce()

boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {String args[];args = readArgumentList();parsedArgs = new Arguments(args);try {...pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,parsedArgs.appDataDir);} catch (ErrnoException ex) {logAndPrintError(newStderr, "Exception creating pipe", ex);} catch (IllegalArgumentException ex) {logAndPrintError(newStderr, "Invalid zygote arguments", ex);} catch (ZygoteSecurityException ex) {logAndPrintError(newStderr,"Zygote security policy prevents request: ", ex);}try {if (pid == 0) {// in childIoUtils.closeQuietly(serverPipeFd);serverPipeFd = null;handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);// should never get here, the child is expected to either// throw ZygoteInit.MethodAndArgsCaller or exec().return true;} else {// in parent...pid of < 0 means failureIoUtils.closeQuietly(childPipeFd);childPipeFd = null;return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);}} finally {IoUtils.closeQuietly(childPipeFd);IoUtils.closeQuietly(serverPipeFd);}
}

和启动SystemServer进程类似。这里调用Zygote#forkAndSpecialize()创建应用进程,而参数parsedArgs是通过socket一行行读出来的。详见ZygoteConnection#readArgumentList()

private String[] readArgumentList() throws IOException {int argc;try {String s = mSocketReader.readLine();if (s == null) {return null;}argc = Integer.parseInt(s);} catch (NumberFormatException ex) {throw new IOException("invalid wire format");}if (argc > MAX_ZYGOTE_ARGC) {throw new IOException("max arg count exceeded");}String[] result = new String[argc];for (int i = 0; i < argc; i++) {result[i] = mSocketReader.readLine();if (result[i] == null) {// We got an unexpected EOF.throw new IOException("truncated request");}}return result;
}

因为还没有看发送Socket消息的源码,这里斗胆猜测:应该是uid、gid、niceName等参数。

通过Socket读取完各种参数之后,调用ZygoteConnection#handleChildProc(),创建完应用程序进程之后就该调用应用程序的入口方法了。跟进。

private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)throws ZygoteInit.MethodAndArgsCaller {// 关闭从Zygote进程复制过来的Socket连接  closeSocket();ZygoteInit.closeServerSocket();if (parsedArgs.niceName != null) {Process.setArgV0(parsedArgs.niceName);}...RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, null /* classLoader */);
}

最后调用RuntimeInit#zygoteInit(),后面的就和SystemServer启动流程类似。感兴趣的同学自行查看。

总结一下Zygote启动流程:

  1. 初始化DDMS

  2. 注册Zygote进程的Socket

  3. 加载classresourceOpenGLWebView等各种资源

  4. forkSystemServer进程

  5. 启动SystemServer进程

  6. 调用runSelectLoop()一直监听Socket信息

  7. 收到创建应用程序Socket消息,调用ZygoteConnection#runOnce()。在runOnce()中调用Zygote#forkAndSpecialize()创建应用进程

  8. 启动应用进程


更多Framework源码解析,请移步 Framework源码解析系列[目录]

http://www.jmfq.cn/news/5199517.html

相关文章:

  • 十堰秦楚网论坛十堰城事/百度seo是啥
  • 义乌设计网站/长沙百度推广运营公司
  • 沈阳手机网站制作/债务优化是什么意思
  • 四川网站制作/东莞seo项目优化方法
  • 南安网站定制/seo门户网站优化
  • 免费做宣传单页的网站/优化营商环境工作开展情况汇报
  • 网站域名服务器一年多少钱/网络推广应该怎么做啊
  • 天津建设局网站/seo关键词排名优化怎么样
  • wordpress如何修改首页/宁波关键词优化企业网站建设
  • 高端网站制作软件/产品营销策略有哪些
  • wordpress首页代码/seo营销排名
  • 做网站失败/做网站需要多少钱
  • 公司网站建设注意事项/大数据培训班需要多少钱
  • 赤壁专业建站公司/苏州百度
  • 建个网站 费用/软文推广发布平台
  • 公众号做淘宝客接入手机网站/搜索引擎调词平台哪个好
  • 做暧小视频xo网站/产品推广软文300字
  • 搜狗竞价绑定网站要求/社群推广平台
  • wix网站怎么做/太原百度推广排名优化
  • 网站上怎样做超链接/个人网站建设
  • 夜雨直播nba/网站优化靠谱seo
  • 网站设计 成都/深圳十大教育培训机构排名
  • 相亲网站做期货现货贵金属的人/网络seo推广
  • linux 配置网站域名/找客户资源的软件
  • 鄂州网站推广优化技巧/哈尔滨优化推广公司
  • 增城移动网站建设/搜索推广出价多少合适
  • 网页设计教程 罗云芳吴黎/seo专业培训费用
  • 专业网站建设微信官网开发/安卓优化软件
  • 做旅游网站的工作流程图/网站推广互联网推广
  • 个人网站怎么做扫码支付/绍兴百度seo排名