浅谈android系统java调用C++函数传参过程

来源:互联网 发布:ubuntu python 安装 编辑:程序博客网 时间:2024/05/13 23:49

读了《深入理解android》卷一,发现了一点小问题,层层查看源码查资料,浅谈下此文。



   //源码目录 frameworks/base/core/java/com/android/internal/os/ZygoteInit.java   /**     * Prepare the arguments and fork for the system server process.     */    private static boolean startSystemServer()            throws MethodAndArgsCaller, RuntimeException {        /* 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,3001,3002,3003,3006,3007",            "--capabilities=130104352,130104352",            "--runtime-init",            "--nice-name=system_server",            "com.android.server.SystemServer",        };        ZygoteConnection.Arguments parsedArgs = null;        int pid;        try {            parsedArgs = new ZygoteConnection.Arguments(args);            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);            /* Request to fork the system server process */            pid = Zygote.forkSystemServer(                    parsedArgs.uid, parsedArgs.gid,                    parsedArgs.gids,                    parsedArgs.debugFlags,                    null,                    parsedArgs.permittedCapabilities,                    parsedArgs.effectiveCapabilities);        } catch (IllegalArgumentException ex) {            throw new RuntimeException(ex);        }        /* For child process */        if (pid == 0) {            handleSystemServerProcess(parsedArgs);        }        return true;    }-------------------------------------------------------------------------------//源码目录 dalvik/vm/native/dalvik_system_Zygote.cpp/* native public static int forkSystemServer(int uid, int gid, *     int[] gids, int debugFlags, long permittedCapabilities, *     long effectiveCapabilities); */static void Dalvik_dalvik_system_Zygote_forkSystemServer(        const u4* args, JValue* pResult){    pid_t pid;    pid = forkAndSpecializeCommon(args, true);    /* The zygote process checks whether the child process has died or not. */    if (pid > 0) {        int status;        LOGI("System server process %d has been created", pid);        gDvm.systemServerPid = pid;        /* There is a slight window that the system server process has crashed         * but it went unnoticed because we haven't published its pid yet. So         * we recheck here just to make sure that all is well.         */        if (waitpid(pid, &status, WNOHANG) == pid) {            LOGE("System server process %d has died. Restarting Zygote!", pid);            kill(getpid(), SIGKILL);        }    }    RETURN_INT(pid);}//源码目录 dalvik/vm/native/dalvik_system_Zygote.cpp/* * Utility routine to fork zygote and specialize the child process. */static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer){    pid_t pid;    uid_t uid = (uid_t) args[0];    gid_t gid = (gid_t) args[1];    ArrayObject* gids = (ArrayObject *)args[2];    u4 debugFlags = args[3];    ArrayObject *rlimits = (ArrayObject *)args[4];    int64_t permittedCapabilities, effectiveCapabilities;    //被调用函数自行转换参数    if (isSystemServer) {        /*         * Don't use GET_ARG_LONG here for now.  gcc is generating code         * that uses register d8 as a temporary, and that's coming out         * scrambled in the child process.  b/3138621         */        //permittedCapabilities = GET_ARG_LONG(args, 5);        //effectiveCapabilities = GET_ARG_LONG(args, 7);        permittedCapabilities = args[5] | (int64_t) args[6] << 32;        effectiveCapabilities = args[7] | (int64_t) args[8] << 32;    } else {        permittedCapabilities = effectiveCapabilities = 0;    }    if (!gDvm.zygote) {        dvmThrowIllegalStateException(            "VM instance not started with -Xzygote");        return -1;    }    if (!dvmGcPreZygoteFork()) {        LOGE("pre-fork heap failed");        dvmAbort();    }    setSignalHandler();    dvmDumpLoaderStats("zygote");    pid = fork();    ...---------------------------------------------------------------------------------

  forksystemserver参数不一致了呀,发现没有?原因何在?

/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * This uses the FFI (Foreign Function Interface) library to abstract away * the system-dependent stuff.  The FFI code is slower than a custom * assembly version, but has the distinct advantage of having been * written already for several platforms. */#include "Dalvik.h"#include "ffi.h"/* * Convert a signature type character to an FFI type. */static ffi_type* getFfiType(char sigType){    switch (sigType) {    case 'V': return &ffi_type_void;    case 'Z': return &ffi_type_uint8;    case 'B': return &ffi_type_sint8;    case 'C': return &ffi_type_uint16;    case 'S': return &ffi_type_sint16;    case 'I': return &ffi_type_sint32;    case 'F': return &ffi_type_float;    case 'J': return &ffi_type_sint64;    case 'D': return &ffi_type_double;    case '[':    case 'L': return &ffi_type_pointer;    default:        LOGE("bad ffitype 0x%02x", sigType);        dvmAbort();        return NULL;    }}/* * Call "func" with the specified arguments. * * The second argument to JNI native functions is either the object (the * "this" pointer) or, for static functions, a pointer to the class object. * The Dalvik instructions will push "this" into argv[0], but it's up to * us to insert the class object. * * Because there is no such thing in as a null "this" pointer, we use * the non-NULL state of "clazz" to determine whether or not it's static. * * For maximum efficiency we should compute the CIF once and save it with * the method.  However, this requires storing the data with every native * method.  Since the goal is to have custom assembly versions of this * on the platforms where performance matters, I'm recomputing the CIF on * every call. */void dvmPlatformInvoke(void* pEnv, ClassObject* clazz, int argInfo, int argc,    const u4* argv, const char* shorty, void* func, JValue* pReturn){    const int kMaxArgs = argc+2;    /* +1 for env, maybe +1 for clazz*/    ffi_cif cif;    ffi_type* types[kMaxArgs];    void* values[kMaxArgs];    ffi_type* retType;    char sigByte;    int srcArg, dstArg;    types[0] = &ffi_type_pointer;    values[0] = &pEnv;    types[1] = &ffi_type_pointer;    if (clazz != NULL) {        values[1] = &clazz;        srcArg = 0;    } else {        values[1] = (void*) argv++;        srcArg = 1;    }    dstArg = 2;    /*     * Scan the types out of the short signature.  Use them to fill out the     * "types" array.  Store the start address of the argument in "values".     */    retType = getFfiType(*shorty);    while ((sigByte = *++shorty) != '\0') {        types[dstArg] = getFfiType(sigByte);        values[dstArg++] = (void*) argv++;        if (sigByte == 'D' || sigByte == 'J')            argv++;    }    /*     * Prep the CIF (Call InterFace object).     */    if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, dstArg, retType, types) != FFI_OK) {        LOGE("ffi_prep_cif failed");        dvmAbort();    }    ffi_call(&cif, FFI_FN(func), pReturn, values);}

在dalvik虚拟机执行native方法有两种,DalvikNativeFunc和DalvikBridgeFunc,头一种方法有虚拟机直接调用,用指针传递参数,很简洁,比如const u4*,需要时在被调用方法里自行转换参数,并不需要方法签名的帮助来转换参数,方法签名只用于标示重载函数,这些函数可以理解成虚拟机的一部分,设计时针对不同平台进行编码,会调用不同平台的系统函数。第二种jni调用了,从源码可知在调用时会加入env 和clazz参数 ,并根据方法签名转换参数。需要说明的是在jni调用方面 ffi方式一般用于未知平台。像arm和x86平台都用汇编实现了。












原创粉丝点击