Framework基础:应用与Zygote的一次亲密接触

西雅图.png

Zgyote是Android中的第一个art虚拟机,他通过socket的方式与其他进程进行通信。这里的“其他进程”其实主要是系统进程——SystemServer。我们试一下让应用直接与Zgyote进行通信,亲密接触下。

一.首先看一下SystemServer是如何跟Zgyote通信的

(1)Zgyote的socket是如何建立的?

在Zygote的main函数进行了Socket的注册,并且开启了监听。
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

    public static void main(String argv[]) {
            ...........
            registerZygoteSocket(socketName);
            ................
    }

执行adb shell netstat,可以看到socket的情况。

Paste_Image.png
(2)SystemServer如何跟Zgyote通信呢?

在AMS启动一个新应用的时候,会告诉Zgyote:Zgyote老兄,帮我搞起一个应用。
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {

            Process.ProcessStartResult startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                    app.info.dataDir, entryPointArgs);

}

所以他是会调用Process的start方法来启动新应用。
/frameworks/base/core/java/android/os/Process.java
依次经过几个方法后,最终到达zygoteSendArgsAndGetResult方法执行。zygoteSendArgsAndGetResult会把启动应用的参数告诉Zygote。Zygote干完事就把结果告诉SystemServer。

Paste_Image.png

    private static ProcessStartResult zygoteSendArgsAndGetResult(
            ZygoteState zygoteState, ArrayList<String> args)
            throws ZygoteStartFailedEx {
            final BufferedWriter writer = zygoteState.writer;  //写参数给Zygote
            final DataInputStream inputStream = zygoteState.inputStream;  //用来读Zygote的回应

            writer.write(Integer.toString(args.size()));
            writer.newLine();

            int sz = args.size();
            for (int i = 0; i < sz; i++) {
                String arg = args.get(i);
                if (arg.indexOf('\n') >= 0) {
                    throw new ZygoteStartFailedEx(
                            "embedded newlines not allowed");
                }
                writer.write(arg);   //把参数一行行写出去
                writer.newLine();
            }

            writer.flush();   //把启动参数告诉Zygote

            // Should there be a timeout on this?
            ProcessStartResult result = new ProcessStartResult();
            result.pid = inputStream.readInt();            //读取Zygote的反应
            if (result.pid < 0) {
                throw new ZygoteStartFailedEx("fork() failed");
            }
            result.usingWrapper = inputStream.readBoolean();
            return result;
        } catch (IOException ex) {
            zygoteState.close();
            throw new ZygoteStartFailedEx(ex);
        }
    }

启动参数大概有下面几个,主要是入口类ActivityThread,这个类老厉害了,是所有应用的入口类。另外还有uid,gid,应用数据目录等等参数。

Paste_Image.png

然后数据传出去了,就会在Zygote收到,在runSelectLoop收到一个远方的连接。
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

    private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
                   ..................
                    boolean done = peers.get(i).runOnce();
                   .....................
    }

进而进入runOnce方法,调用forkAndSpecialize完成进程的fork操作,哈哈。
/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

    boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {

            pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                    parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                    parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
                    parsedArgs.appDataDir);

    }

一.应用是如何跟Zgyote通信的

上面是系统进程与Zygote进行socket通信,应用要怎么跟Zygote通信呢?我用了反射调用Process类的openZygoteSocketIfNeeded 方法,简单通信了一番。下面是简单例子来获取cpu的架构。

package com.wenfeng.zygotesocketdemo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    public  static final String TAG = "zygotesocketdemotag";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        try {
            String abi = "arm64-v8a";
            //process        反射调用android.os.Process类,获取openZygoteSocketIfNeeded方法
            Class<?> ProcessClazz = Class.forName("android.os.Process");
            Method method = ProcessClazz.getDeclaredMethod("openZygoteSocketIfNeeded", String.class);
            method.setAccessible(true);

            //ZygoteState
            Class<?> ZygoteStateClazz = Class.forName("android.os.Process$ZygoteState");
            Field abilistfeild=ZygoteStateClazz.getDeclaredField("abiList");
            abilistfeild.setAccessible(true);

            //连接zygote,返回一个ZygoteState的对象
            Object ZygoteStateobj=method.invoke(null,abi);

            //获取ZygoteState的abiList值,他的值就是cpu的架构
            List<String> abilist= (List<String>) abilistfeild.get(ZygoteStateobj);
            for(int i = 0 ;i < abilist.size();i++){
                Log.i(TAG,"hehe "+ " "+ abilist.get(i));
            }
        }catch (Exception e){
            e.printStackTrace();
            Log.i(TAG,"error="+e.toString());
        }
    }
}

结果.png

出现上面的结果我们必须要配好selinux权限和应用必须是系统应用。
因为这个socket的权限是root:system 660,这个只有root或者system才能访问到。


Paste_Image.png

另外selinux也要配置好,为了临时看效果,我们可以先临时把selinux关掉,执行下面一句就可以了。
setenforce 0

例子传送门:
https://github.com/wenfengtou/ZygoteSocketDemo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容