美文网首页
framework 学习笔记19. 知识点1(framework

framework 学习笔记19. 知识点1(framework

作者: 加个标志位 | 来源:发表于2021-02-20 22:18 被阅读0次

Linux 系统中,创建线程函数为:pthread_create();在 Android 中,通过调用 pthread_create() 封装了一个为线程操作的 Thread类;在创建线程的时候,只需要继承于这个 Thread 类并实现虚函数 thread_loop()。下面就简单介绍一下这个 Thread 类:

1. 头文件中的定义

// frameworks/base/include/utils/threads.h
frameworks/base/include/utils/threads.h
class Thread : virtual public RefBase
{
public:
    // canCallJava 为 true
    Thread(bool canCallJava = true);
    virtual ~Thread();
    // 线程启动函数,调用的是threadLoop
    virtual status_t run(const char*name = 0, int32_t prority = PRIORITY_DEFAULT,
                size_t stack = 0);
    // 申请退出这个线程
    virtual void requestExit();
    virtual status_t readyToRun();
    // 调用requestExit()等待直到这个线程退出
        status_t requestExitAndWait();
    // 等待直到线程退出,如果没有启动立即返回
        status_t join();
protected:
    // 如果调用了 requestExit() 返回true
    bool exitPending() const;
private:
    // 实际的线程函数,继承类必须实现该方法:threadLoop()
    // 返回 true 时会一直调用,返回 false 的时会退出该线程;
    virtual bool threadLoop() = 0;
    // 禁止赋值
    Thread& operator = (const Thread&);
    // 被 run() 函数调用,实际调用threadLoop();
    static int _threadLoop(void* user);
    const bool mCanCallJava;
        thread_id_t mThread;    // thread_id_t 是 void*类型
    mutable Mutex mLock;
        Condition mThreadExitedCondition;
        status_t mStatus;
    // 注意:操作这两个变量的地方都需要上锁
    volatile bool mExitPending;
    volatile bool mRunning;
        sp<Thread> mHoldSelf;
};

2. Thread 类的构造函数

Thread::Thread(bool canCallJava) 
        :   mCanCallJava(canCallJava),
            mThread(thread_id_t(-1)),
            mLock("Thrad::mLock"),
            mStatus(NO_ERROR),
            mExitPending(false), mRunnig(false)
{
}

3. run() 方法

status_t Thread::run(const char* name, int32_t priority, size_t stack)
{
    Mutex::Autolock _l(mLock);

    if (mRunning) {
        // thread already started
        return INVALID_OPERATION;
    }

    // reset status and exitPending to their default value, so we can
    // try again after an error happened (either below, or in readyToRun())
    mStatus = NO_ERROR;
    mExitPending = false;
    mThread = thread_id_t(-1);
    
    // hold a strong reference on ourself 
    mHoldSelf = this;  // 保存当前对象的引用

    mRunning = true;

    bool res;
   // 如果 mCanCallJava为真,则调用createThreadEtc函数,线程函数是_threadLoop(Thread.cpp中定义的一个函数)。
    if (mCanCallJava) {  // 这里初始化的时候为 true; 见 3.1
        res = createThreadEtc(_threadLoop,
                this, name, priority, stack, &mThread);
    } else {    // 见 3.2
        res = androidCreateRawThreadEtc(_threadLoop,
                this, name, priority, stack, &mThread);
    }
    
    if (res == false) {
        mStatus = UNKNOWN_ERROR;   // something happened!
        mRunning = false;
        mThread = thread_id_t(-1);
        mHoldSelf.clear();  // "this" may have gone away after this.

        return UNKNOWN_ERROR;
    }
    
    // Do not refer to mStatus here: The thread is already running (may, in fact
    // already have exited with a valid mStatus result). The NO_ERROR indication
    // here merely indicates successfully starting the thread and does not
    // imply successful termination/execution.
    return NO_ERROR;

    // Exiting scope of mLock is a memory barrier and allows new thread to run
}

3.1 createThreadEtc() 方法:这里 mCanCallJava 为 true 时,调用的方法;其实最终调用的方法都是同一个线程创建函数,只不过传入参数的回调函数不一样,之后会有分析:

//(1)创建线程:Create thread with lots of parameters
inline bool createThreadEtc(thread_func_t entryFunction,
                            void *userData,
                            const char* threadName = "android:unnamed_thread",
                            int32_t threadPriority = PRIORITY_DEFAULT,
                            size_t threadStackSize = 0,
                            thread_id_t *threadId = 0)
{
    return androidCreateThreadEtc(entryFunction, userData, threadName,
        threadPriority, threadStackSize, threadId) ? true : false;
}


//(2)调用的函数:
static android_create_thread_fn gCreateThreadFn = androidCreateRawThreadEtc;  // 函数指针;
// 线程创建函数:gCreateThreadFn是函数指针,初始化时和 mCanCallJava 为 false 时使用的是同一个
int androidCreateThreadEtc(android_thread_func_t entryFunction,
                            void *userData,
                            const char* threadName,
                            int32_t threadPriority,
                            size_t threadStackSize,
                            android_thread_id_t *threadId)
{
    return gCreateThreadFn(entryFunction, userData, threadName,
        threadPriority, threadStackSize, threadId);
}

3.2 androidCreateRawThreadEtc() 方法:

// 
int androidCreateRawThreadEtc(android_thread_func_t entryFunction,
                               void *userData,
                               const char* threadName __android_unused,
                               int32_t threadPriority,
                               size_t threadStackSize,
                               android_thread_id_t *threadId)
{
    pthread_attr_t attr; 
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

#ifdef HAVE_ANDROID_OS  /* valgrind is rejecting RT-priority create reqs */
    if (threadPriority != PRIORITY_DEFAULT || threadName != NULL) {
        // Now that the pthread_t has a method to find the associated
        // android_thread_id_t (pid) from pthread_t, it would be possible to avoid
        // this trampoline in some cases as the parent could set the properties
        // for the child.  However, there would be a race condition because the
        // child becomes ready immediately, and it doesn't work for the name.
        // prctl(PR_SET_NAME) only works for self; prctl(PR_SET_THREAD_NAME) was
        // proposed but not yet accepted.
        thread_data_t* t = new thread_data_t;
        t->priority = threadPriority;
        t->threadName = threadName ? strdup(threadName) : NULL;
        t->entryFunction = entryFunction;
        t->userData = userData;
        entryFunction = (android_thread_func_t)&thread_data_t::trampoline;
        userData = t;            
    }
#endif

    if (threadStackSize) {
        pthread_attr_setstacksize(&attr, threadStackSize);
    }
    
    errno = 0;
    pthread_t thread; 
    // 从这里可以看出线程的创建最终还是通过 pthread_create() 封装而成的;
    int result = pthread_create(&thread, &attr,
                    (android_pthread_entry)entryFunction, userData);
    pthread_attr_destroy(&attr);
    if (result != 0) {
        ALOGE("androidCreateRawThreadEtc failed (entry=%p, res=%d, errno=%d)\n"
             "(android threadPriority=%d)",
            entryFunction, result, errno, threadPriority);
        return 0;
    }

    // Note that *threadID is directly available to the parent only, as it is
    // assigned after the child starts.  Use memory barrier / lock if the child
    // or other threads also need access.
    if (threadId != NULL) {
        *threadId = (android_thread_id_t)thread; // XXX: this is not portable
    }
    return 1;
}
/**
简单介绍 pthread_create() :pthread_create 是(Unix、Linux、Mac OS X)等操作系统的创建线程的函
数。它的功能是创建线程(实际上就是确定调用该线程函数的入口点),在线程创建以后,就开始运行相关的线程函数。

pthread_create的返回值表示成功,返回0;表示出错,返回表示-1。

参数说明:int pthread_create (pthread_t * tid, const pthread_attr_t * attr, void * (*start_rtn)(void*), void *arg);
各个参数说明:
第一个参数为指向线程标识符的指针。
第二个参数用来设置线程属性。
第三个参数是线程运行函数的起始地址(也就是传入的entryFunction)。
最后一个参数是运行函数的参数。
**/

上述中当 mCanCallJava 为 true 时最终调用的是 gCreateThreadFn这个函数,gCreateThreadFn是个全局的函数指针(static android_create_thread_fn gCreateThreadFn = androidCreateRawThreadEtc),而这个与 mCanCallJava 为 false 时看上去是一模一样的,那么这两者是不是有所区别呢(答案是肯定有的,不然搞这么麻烦作甚)?

3.3 布尔变量 mCanCallJava 取值不同时的区别:
过程:
(1)mCanCallJava 为 false 时:直接调用的是 androidCreateRawThreadEtc() 这个方法;
(2)mCanCallJava 为 true 时:createThreadEtc() -> android_create_thread_fn () -> androidCreateRawThreadEtc();
区别:
在 3.1分析 mCanCallJava 为 true 的过程中其实就多执行了一步,即调用了 androidCreateThreadEtc() 方法,而在这个方法中也只是引入了 static android_create_thread_fn gCreateThreadFn = androidCreateRawThreadEtc 这个函数指针,并调用 gCreateThreadFn 方法创建线程;那么接下来就跟踪这个 gCreateThreadFn 变量的初始化就行了;

3.4 gCreateThreadFn() 的赋值:代码中有的地方是会修改这个函数指针的指向的,比如在 zygote 中创建线程,AndroidRuntime 调用 startReg() 的地方,就有修改这个函数指针,其代码如下所示(这里顺便简单介绍一下 zygote 进程的启动):

//(1)zygote 是由 init 进程通过解析 init.rc 文件而创建并启动的:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media
    onrestart restart netd


//(2)frameworks/base/cmds/app_process/app_main.cpp 中的 main() 方法:
int main(int argc, char* const argv[])
{
    // AppRuntime 继承 AndoirdRuntime
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    // 跳过第一个参数
    argc--;
    argv++;

    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;

    ++i;  // Skip unused "parent dir" argument.
    // 解析参数
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            niceName.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }

    //  省略部分代码 ...
    //设置进程名
    if (!niceName.isEmpty()) {
        runtime.setArgv0(niceName.string());
        set_process_name(niceName.string());
    }
    // 如果 zygote ,AndroidRuntime 执行 com.android.internal.os.ZygoteInit 
    if (zygote) {  // 根据上面解析的脚本参数,执行的是此分支;
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
        return 10;
    }
}

//(3)在 zygote 的启动过程中会调用到 AndroidRuntime的 start 方法:
void AndroidRuntime::start(const char* className, const Vector<String8>& options)
{
    // ... 
    // 创建一个虚拟机的实例
    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);

    // JNI 方法注册
    /*
     * Register android functions.
     */
    if (startReg(env) < 0) {  // ********* 此处为下面的关注点 *********
        ALOGE("Unable to register all android natives\n");
        return;
    }

    /*
     * We want to call main() with a String array with arguments in it.
     * At present we have two arguments, the class name and an option string.
     * Create an array to hold them.
     */
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;

    // strArray= new String[options.size() + 1];
    stringClass = env->FindClass("java/lang/String");
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    // strArray[0] = "com.android.internal.os.ZygoteInit"
    classNameStr = env->NewStringUTF(className);
    env->SetObjectArrayElement(strArray, 0, classNameStr);

    // strArray[1] = "start-system-server";
    // strArray[2] = "--abi-list=系统响应的cpu架构类型";
    for (size_t i = 0; i < options.size(); ++i) {
        jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
        env->SetObjectArrayElement(strArray, i + 1, optionsStr);
    }

    // slashClassName = "com/android/internal/os/ZygoteInit"
    char* slashClassName = toSlashClassName(className);
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        // 获取 ZygoteInit.java 的 main 方法
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
            // 执行 ZygoteInit.java 的 main 方法,从 Native 世界进入 Java 世界
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
        }
    }
    // ...
}

//(4)Java 代码是运行在 Java 虚拟机上的,而 Java 与 native 通信采用的是 JNI ,从这里就开始进入 Java 层的代码:
public static void main(String argv[]) {
    try {
        // 解析参数
        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]);
            }
        }
        // 省略部分代码...
        // 为 Zygote 注册 socket 用于通信
        registerZygoteSocket(socketName);
        // 预加载类和资源
        preload(); 
        // 启动 system_server
        if (startSystemServer) {
            startSystemServer(abiList, socketName);
        }
        // 进入循环模式,等待孵化进程
        runSelectLoop(abiList); 
        closeServerSocket();
    } catch (MethodAndArgsCaller caller) {
        caller.run();
    } catch (RuntimeException ex) {
        closeServerSocket();
        throw ex;
    }
}

private static void registerZygoteSocket(String socketName) {
    if (sServerSocket == null) {
        int fileDesc;
        final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
        try {
            String env = System.getenv(fullSocketName);
            fileDesc = Integer.parseInt(env);
        } catch (RuntimeException ex) {
            // 省略部分代码...
        }

        try {
            FileDescriptor fd = new FileDescriptor();
            // 设置文件描述符
            fd.setInt$(fileDesc);
            // 创建 Socket 的本地服务端
            sServerSocket = new LocalServerSocket(fd); 
        } catch (IOException ex) {
            // 省略部分代码...
        }
    }
}

static void preload() {
    // 预加载位于 /system/etc/preloaded-classes 文件中的类
    preloadClasses();

    // 预加载资源,包含 drawable 和 color 资源
    preloadResources();

    // 预加载 OpenGL
    preloadOpenGL();

    // 通过 System.loadLibrary() 方法,
    // 预加载 "android", "compiler_rt", "jnigraphics" 这3个共享库
    preloadSharedLibraries();

    // 预加载 文本连接符资源
    preloadTextResources();

    // 仅用于 zygote 进程,用于内存共享的进程
    WebViewFactory.prepareWebViewInZygote();
}

private static boolean startSystemServer(String abiList, String socketName) throws 
                  MethodAndArgsCaller, RuntimeException {

    // 省略部分代码...
    // 设置一些参数 
    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 {
        // 省略部分代码...
        // fork 创建 system_server 进程,后面会具体分析
        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 代表子进程,也就是 system_server 进程
    if (pid == 0) {
        // 执行初始化 system_server 进程
        handleSystemServerProcess(parsedArgs);
    }
    return true;
}

private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
    ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
    ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
    // sServerSocket 是 registerZygoteSocket 中创建的,即 zygote 进程。保存到 fds[0]
    fds.add(sServerSocket.getFileDescriptor());
    peers.add(null);

    while (true) {
        // 给 pollFds 设置参数,fds.size 是 1 ,也就是说 pollFds 里面只有 sServerSocket.getFileDescriptor() 
        StructPollfd[] pollFds = new StructPollfd[fds.size()];
        for (int i = 0; i < pollFds.length; ++i) {
            pollFds[i] = new StructPollfd();
            pollFds[i].fd = fds.get(i);
            pollFds[i].events = (short) POLLIN;
        }
        try {
            // 处理轮询状态,当 pollFds 有事件到来则往下执行,否则阻塞在这里
            Os.poll(pollFds, -1);
        } catch (ErrnoException ex) {
            // 省略部分代码...
        }
        
        for (int i = pollFds.length - 1; i >= 0; --i) {
            if (i == 0) {
                // 即fds[0],代表的是 sServerSocket,则意味着有客户端连接请求;
                // 则创建 ZygoteConnection 对象,并添加到 fds。
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                //添加到 fds.
                fds.add(newPeer.getFileDesciptor()); 
            } else {
                // i>0,则代表通过 socket 接收来自对端的数据,并执行相应操作
                boolean done = peers.get(i).runOnce();
                if (done) {
                    peers.remove(i);
                    // 处理完则从fds中移除该文件描述符
                    fds.remove(i); 
                }
            }
        }
    }
}

boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
    String args[];
    Arguments parsedArgs = null;
    FileDescriptor[] descriptors;

    try {
        // 读取 socket 客户端发送过来的参数列表
        args = readArgumentList();
        descriptors = mSocket.getAncillaryFileDescriptors();
    } catch (IOException ex) {
        // 省略部分代码...
        return true;
    }
    // 省略部分代码...

    try {
        // 将 binder 客户端传递过来的参数,解析成 Arguments 对象格式
        parsedArgs = new Arguments(args);
        // 省略部分代码...
        // fork 创建一个新的进程
        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
                parsedArgs.appDataDir);
    } catch (Exception e) {
        // 省略部分代码...
    }

    try {
        if (pid == 0) {
            // pid == 0 执行子进程的逻辑
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;
            // 进入子进程流程
            handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
            return true;
        } else {
            // pid>0 执行父进程的逻辑
            IoUtils.closeQuietly(childPipeFd);
            childPipeFd = null;
            return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
        }
    } finally {
        IoUtils.closeQuietly(childPipeFd);
        IoUtils.closeQuietly(serverPipeFd);
    }
}

在 startReg(env) 方法中:

//(1)AndroidRuntime.cpp 中 startReg():
/*
 * Register android native functions with the VM.
 */
/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
{
    /*
     * This hook causes all future threads created in this process to be
     * attached to the JavaVM.  (This needs to go away in favor of JNI
     * Attach calls.)
     */
    // 这里会修改函数指针为 javaCreateThreadEtc,不再是 mCanCallJava 为 false 时调用的 androidCreateRawThreadEtc
    androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);

    ALOGV("--- registering native functions ---\n");

    /*
     * Every "register" function calls one or more things that return
     * a local reference (e.g. FindClass).  Because we haven't really
     * started the VM yet, they're all getting stored in the base frame
     * and never released.  Use Push/Pop to manage the storage.
     */
    env->PushLocalFrame(200);

    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }
    env->PopLocalFrame(NULL);

    //createJavaThread("fubar", quickTest, (void*) "hello");

    return 0;
}


//(2)Threads.cpp 中 androidSetCreateThreadFunc():
void androidSetCreateThreadFunc(android_create_thread_fn func)
{
    gCreateThreadFn = func;  // 也就是说 gCreateThreadFn 为 javaCreateThreadEtc
}


//(3)AndroidRuntime.cpp 中 javaCreateThreadEtc():
/*static*/ int AndroidRuntime::javaCreateThreadEtc(
                                android_thread_func_t entryFunction,
                                void* userData,
                                const char* threadName,
                                int32_t threadPriority,
                                size_t threadStackSize,
                                android_thread_id_t* threadId)
{
    void** args = (void**) malloc(3 * sizeof(void*));   // javaThreadShell must free
    int result;

    if (!threadName)
        threadName = "unnamed thread";

    args[0] = (void*) entryFunction;
    args[1] = userData;
    args[2] = (void*) strdup(threadName);   // javaThreadShell must free
    // 最终调用的还是 androidCreateRawThreadEtc,但把线程函数(回调函数)换成了 javaThreadShell
    result = androidCreateRawThreadEtc(AndroidRuntime::javaThreadShell, args,
        threadName, threadPriority, threadStackSize, threadId);
    return result;
}


//(4)AndroidRuntime.cpp 中 javaThreadShell():
/*static*/ int AndroidRuntime::javaThreadShell(void* args) {
    void* start = ((void**)args)[0];
    void* userData = ((void **)args)[1];
    char* name = (char*) ((void **)args)[2];        // we own this storage
    free(args);
    JNIEnv* env;
    int result;

    /* hook us into the VM */
    //把这个线程 attach 到 JNI 环境中,调用了JavaVM* vm 的 vm->AttachCurrentThread()
    if (javaAttachThread(name, &env) != JNI_OK)
        return -1;

    /* start the thread running */ 
    result = (*(android_thread_func_t)start)(userData);

    /* unhook us */
    // 当在一个线程里面调用AttachCurrentThread后,如果不需要用的时候一定要DetachCurrentThread,否则线程无法正常退出。
    javaDetachThread();  // 从JNI环境中detach出来,调用了 vm->DetachCurrentThread()
    free(name);

    return result;  // 返回当前线程的JNIEnv,这样就可以调用 JNI 中的方法使用了
}
目的:
  • 在调用线程函数之前会 attach 到 JNI 环境中,这样,线程函数就可以使用JNI中的方法了。
  • 线程函数退出后,它会从 JNI 环境中 detach,释放资源。

4 _threadLoop() 与 threadLoop():

4.1 _threadLoop():前面的代码讲到了 Thread 中 mCanCallJava 取值到 zygote 启动时创建线程时通过修改函数指针 gCreateThreadFn,从而绑定到 JNI 环境中;现在回到之前的代码,跟踪一下传入创建线程时的回调函数 _threadLoop() ;

  // 之前的代码:
  // 从上面 3.3、 3.4 中可知,当 mCanCallJava 为 true 时,可以通过重新给 gCreateThreadFn 赋值,
  // 从而执行不同的线程回调函数;
  if(mCanCallJava) {  
       res = createThreadEtc(_threadLoop, this, name, priority,
                                   stack,&mThread);
    } else{
       res = androidCreateRawThreadEtc(_threadLoop, this, name, priority,
                                   stack,&mThread);
    }
int Thread::_threadLoop(void* user)
{
    Thread* const self = static_cast<Thread*>(user);  // self代表继承Thread类的对象

    sp<Thread> strong(self->mHoldSelf);
    wp<Thread> weak(strong);
    self->mHoldSelf.clear();

#ifdef HAVE_ANDROID_OS
    // this is very useful for debugging with gdb
    self->mTid = gettid();
#endif

    bool first = true;

    do {  // 这段代码运行在一个do-while循环中。 即使我们的threadLoop()返回了,线程也不一定会退出
        bool result;
        if (first) {  // 只执行一次
            first = false;
            self->mStatus = self->readyToRun();  // 第一次进来调用 readyToRun(),检查是否准备完成
            result = (self->mStatus == NO_ERROR);

            if (result && !self->exitPending()) { 
                result = self->threadLoop();  // 调用派生类的threadLoop
            }
        } else {
            result = self->threadLoop();  // 如果不是第一次执行此循环
        }

        // 建立 mLock 的作用域
        {
    //线程退出的条件:
    //(1)result 为 false。如果子类在 threadLoop 中返回 false,线程就可以退出,这种属于主动退出的情况;
    //(2)mExitPending为true,这个变量可由Thread类的requestExit函数设置,这属于被动退出,因为由外界强制设置了退出条件。
        Mutex::Autolock _l(self->mLock);
        if (result == false || self->mExitPending) {
            self->mExitPending = true;
            self->mRunning = false;
            // clear thread ID so that requestExitAndWait() does not exit if
            // called by a new thread using the same thread ID as this one.
            self->mThread = thread_id_t(-1);
            // note that interested observers blocked in requestExitAndWait are
            // awoken by broadcast, but blocked on mLock until break exits scope
            self->mThreadExitedCondition.broadcast();
            break;
        }
        }
        
        // Release our strong reference, to let a chance to the thread
        // to die a peaceful death.
        strong.clear();
        // And immediately, re-acquire a strong reference for the next loop
        strong = weak.promote();
    } while(strong != 0);
    
    return 0;
}

4.2 threadLoop():
(1)run() -> _threadLoop() -> threadLoop():如果线程是第一次执行 _threadLoop()方法,会先行线程的readyToRun()方法,再执行threadLoop(),否则,直接执行threadLoop() ;
(2)threadLoop() 方法有返回值,如果 threadLoop() 返回 false 时,线程会做清理工作;然后退出 while 循环,结束执行;

相关文章

网友评论

      本文标题:framework 学习笔记19. 知识点1(framework

      本文链接:https://www.haomeiwen.com/subject/jqmbtltx.html