system_server进程创建流程

news2024/9/26 3:32:48

system_server 进程是 Zygote 进程 fork 出的第一个进程,它负责管理和启动整个 Framework 层,下面附上android系统启动流程图:

记得上一篇Zygote进程创建里面提到过,forckSystemServer创建system_server进程。

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java 中代码如下:

下面是forkSystemServer 里面的代码: 

 Zygote.forkSystemServer 返回的是一个int型的pid,如果pid不等于0,代表的是在父进程中执行,即

Zygote进程,如果pid等于0,代表在子进程中执行。

 最终执行handleSystemServerProcess,是在system_server进程中执行。

接下来看handleSystemServerProcess方法

 /**
499       * Finish remaining work for the newly forked system server process.
500       */
501      private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
502          // set umask to 0077 so new files and directories will default to owner-only permissions.
503          Os.umask(S_IRWXG | S_IRWXO);
504  
505          if (parsedArgs.mNiceName != null) {
506              Process.setArgV0(parsedArgs.mNiceName);
507          }
508  
509          final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
510          if (systemServerClasspath != null) {
511              performSystemServerDexOpt(systemServerClasspath);
512              // Capturing profiles is only supported for debug or eng builds since selinux normally
513              // prevents it.
514              if (shouldProfileSystemServer() && (Build.IS_USERDEBUG || Build.IS_ENG)) {
515                  try {
516                      Log.d(TAG, "Preparing system server profile");
517                      prepareSystemServerProfile(systemServerClasspath);
518                  } catch (Exception e) {
519                      Log.wtf(TAG, "Failed to set up system server profile", e);
520                  }
521              }
522          }
523  
524          if (parsedArgs.mInvokeWith != null) {
525              String[] args = parsedArgs.mRemainingArgs;
526              // If we have a non-null system server class path, we'll have to duplicate the
527              // existing arguments and append the classpath to it. ART will handle the classpath
528              // correctly when we exec a new process.
529              if (systemServerClasspath != null) {
530                  String[] amendedArgs = new String[args.length + 2];
531                  amendedArgs[0] = "-cp";
532                  amendedArgs[1] = systemServerClasspath;
533                  System.arraycopy(args, 0, amendedArgs, 2, args.length);
534                  args = amendedArgs;
535              }
536  
537              WrapperInit.execApplication(parsedArgs.mInvokeWith,
538                      parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
539                      VMRuntime.getCurrentInstructionSet(), null, args);
540  
541              throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
542          } else {
543              ClassLoader cl = null;
544              if (systemServerClasspath != null) {
545                  cl = createPathClassLoader(systemServerClasspath, parsedArgs.mTargetSdkVersion);
546  
547                  Thread.currentThread().setContextClassLoader(cl);
548              }
549  
550              /*
551               * Pass the remaining arguments to SystemServer.
552               */
553              return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
554                      parsedArgs.mDisabledCompatChanges,
555                      parsedArgs.mRemainingArgs, cl);
556          }
557  
558          /* should never reach here */
559      }

 最终执行到ZygoteInit.zygoteInit方法,点进去看一下

     /**
978       * The main function called when started through the zygote process. This could be unified with
979       * main(), if the native code in nativeFinishInit() were rationalized with Zygote startup.<p>
980       *
981       * Current recognized args:
982       * <ul>
983       * <li> <code> [--] &lt;start class name&gt;  &lt;args&gt;
984       * </ul>
985       *
986       * @param targetSdkVersion target SDK version
987       * @param disabledCompatChanges set of disabled compat changes for the process (all others
988       *                              are enabled)
989       * @param argv             arg strings
990       */
991      public static final Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
992              String[] argv, ClassLoader classLoader) {
993          if (RuntimeInit.DEBUG) {
994              Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
995          }
996  
997          Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
998          RuntimeInit.redirectLogStreams();
999  
1000          RuntimeInit.commonInit();
1001          ZygoteInit.nativeZygoteInit();
1002          return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
1003                  classLoader);
1004      }

再看看RuntimeInit.applicationInit方法

 protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
405              String[] argv, ClassLoader classLoader) {
406          // If the application calls System.exit(), terminate the process
407          // immediately without running any shutdown hooks.  It is not possible to
408          // shutdown an Android application gracefully.  Among other things, the
409          // Android runtime shutdown hooks close the Binder driver, which can cause
410          // leftover running threads to crash before the process actually exits.
411          nativeSetExitWithoutCleanup(true);
412  
413          VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
414          VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges);
415  
416          final Arguments args = new Arguments(argv);
417  
418          // The end of of the RuntimeInit event (see #zygoteInit).
419          Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
420  
421          // Remaining arguments are passed to the start class's static main
422          return findStaticMain(args.startClass, args.startArgs, classLoader);
423      }

 最终执行的是findStaticMain方法

 /**
337       * Invokes a static "main(argv[]) method on class "className".
338       * Converts various failing exceptions into RuntimeExceptions, with
339       * the assumption that they will then cause the VM instance to exit.
340       *
341       * @param className Fully-qualified class name
342       * @param argv Argument vector for main()
343       * @param classLoader the classLoader to load {@className} with
344       */
345      protected static Runnable findStaticMain(String className, String[] argv,
346              ClassLoader classLoader) {
347          Class<?> cl;
348  
349          try {
350              cl = Class.forName(className, true, classLoader);
351          } catch (ClassNotFoundException ex) {
352              throw new RuntimeException(
353                      "Missing class when invoking static main " + className,
354                      ex);
355          }
356  
357          Method m;
358          try {
359              m = cl.getMethod("main", new Class[] { String[].class });
360          } catch (NoSuchMethodException ex) {
361              throw new RuntimeException(
362                      "Missing static main on " + className, ex);
363          } catch (SecurityException ex) {
364              throw new RuntimeException(
365                      "Problem getting static main on " + className, ex);
366          }
367  
368          int modifiers = m.getModifiers();
369          if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
370              throw new RuntimeException(
371                      "Main method is not public and static on " + className);
372          }
373  
374          /*
375           * This throw gets caught in ZygoteInit.main(), which responds
376           * by invoking the exception's run() method. This arrangement
377           * clears up all the stack frames that were required in setting
378           * up the process.
379           */
380          return new MethodAndArgsCaller(m, argv);
381      }

 再看看 MethodAndArgsCaller

  /**
575       * Helper class which holds a method and arguments and can call them. This is used as part of
576       * a trampoline to get rid of the initial process setup stack frames.
577       */
578      static class MethodAndArgsCaller implements Runnable {
579          /** method to call */
580          private final Method mMethod;
581  
582          /** argument array */
583          private final String[] mArgs;
584  
585          public MethodAndArgsCaller(Method method, String[] args) {
586              mMethod = method;
587              mArgs = args;
588          }
589  
590          public void run() {
591              try {
592                  mMethod.invoke(null, new Object[] { mArgs });
593              } catch (IllegalAccessException ex) {
594                  throw new RuntimeException(ex);
595              } catch (InvocationTargetException ex) {
596                  Throwable cause = ex.getCause();
597                  if (cause instanceof RuntimeException) {
598                      throw (RuntimeException) cause;
599                  } else if (cause instanceof Error) {
600                      throw (Error) cause;
601                  }
602                  throw new RuntimeException(ex);
603              }
604          }
605      }
606  }

这样一看就知道通过反射来调用方法的

最后回过头来看下顶部的代码图片

返回的Runnable对象,执行run, 执行system_server main 方法,然后return了。

接下来我们看SystemServer main 方法

/**
411       * The main entry point from zygote.
412       */
413      public static void main(String[] args) {
414          new SystemServer().run();
415      }

run代码中大致分为11个步骤:

1.设定时间

//
450              // Default the timezone property to GMT if not set.
451              //
452              String timezoneProperty = SystemProperties.get("persist.sys.timezone");
453              if (timezoneProperty == null || timezoneProperty.isEmpty()) {
454                  Slog.w(TAG, "Timezone not set; setting to GMT.");
455                  SystemProperties.set("persist.sys.timezone", "GMT");
456              }
457  

2.设定语言

// If the system has "persist.sys.language" and friends set, replace them with
459              // "persist.sys.locale". Note that the default locale at this point is calculated
460              // using the "-Duser.locale" command line flag. That flag is usually populated by
461              // AndroidRuntime using the same set of system properties, but only the system_server
462              // and system apps are allowed to set them.
463              //
464              // NOTE: Most changes made here will need an equivalent change to
465              // core/jni/AndroidRuntime.cpp
466              if (!SystemProperties.get("persist.sys.language").isEmpty()) {
467                  final String languageTag = Locale.getDefault().toLanguageTag();
468  
469                  SystemProperties.set("persist.sys.locale", languageTag);
470                  SystemProperties.set("persist.sys.language", "");
471                  SystemProperties.set("persist.sys.country", "");
472                  SystemProperties.set("persist.sys.localevar", "");
473              }
474  

3.虚拟机库文件路径

  // In case the runtime switched since last boot (such as when
498              // the old runtime was removed in an OTA), set the system
499              // property so that it is in sync. We can't do this in
500              // libnativehelper's JniInvocation::Init code where we already
501              // had to fallback to a different runtime because it is
502              // running as root and we need to be the system user to set
503              // the property. http://b/11463182
504              SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());

4.清除内存使用上限

 // Mmmmmm... more memory!
507              VMRuntime.getRuntime().clearGrowthLimit();

5.设定指纹使用

             // Some devices rely on runtime fingerprint generation, so make sure
510              // we've defined it before booting further.
511              Build.ensureFingerprintProperty();

6.设定环境变量访问用户条件

             // Within the system server, it is an error to access Environment paths without
514              // explicitly specifying a user.
515              Environment.setUserRequired(true);

7.设定binder服务永远运行在前台

             // Ensure binder calls into the system always run at foreground priority.
525              BinderInternal.disableBackgroundScheduling(true);

8.设定线程池最大线程数


527              // Increase the number of binder threads in system_server
528              BinderInternal.setMaxThreads(sMaxBinderThreads);

9.启动各种服务

 // Start services.
594          try {
595              t.traceBegin("StartServices");
596              startBootstrapServices(t);
597              startCoreServices(t);
598              startOtherServices(t);
599          } catch (Throwable ex) {
600              Slog.e("System", "******************************************");
601              Slog.e("System", "************ Failure starting system services", ex);
602              throw ex;
603          } finally {
604              t.traceEnd(); // StartServices
605          }
606  
607          StrictMode.initVmDefaults(null);
608  
609          if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {
610              final long uptimeMillis = SystemClock.elapsedRealtime();
611              FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
612                      FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__SYSTEM_SERVER_READY,
613                      uptimeMillis);
614              final long maxUptimeMillis = 60 * 1000;
615              if (uptimeMillis > maxUptimeMillis) {
616                  Slog.wtf(SYSTEM_SERVER_TIMING_TAG,
617                          "SystemServer init took too long. uptimeMillis=" + uptimeMillis);
618              }
619          }
620  
621          // Diagnostic to ensure that the system is in a base healthy state. Done here as a common
622          // non-zygote process.
623          if (!VMRuntime.hasBootImageSpaces()) {
624              Slog.wtf(TAG, "Runtime is not running with a boot image!");
625          }
626  

10.服务开启循环

  // Loop forever.
628          Looper.loop();

启动系统上下文

   // Initialize the system context.
556              createSystemContext();
 private void createSystemContext() {
696          ActivityThread activityThread = ActivityThread.systemMain();
697          mSystemContext = activityThread.getSystemContext();
698          mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
699  
700          final Context systemUiContext = activityThread.getSystemUiContext();
701          systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
702      }

创建SystemServiceManager


561              // Create the system service manager.
562              mSystemServiceManager = new SystemServiceManager(mSystemContext);
563              mSystemServiceManager.setStartInfo(mRuntimeRestart,
564                      mRuntimeStartElapsedTime, mRuntimeStartUptime);
565              LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
566              // Prepare the thread pool for init tasks that can be parallelized
567              SystemServerInitThreadPool.start();

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1414844.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

nginx负载均衡-轮询

实验使用ubuntu做主机 1.安装nginx 安装依赖 sudo apt install libgd-dev 下载nginx wget http://nginx.org/download/nginx-1.22.1.tar.gz 解压nginx tar -zvxf nginx-1.22.1.tar.gz 编译安装 cd nginx-1.22.1 编译并指定安装位置&#xff0c;执行安装之后会创建指定…

鸿蒙APP的应用场景

鸿蒙APP可以用于多种场合和设备类型&#xff0c;这是鸿蒙系统的分布式能力和多终端适配的优势。以下是一些鸿蒙APP的应用场景&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1.智能手机和平板电脑&am…

【听力与言语医学中心系列科普16】听力检查之纯音听阈测定

当我们去医院向医生诉说我们耳朵有问题时&#xff0c;最常听到医生说的是“去做个测听”吧&#xff0c;那么什么是测听&#xff1f;做测听有什么作用呢&#xff1f; 一、什么是纯音测听纯音听力测试自1943年Bunch教授发表后&#xff0c;就被作为首选的测听方法。纯音测听是测试…

一键轻松,免费创造:QuickQR带你体验AI二维码的轻松生成!

当今时代&#xff0c;将信息快速转变为可扫描图案&#xff0c;以简化人们的生活和工作方式&#xff0c;二维码技术展现了它强大的功能。特别是在分享链接、联系信息或进行支付时&#xff0c;二维码已成为现代社会一个不可或缺的部分。本文将探讨生成AI二维码的一种工具&#xf…

Linux服务器配置与管理(第三次实验)

实验目的及具体要求 目的 1.熟悉Shell 脚本语法 2.掌握创建脚本的方法 3.掌握运行脚本的方法 4.掌握变量及表达式 5.掌握Shell 控制结构 6.掌握Shell 函数 任务 1.显示当前日期时间、执行路径、用户账户及所在的目录位置 2.判断一个文件是不是字符设备文件&#xff0…

首发:2024全球DAO组织发展研究

作者&#xff0c;张群&#xff08;专注DAO及区块链应用研究&#xff0c;赛联区块链教育首席讲师&#xff0c;工信部赛迪特邀资深专家&#xff0c;CSDN认证业界专家&#xff0c;微软认证专家&#xff0c;多家企业区块链产品顾问&#xff09; DAO&#xff08;去中心化自治组织&am…

手把手教学:AD09制作BOM及小技巧

BOM&#xff08;Bill of Material&#xff09;物料清单&#xff0c;是以数据格式来描述产品结构的文件&#xff0c;即生产一件产品所需的子零件及其产品中零件数量的完全组合。这里生成BOM表用作对你制作的pcb板进行成本预估和制作生产资料文件。同时也是样品制作时&#xff0c…

2024.1.25 C++QT 作业

思维导图 练习题 1. 自己封装一个矩形类(Rect)&#xff0c;拥有私有属性:宽度(width)、高度(height)&#xff0c; 定义公有成员函数: 初始化函数:void init(int w, int h) 更改宽度的函数:set_w(int w) 更改高度的函数:set_h(int h) 输出该矩形的周长和面积函数:void sh…

策略者模式-C#实现

该实例基于WPF实现&#xff0c;直接上代码&#xff0c;下面为三层架构的代码。 目录 一 Model 二 View 三 ViewModel 一 Model using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace 设计模式练…

JavaWeb01--Tomcat

1、JavaWeb概述 Web开发是基于请求和响应的&#xff1a; 请求&#xff1a;浏览器&#xff08;客户端&#xff09;向服务器发送信息 响应&#xff1a;服务器向浏览器回送信息 请求和响应是成对出现的。 Web资源分类 所谓Web资源即放在Internet网上供外界访问的文件或程序&#x…

[java基础揉碎]break跳出循环的标签使用方式(continue同理)

语法: (1)break 语句可以指定退出哪层 (2)label1是标签&#xff0c;由程序员指定 (3)break 后指定到哪个label 就退出到哪里 (4)在实际的开发中&#xff0c;尽量不要使用标签(可读性会变差), 除非有业务逻辑需要必须使用迫不得已 (5)如果没有指定break,默认退出最近的循环体…

new mars3d.layer.WeiVectorTileLayer({在Mars3d官网个api搜索不到的说明

前景&#xff1a;new mars3d.layer.WeiVectorTileLayer({在Mars3d官网个api搜索不到的说明 说明&#xff1a; 可以下载示例git clone https://gitee.com/marsgis/mars3d-vue-example.git 参考api文档的Cesium.VectorStyle类&#xff0c;这个类可以在示例的thirdParty下面进行…

sql 行转列 日周月 图表统计

目录 目录 需求 准备 月 分析 按月分组 行转列 错误版本 正确版本 日 分析 行转列 周 分析 按周分组 行转列 本年 需求 页面有三个按钮 日周月&#xff0c;统计一周中每天(日)&#xff0c;一月中每周(周)&#xff0c;一年中每月(月)&#xff0c;设备台数 点…

ROS2学习笔记(0)开坑声明

0.前提 在做racecar的过程中发现已经有不少的开发者和公司开始从ros1转向ros2的怀抱了&#xff0c;刚好寒假在家&#xff0c;我就顺带试试看能不能学点ros2&#xff0c;刚好我有两辆车和主板可以双线开工&#xff08;是的&#xff0c;全是老师们赞助的&#xff0c;真的我哭死&…

DDPM的一点笔记

1 Title Denoising Diffusion Probabilistic Models&#xff08;Jonathan Ho、Ajay Jain、Pieter Abbeel&#xff09; 2 Conclusion This paper present high quality image synthesis results using diffusion probabilistic models, a class of latent variable models insp…

Two-factor authentication (2FA) is required for your GitHub account解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

物联网IOT: 风浆叶片拧紧装配及实时监测系统

某大型风电设备,通过机器人应用与精益化生产体系的融合,打造出行业领先的具备柔性生产能力的“脉动式”生产体系。同时在关键工序上。其中,在叶片装配等关键工序上使用由智能机器人代替人工,以提高生产的效率和装配质量可靠性,将六轴机器人、视觉系统、光电系统、液压、气动、伺…

计算机设计大赛 图像识别-人脸识别与疲劳检测 - python opencv

文章目录 0 前言1 课题背景2 Dlib人脸识别2.1 简介2.2 Dlib优点2.3 相关代码2.4 人脸数据库2.5 人脸录入加识别效果 3 疲劳检测算法3.1 眼睛检测算法3.3 点头检测算法 4 PyQt54.1 简介4.2相关界面代码 5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是…

5 步轻松上手,教你从 0 到 1 落地 Jmeter 接口自动化脚本!

Jmeter是进行接口测试的一款非常主流的工具&#xff0c;但绝大部分测试工程师&#xff0c;对于Jmeter接口测试脚本整理都是一知半解的。今天这篇文章&#xff0c;就以一个金融项目中接口为例&#xff0c;通过简单5步&#xff0c;教大家如何0代码编写Jmeter接口自动化脚本&#…

HBase入门:运行机制

文章目录 HBase 系统架构客户端ZooKeeper 服务器Master 主服务器Region 服务器 Region 服务器工作原理用户读写数据的过程缓存的刷新StoreFile合并 Store 的工作原理HLog 的工作原理 HBase 系统架构 HBase 的系统架构包括客户端、ZooKeeper 服务器、Master 主服务器、Region服…