Android之Zygote(下)--- SystemServer详解

news2024/11/16 21:49:14

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进程的id
        if (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继承下来的socket
        closeServerSocket();
        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<ProcessState> 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是SS
            try { //找到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<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> 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<String> args) throws ZygoteStartFailedEx {
   openZygoteSocketIfNeeded();//打开和zygote通信的socket
    sZygoteWriter.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 为true
            RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
        } 
}

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

 

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

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

相关文章

ABAP学习笔记之——第十章:面向对象ALV

一、ALV ALV 是 ABAP List Viewer 的缩写&#xff0c;是实际业务中查询数据或修改数据时经常使用的程序。 1、ALV的主要功能排序功能 (Ascending/Descending); 过滤设置; 变更列宽; 变更布局; ABC 分析; 下载 Excel及 Word 文档的保存。 2、ALV的类型 Function ALV; …

java计算机毕业设计ssm校园疫情防控系统u3669(附源码、数据库)

java计算机毕业设计ssm校园疫情防控系统u3669&#xff08;附源码、数据库&#xff09; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff0…

Docker安装以及容器使用笔记

我们知道容器是一个打包了应用和相关依赖的盒子,那怎么去操控这个盒子呢? 这一篇我通过一个简单的aspnetcore程序来加深对盒子的理解,使用之前先 安装一下Docker的环境。 一:Docker的安装 官方下载地址:Install Docker Engine on CentOS | Docker Documentation ,跟着文…

深度学习——NiN网络模型(笔记)

网络中的网络&#xff08;NiN&#xff09; 1.全连接层的问题&#xff1a;参数多&#xff0c;容易过拟合。 ①卷积层需要的参数较少 ②卷积层后第一个全连接层参数对比 参数过多带来的问题&#xff1a;1.占内存 2.占用计算的带宽多3.容易过拟合 2.NiN为了解决全连接层参数过多的…

20221208英语学习

今日新词&#xff1a; fragment n.碎片&#xff0c;碎块&#xff0c;破片&#xff1b;片段 cynicism n.愤世嫉俗, 玩世不恭, (古希腊的)犬儒哲学, 冷言冷语, 犬儒学派 slight adj.少量的&#xff1b;轻微的&#xff1b;细小的&#xff1b;纤细的 willing adj.愿意, 乐意, 自…

虚拟存储器

虚拟存储器 文章目录虚拟存储器虚拟存储器概述常规存储器管理方式的特征局部性原理虚拟存储器的定义和特征请求分页存储管理方式请求分页中的硬件支持请求分页中的内存分配页面调入策略页面置换算法最佳(Optimal)置换算法先进先出(FIFO)页面置换算法最近最久未使用(LRU)置换算法…

深度学习下的脑机接口BCI究竟有多远?

BCI | ECoG | 脑机接口 LFP | CMRR | 生物计算 随着生命科学、医药研发、数据分析、数据挖掘、LFP、生物计算、靶点发现、基因测序等技术的快速发展&#xff0c;脑科学逐渐出现在人们的视野中&#xff0c;随之而来的脑机接口技术同时得到快速发展。 脑科学是人类社会面临的…

Word处理控件Aspose.Words功能演示:使用 Java 将 Word 文档转换为 HTML

为了将 Word 文档的内容嵌入到您的应用程序中&#xff0c;您可能需要执行转换。在这种情况下&#xff0c;最广泛选择的转换是 Word 到HTML或 Word 到图像。&#xff0c;Aspose API支持流行文件格式处理&#xff0c;并允许将各类文档导出或转换为固定布局文件格式和最常用的图像…

Ubuntu20.04安装各种库----简洁版

目录Eigen3SophusPangolinCeresg2o建议先装anaconda再装ros, python,opencv啥该有的都有了下面仅仅安装ros没有的库Eigen3 作用:线性代数开源库, 提供了有关线性代数、矩阵和矢量运算、数值分析及相关的算法安裝方法: sudo apt-get install libeigen3-dev使用時注意添加頭文件…

性能测试:数据库性能问题实战分析

接口压测分析 现在我们来压测一个获取用户信息接口&#xff0c;这个接口会涉及到数据库的数据查询。我们的项目是部署正在应用服务器上面的&#xff0c;因此我们需要同时监控应用服务器和数据库服务器。 那么下面我们来看一下tomcat的这台服务器&#xff0c;cpu的使用率并不高&…

linux系统怎么安装宝塔面板

linux系统怎么安装宝塔面板 怎么安装宝塔面板&#xff1f;这个其实很简单接下来跟着我操作&#xff1a;以linux centos7.6 举例 Centos安装脚本&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh i…

JavaScript -- 10. 一文了解DOM对象及常用方法

文章目录1. DOM介绍1.1 什么是DOM1.2 概念1.3 关系1.4 HelloWorld1.5 document对象2. DOM节点2.1 元素节点2.1.1 获取已有的元素节点2.1.1 document.getElementById()2.1.2 document.getElementsByClassName()2.1.3 document.getElementsByTagName()2.1.4 document.getElements…

设计模式之简单工厂模式

simple factory design pattern 简单工厂模式的概念、简单工厂模式的结构、简单工厂模式优缺点、简单工厂模式的使用场景、简单工厂模式的实现示例 注&#xff1a;简单工厂模式没有被收录在 GoF 的二十三种设计模式中。 1、简单工厂的概念 简单工厂模式&#xff0c;与其说是设…

32位PCI转CPCI转接板

功能型号 32位PCI转CPCI转接板&#xff0c;调试卡 支持PICMG 2.0 D3.0规范&#xff1b; 支持33MHz速率&#xff1b; 支持32bit总线&#xff1b; 功能描述 1、沉金工艺&#xff0c;接触更好&#xff1b; 2、四层板设计&#xff0c;抗干扰更好&#xff1b; 3、信号线等长处理&…

【论文精读9】MVSNet系列论文详解-AA-RMVSNet

AA-RMVSNet&#xff0c;论文名为&#xff1a;AA-RMVSNet: Adaptive Aggregation Recurrent Multi-view Stereo Network&#xff0c;CVPR2021&#xff08;CCF A&#xff09; 本文是MVSNet系列的第9篇&#xff0c;建议看过【论文精读1】MVSNet系列论文详解-MVSNet之后再看便于理解…

【Java 快速复习】 Java 内存模型 并发问题本质

【Java 快速复习】 Java 内存模型 & 并发问题本质 在 Java 领域&#xff0c;我们经常会说两个名词大家要有所区分&#xff1a; JVM 内存模型&#xff1a;这个所说的是 JVM 内存的划分规则&#xff0c;如 堆、栈、元空间等Java 内存模型&#xff1a;这个所说的是线程和主内…

【计算机网络】应用层

应用层的许多协议都是基于客户服务器方式。 客户和服务器指通信中所涉及的两个应用进程。客户服务器方式描述的是进程之间服务和被服务的关系。客户是服务请求方&#xff0c;服务器是服务提供方。 P2P模式&#xff1a;整个网络中的传输内容不再被保存在中心服务器中&#xff…

怎么裁剪视频?手把手教你裁剪

这两年&#xff0c;随着网课的不断发展&#xff0c;我们可以很轻松的就在网上找到各种课程视频。可是有时候&#xff0c;一些视频里面的重点内容往往只有那几分钟&#xff0c;当我们回顾的时候&#xff0c;需要不断跳转&#xff0c;这就显得有些麻烦。其实我们可以将重点内容裁…

【代码随想录】二刷-回溯算法

回溯算法 《代码随想录》 什么是回溯算法&#xff1f; 回溯算法也可以叫做回溯搜索法&#xff0c;它是一种搜索方式。回溯是递归的副产品&#xff0c;只要有递归就会有回溯。 回溯法的效率: 回溯法的本质是穷举&#xff0c;穷举所有可能&#xff0c;然后选出我们想要的答案。(n…

如何使用virtualenv实现python环境的隔离?

有关更多的Python 开发内容,可访问:《 Python Flask开发指南》​​​​​​​ virtualenv可以帮助我们来创建一个Python的虚拟环境,虚拟环境可以独立并隔离外部的python环境,方便我们对于不同项目使用不同的python依赖,已经依赖版本的不同而导致的错误。本篇文章主要来了解…