Linux 系統(tǒng)中没隘,創(chuàng)建線(xiàn)程函數(shù)為:pthread_create();在 Android 中,通過(guò)調(diào)用 pthread_create() 封裝了一個(gè)為線(xiàn)程操作的 Thread類(lèi)熄云;在創(chuàng)建線(xiàn)程的時(shí)候膨更,只需要繼承于這個(gè) Thread 類(lèi)并實(shí)現(xiàn)虛函數(shù) thread_loop()妙真。下面就簡(jiǎn)單介紹一下這個(gè) Thread 類(lèi):
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();
// 線(xiàn)程啟動(dòng)函數(shù),調(diào)用的是threadLoop
virtual status_t run(const char*name = 0, int32_t prority = PRIORITY_DEFAULT,
size_t stack = 0);
// 申請(qǐng)退出這個(gè)線(xiàn)程
virtual void requestExit();
virtual status_t readyToRun();
// 調(diào)用requestExit()等待直到這個(gè)線(xiàn)程退出
status_t requestExitAndWait();
// 等待直到線(xiàn)程退出荚守,如果沒(méi)有啟動(dòng)立即返回
status_t join();
protected:
// 如果調(diào)用了 requestExit() 返回true
bool exitPending() const;
private:
// 實(shí)際的線(xiàn)程函數(shù)珍德,繼承類(lèi)必須實(shí)現(xiàn)該方法:threadLoop()
// 返回 true 時(shí)會(huì)一直調(diào)用,返回 false 的時(shí)會(huì)退出該線(xiàn)程矗漾;
virtual bool threadLoop() = 0;
// 禁止賦值
Thread& operator = (const Thread&);
// 被 run() 函數(shù)調(diào)用锈候,實(shí)際調(diào)用threadLoop();
static int _threadLoop(void* user);
const bool mCanCallJava;
thread_id_t mThread; // thread_id_t 是 void*類(lèi)型
mutable Mutex mLock;
Condition mThreadExitedCondition;
status_t mStatus;
// 注意:操作這兩個(gè)變量的地方都需要上鎖
volatile bool mExitPending;
volatile bool mRunning;
sp<Thread> mHoldSelf;
};
2. Thread 類(lèi)的構(gòu)造函數(shù)
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; // 保存當(dāng)前對(duì)象的引用
mRunning = true;
bool res;
// 如果 mCanCallJava為真敞贡,則調(diào)用createThreadEtc函數(shù)泵琳,線(xiàn)程函數(shù)是_threadLoop(Thread.cpp中定義的一個(gè)函數(shù))。
if (mCanCallJava) { // 這里初始化的時(shí)候?yàn)?true誊役; 見(jiàn) 3.1
res = createThreadEtc(_threadLoop,
this, name, priority, stack, &mThread);
} else { // 見(jiàn) 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 時(shí)获列,調(diào)用的方法;其實(shí)最終調(diào)用的方法都是同一個(gè)線(xiàn)程創(chuàng)建函數(shù)蛔垢,只不過(guò)傳入?yún)?shù)的回調(diào)函數(shù)不一樣击孩,之后會(huì)有分析:
//(1)創(chuàng)建線(xiàn)程: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)調(diào)用的函數(shù):
static android_create_thread_fn gCreateThreadFn = androidCreateRawThreadEtc; // 函數(shù)指針;
// 線(xiàn)程創(chuàng)建函數(shù):gCreateThreadFn是函數(shù)指針鹏漆,初始化時(shí)和 mCanCallJava 為 false 時(shí)使用的是同一個(gè)
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;
// 從這里可以看出線(xiàn)程的創(chuàng)建最終還是通過(guò) 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;
}
/**
簡(jiǎn)單介紹 pthread_create() :pthread_create 是(Unix、Linux艺玲、Mac OS X)等操作系統(tǒng)的創(chuàng)建線(xiàn)程的函
數(shù)括蝠。它的功能是創(chuàng)建線(xiàn)程(實(shí)際上就是確定調(diào)用該線(xiàn)程函數(shù)的入口點(diǎn)),在線(xiàn)程創(chuàng)建以后饭聚,就開(kāi)始運(yùn)行相關(guān)的線(xiàn)程函數(shù)又跛。
pthread_create的返回值表示成功,返回0若治;表示出錯(cuò)慨蓝,返回表示-1。
參數(shù)說(shuō)明:int pthread_create (pthread_t * tid, const pthread_attr_t * attr, void * (*start_rtn)(void*), void *arg);
各個(gè)參數(shù)說(shuō)明:
第一個(gè)參數(shù)為指向線(xiàn)程標(biāo)識(shí)符的指針端幼。
第二個(gè)參數(shù)用來(lái)設(shè)置線(xiàn)程屬性礼烈。
第三個(gè)參數(shù)是線(xiàn)程運(yùn)行函數(shù)的起始地址(也就是傳入的entryFunction)。
最后一個(gè)參數(shù)是運(yùn)行函數(shù)的參數(shù)婆跑。
**/
上述中當(dāng) mCanCallJava 為 true 時(shí)最終調(diào)用的是 gCreateThreadFn這個(gè)函數(shù)此熬,gCreateThreadFn是個(gè)全局的函數(shù)指針(static android_create_thread_fn gCreateThreadFn = androidCreateRawThreadEtc),而這個(gè)與 mCanCallJava 為 false 時(shí)看上去是一模一樣的,那么這兩者是不是有所區(qū)別呢(答案是肯定有的犀忱,不然搞這么麻煩作甚)募谎?
3.3 布爾變量 mCanCallJava 取值不同時(shí)的區(qū)別:
過(guò)程:
(1)mCanCallJava 為 false 時(shí):直接調(diào)用的是 androidCreateRawThreadEtc() 這個(gè)方法;
(2)mCanCallJava 為 true 時(shí):createThreadEtc() -> android_create_thread_fn () -> androidCreateRawThreadEtc()阴汇;
區(qū)別:
在 3.1分析 mCanCallJava 為 true 的過(guò)程中其實(shí)就多執(zhí)行了一步数冬,即調(diào)用了 androidCreateThreadEtc() 方法,而在這個(gè)方法中也只是引入了 static android_create_thread_fn gCreateThreadFn = androidCreateRawThreadEtc 這個(gè)函數(shù)指針搀庶,并調(diào)用 gCreateThreadFn 方法創(chuàng)建線(xiàn)程拐纱;那么接下來(lái)就跟蹤這個(gè) gCreateThreadFn 變量的初始化就行了;
3.4 gCreateThreadFn() 的賦值:代碼中有的地方是會(huì)修改這個(gè)函數(shù)指針的指向的哥倔,比如在 zygote 中創(chuàng)建線(xiàn)程秸架,AndroidRuntime 調(diào)用 startReg() 的地方,就有修改這個(gè)函數(shù)指針咆蒿,其代碼如下所示(這里順便簡(jiǎn)單介紹一下 zygote 進(jìn)程的啟動(dòng)):
//(1)zygote 是由 init 進(jìn)程通過(guò)解析 init.rc 文件而創(chuàng)建并啟動(dòng)的:
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));
// 跳過(guò)第一個(gè)參數(shù)
argc--;
argv++;
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName;
String8 className;
++i; // Skip unused "parent dir" argument.
// 解析參數(shù)
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;
}
}
// 省略部分代碼 ...
//設(shè)置進(jìn)程名
if (!niceName.isEmpty()) {
runtime.setArgv0(niceName.string());
set_process_name(niceName.string());
}
// 如果 zygote 东抹,AndroidRuntime 執(zhí)行 com.android.internal.os.ZygoteInit
if (zygote) { // 根據(jù)上面解析的腳本參數(shù),執(zhí)行的是此分支沃测;
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 的啟動(dòng)過(guò)程中會(huì)調(diào)用到 AndroidRuntime的 start 方法:
void AndroidRuntime::start(const char* className, const Vector<String8>& options)
{
// ...
// 創(chuàng)建一個(gè)虛擬機(jī)的實(shí)例
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
onVmCreated(env);
// JNI 方法注冊(cè)
/*
* Register android functions.
*/
if (startReg(env) < 0) { // ********* 此處為下面的關(guān)注點(diǎn) *********
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=系統(tǒng)響應(yīng)的cpu架構(gòu)類(lèi)型";
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 {
// 執(zhí)行 ZygoteInit.java 的 main 方法芽突,從 Native 世界進(jìn)入 Java 世界
env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
}
// ...
}
//(4)Java 代碼是運(yùn)行在 Java 虛擬機(jī)上的试浙,而 Java 與 native 通信采用的是 JNI ,從這里就開(kāi)始進(jìn)入 Java 層的代碼:
public static void main(String argv[]) {
try {
// 解析參數(shù)
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 注冊(cè) socket 用于通信
registerZygoteSocket(socketName);
// 預(yù)加載類(lèi)和資源
preload();
// 啟動(dòng) system_server
if (startSystemServer) {
startSystemServer(abiList, socketName);
}
// 進(jìn)入循環(huán)模式寞蚌,等待孵化進(jìn)程
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();
// 設(shè)置文件描述符
fd.setInt$(fileDesc);
// 創(chuàng)建 Socket 的本地服務(wù)端
sServerSocket = new LocalServerSocket(fd);
} catch (IOException ex) {
// 省略部分代碼...
}
}
}
static void preload() {
// 預(yù)加載位于 /system/etc/preloaded-classes 文件中的類(lèi)
preloadClasses();
// 預(yù)加載資源田巴,包含 drawable 和 color 資源
preloadResources();
// 預(yù)加載 OpenGL
preloadOpenGL();
// 通過(guò) System.loadLibrary() 方法,
// 預(yù)加載 "android", "compiler_rt", "jnigraphics" 這3個(gè)共享庫(kù)
preloadSharedLibraries();
// 預(yù)加載 文本連接符資源
preloadTextResources();
// 僅用于 zygote 進(jìn)程挟秤,用于內(nèi)存共享的進(jìn)程
WebViewFactory.prepareWebViewInZygote();
}
private static boolean startSystemServer(String abiList, String socketName) throws
MethodAndArgsCaller, RuntimeException {
// 省略部分代碼...
// 設(shè)置一些參數(shù)
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 創(chuàng)建 system_server 進(jìn)程壹哺,后面會(huì)具體分析
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 代表子進(jìn)程,也就是 system_server 進(jìn)程
if (pid == 0) {
// 執(zhí)行初始化 system_server 進(jìn)程
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 中創(chuàng)建的艘刚,即 zygote 進(jìn)程管宵。保存到 fds[0]
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
while (true) {
// 給 pollFds 設(shè)置參數(shù),fds.size 是 1 攀甚,也就是說(shuō) 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 {
// 處理輪詢(xún)狀態(tài)箩朴,當(dāng) pollFds 有事件到來(lái)則往下執(zhí)行,否則阻塞在這里
Os.poll(pollFds, -1);
} catch (ErrnoException ex) {
// 省略部分代碼...
}
for (int i = pollFds.length - 1; i >= 0; --i) {
if (i == 0) {
// 即fds[0]秋度,代表的是 sServerSocket炸庞,則意味著有客戶(hù)端連接請(qǐng)求;
// 則創(chuàng)建 ZygoteConnection 對(duì)象,并添加到 fds荚斯。
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
//添加到 fds.
fds.add(newPeer.getFileDesciptor());
} else {
// i>0埠居,則代表通過(guò) socket 接收來(lái)自對(duì)端的數(shù)據(jù)查牌,并執(zhí)行相應(yīng)操作
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 客戶(hù)端發(fā)送過(guò)來(lái)的參數(shù)列表
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
} catch (IOException ex) {
// 省略部分代碼...
return true;
}
// 省略部分代碼...
try {
// 將 binder 客戶(hù)端傳遞過(guò)來(lái)的參數(shù),解析成 Arguments 對(duì)象格式
parsedArgs = new Arguments(args);
// 省略部分代碼...
// fork 創(chuàng)建一個(gè)新的進(jìn)程
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 執(zhí)行子進(jìn)程的邏輯
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
// 進(jìn)入子進(jìn)程流程
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
return true;
} else {
// pid>0 執(zhí)行父進(jìn)程的邏輯
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.)
*/
// 這里會(huì)修改函數(shù)指針為 javaCreateThreadEtc滥壕,不再是 mCanCallJava 為 false 時(shí)調(diào)用的 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; // 也就是說(shuō) 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
// 最終調(diào)用的還是 androidCreateRawThreadEtc纸颜,但把線(xiàn)程函數(shù)(回調(diào)函數(shù))換成了 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 */
//把這個(gè)線(xiàn)程 attach 到 JNI 環(huán)境中,調(diào)用了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 */
// 當(dāng)在一個(gè)線(xiàn)程里面調(diào)用AttachCurrentThread后绎橘,如果不需要用的時(shí)候一定要DetachCurrentThread胁孙,否則線(xiàn)程無(wú)法正常退出。
javaDetachThread(); // 從JNI環(huán)境中detach出來(lái)金踪,調(diào)用了 vm->DetachCurrentThread()
free(name);
return result; // 返回當(dāng)前線(xiàn)程的JNIEnv浊洞,這樣就可以調(diào)用 JNI 中的方法使用了
}
目的:
- 在調(diào)用線(xiàn)程函數(shù)之前會(huì) attach 到 JNI 環(huán)境中牵敷,這樣胡岔,線(xiàn)程函數(shù)就可以使用JNI中的方法了。
- 線(xiàn)程函數(shù)退出后枷餐,它會(huì)從 JNI 環(huán)境中 detach靶瘸,釋放資源。
4 _threadLoop() 與 threadLoop():
4.1 _threadLoop():前面的代碼講到了 Thread 中 mCanCallJava 取值到 zygote 啟動(dòng)時(shí)創(chuàng)建線(xiàn)程時(shí)通過(guò)修改函數(shù)指針 gCreateThreadFn毛肋,從而綁定到 JNI 環(huán)境中怨咪;現(xiàn)在回到之前的代碼,跟蹤一下傳入創(chuàng)建線(xiàn)程時(shí)的回調(diào)函數(shù) _threadLoop() 润匙;
// 之前的代碼:
// 從上面 3.3诗眨、 3.4 中可知,當(dāng) mCanCallJava 為 true 時(shí)孕讳,可以通過(guò)重新給 gCreateThreadFn 賦值匠楚,
// 從而執(zhí)行不同的線(xiàn)程回調(diào)函數(shù);
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類(lèi)的對(duì)象
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 { // 這段代碼運(yùn)行在一個(gè)do-while循環(huán)中厂财。 即使我們的threadLoop()返回了芋簿,線(xiàn)程也不一定會(huì)退出
bool result;
if (first) { // 只執(zhí)行一次
first = false;
self->mStatus = self->readyToRun(); // 第一次進(jìn)來(lái)調(diào)用 readyToRun(),檢查是否準(zhǔn)備完成
result = (self->mStatus == NO_ERROR);
if (result && !self->exitPending()) {
result = self->threadLoop(); // 調(diào)用派生類(lèi)的threadLoop
}
} else {
result = self->threadLoop(); // 如果不是第一次執(zhí)行此循環(huán)
}
// 建立 mLock 的作用域
{
//線(xiàn)程退出的條件:
//(1)result 為 false璃饱。如果子類(lèi)在 threadLoop 中返回 false与斤,線(xiàn)程就可以退出,這種屬于主動(dòng)退出的情況荚恶;
//(2)mExitPending為true撩穿,這個(gè)變量可由Thread類(lèi)的requestExit函數(shù)設(shè)置,這屬于被動(dòng)退出谒撼,因?yàn)橛赏饨鐝?qiáng)制設(shè)置了退出條件食寡。
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():如果線(xiàn)程是第一次執(zhí)行 _threadLoop()方法,會(huì)先行線(xiàn)程的readyToRun()方法嗤栓,再執(zhí)行threadLoop()冻河,否則箍邮,直接執(zhí)行threadLoop() ;
(2)threadLoop() 方法有返回值叨叙,如果 threadLoop() 返回 false 時(shí)锭弊,線(xiàn)程會(huì)做清理工作;然后退出 while 循環(huán)擂错,結(jié)束執(zhí)行味滞;