做寫(xiě)字樓的網(wǎng)站有哪些河南seo網(wǎng)站多少錢(qián)
文章目錄
- Android native層的線(xiàn)程分析(C++),多線(xiàn)程實(shí)現(xiàn)
- 1.native線(xiàn)程的創(chuàng)建
- 第一部分:android_thread模塊
- 第二部分:linux_thread模塊
- 2.測(cè)試linux_thread模塊
- 3.Android native的Thread類(lèi)
- 3.1源碼分析
- 4.native層堆棧調(diào)試方法
Android native層的線(xiàn)程分析(C++),多線(xiàn)程實(shí)現(xiàn)
1.native線(xiàn)程的創(chuàng)建
pthread_t //表示線(xiàn)程ID
pthread_equal (pthread_t __thread1, pthread_t __thread2);//比較線(xiàn)程ID
pthread_t pthread_self (void);//用戶(hù)返回線(xiàn)程ID
pthread_create()//線(xiàn)程創(chuàng)建
編寫(xiě)Android.mk文件,
這個(gè)MK文件是一個(gè)Android.mk構(gòu)建腳本,用于指導(dǎo)Android Native Development Kit (NDK)如何編譯和鏈接兩個(gè)可執(zhí)行模塊:android_thread
和 linux_thread
。下面是該腳本的詳細(xì)解析:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)LOCAL_SRC_FILES := MyThread.cpp \Main.cpp \LOCAL_SHARED_LIBRARIES :=libandroid_runtime \libcutils \libutils \liblog LOCAL_MODULE := android_threadLOCAL_PRELINK_MODULE := falseinclude $(BUILD_EXECUTABLE)include $(CLEAR_VARS)LOCAL_SRC_FILES := thread_posix.c LOCAL_MODULE := linux_thread
LOCAL_SHARED_LIBRARIES :=liblog LOCAL_PRELINK_MODULE := falseinclude $(BUILD_EXECUTABLE)//把thread_posix.c 文件編譯(BUILD_EXECUTABLE)成為一個(gè)二進(jìn)制的可執(zhí)行文件,這個(gè)二進(jìn)制可執(zhí)行文件的名字是linux_thread。
第一部分:android_thread模塊
- LOCAL_PATH: 這一行定義了當(dāng)前目錄的路徑,通過(guò)
my-dir
函數(shù)自動(dòng)獲取,作為查找其他文件(如源代碼文件)的相對(duì)路徑基礎(chǔ)。 - include $(CLEAR_VARS): 這行代碼包含了清除所有之前定義的LOCAL變量的腳本,確保為新模塊提供一個(gè)干凈的構(gòu)建環(huán)境。
- LOCAL_SRC_FILES: 指定了要編譯的源文件列表。在這個(gè)例子中,包括
MyThread.cpp
和Main.cpp
。 - LOCAL_SHARED_LIBRARIES: 列出了該模塊需要鏈接的共享庫(kù),包括
libandroid_runtime
,libcutils
,libutils
, 和liblog
。這些都是Android系統(tǒng)提供的庫(kù),用于支持Android運(yùn)行時(shí)功能、實(shí)用工具函數(shù)、日志輸出等功能。 - LOCAL_MODULE: 定義了模塊的名稱(chēng),這里是
android_thread
。 - LOCAL_PRELINK_MODULE: 設(shè)定為
false
,表示該模塊在預(yù)鏈接階段不會(huì)被處理。預(yù)鏈接是一個(gè)可選步驟,通常用于減少應(yīng)用啟動(dòng)時(shí)間,但在這里不適用。 - include $(BUILD_EXECUTABLE): 告訴NDK構(gòu)建系統(tǒng),根據(jù)前面定義的規(guī)則,將這些源文件編譯成一個(gè)可執(zhí)行文件。
第二部分:linux_thread模塊
這部分結(jié)構(gòu)與第一部分相似,但是針對(duì)另一個(gè)模塊linux_thread
:
- LOCAL_SRC_FILES 只包含一個(gè)源文件:
thread_posix.c
,意味著這是一個(gè)基于POSIX線(xiàn)程標(biāo)準(zhǔn)實(shí)現(xiàn)的模塊。 - LOCAL_SHARED_LIBRARIES 只列出了
liblog
,說(shuō)明這個(gè)模塊依賴(lài)于日志庫(kù)來(lái)記錄日志信息。 - 其他如
LOCAL_MODULE
、LOCAL_PRELINK_MODULE
以及最后的include $(BUILD_EXECUTABLE)
指令用法與android_thread
模塊相同,用于構(gòu)建名為linux_thread
的獨(dú)立可執(zhí)行模塊。
綜上所述,這個(gè)MK文件配置了兩個(gè)C++/C語(yǔ)言編寫(xiě)的可執(zhí)行模塊的構(gòu)建過(guò)程,一個(gè)是與Android系統(tǒng)緊密結(jié)合的android_thread
,另一個(gè)是使用POSIX線(xiàn)程API的linux_thread
,兩者都將作為獨(dú)立的可執(zhí)行文件生成。
thread_posix.c
這段代碼是一個(gè)簡(jiǎn)單的C語(yǔ)言程序,演示了如何在Linux或類(lèi)Unix系統(tǒng)中使用POSIX線(xiàn)程庫(kù)(pthread.h
)創(chuàng)建并管理一個(gè)線(xiàn)程。同時(shí),它也使用了Android的日志系統(tǒng)(通過(guò)utils/Log.h
頭文件)來(lái)記錄日志信息。以下是代碼的詳細(xì)解釋:
#include <pthread.h> // 包含POSIX線(xiàn)程庫(kù)頭文件
#include <stdlib.h> // 用于exit函數(shù)
#include <stdio.h> // 用于printf函數(shù)
#include <utils/Log.h> // 包含Android日志系統(tǒng)頭文件// 定義線(xiàn)程執(zhí)行的函數(shù)
void *thread_posix_function(void *arg) {(void*)arg; // 忽略傳入的參數(shù),這里沒(méi)有使用int i;for (i = 0; i < 30; i++) {printf("hello thread i = %d\n", i); // 打印到標(biāo)準(zhǔn)輸出ALOGD("hello thread i = %d\n", i); // 使用Android日志系統(tǒng)打印DEBUG級(jí)別日志sleep(1); // 線(xiàn)程暫停1秒}return NULL; // 線(xiàn)程函數(shù)結(jié)束,返回空指針
}int main(void) {pthread_t mythread; // 定義一個(gè)線(xiàn)程標(biāo)識(shí)符// 創(chuàng)建一個(gè)新的線(xiàn)程,執(zhí)行thread_posix_function函數(shù),傳入?yún)?shù)為NULLif (pthread_create(&mythread, NULL, thread_posix_function, NULL)) {ALOGD("error creating thread."); // 如果創(chuàng)建失敗,記錄錯(cuò)誤日志abort(); // 終止程序執(zhí)行}// 主線(xiàn)程等待mythread線(xiàn)程結(jié)束if (pthread_join(mythread, NULL)) {ALOGD("error joining thread."); // 如果等待失敗,記錄錯(cuò)誤日志abort(); // 終止程序執(zhí)行}ALOGD("hello thread has run end exit\n"); // 記錄日志,表明線(xiàn)程已正確執(zhí)行完畢exit(0); // 主程序正常退出
}
這段代碼首先定義了一個(gè)線(xiàn)程執(zhí)行的函數(shù)thread_posix_function
,該函數(shù)每隔一秒打印一次消息到控制臺(tái)和Android日志系統(tǒng),共打印30次。在main
函數(shù)中,它創(chuàng)建了一個(gè)新的線(xiàn)程并執(zhí)行thread_posix_function
,然后主線(xiàn)程等待這個(gè)新線(xiàn)程完成其任務(wù)后才退出。整個(gè)過(guò)程中,還利用了Android的日志系統(tǒng)來(lái)報(bào)告錯(cuò)誤或提供執(zhí)行狀態(tài)信息。
2.測(cè)試linux_thread模塊
在安卓源碼的根目錄下創(chuàng)建一個(gè)文件夾,并寫(xiě)上mk文件,提供編譯的腳本。
然后單獨(dú)編譯模塊名即可 ===== LOCAL_MODULE
把編譯后的可執(zhí)行二進(jìn)制文件push到設(shè)備中
執(zhí)行一下,可以看到線(xiàn)程在打印輸出。
3.Android native的Thread類(lèi)
Android native的Thread類(lèi)是Android提供的一個(gè)基礎(chǔ)類(lèi)
system\core\libutils\include\utils\Thread.h
system\core\libutils\Threads.cpp
智能指針,主要用來(lái)釋放和控制內(nèi)存。
virtual void onFirstRef();
第一次這個(gè)類(lèi)被創(chuàng)建就會(huì)執(zhí)行這個(gè)智能指針的這個(gè)方法,在這個(gè)方法里面我們就可以做一些事情了。執(zhí)行線(xiàn)程創(chuàng)建并啟動(dòng)運(yùn)行un方法,status_t run(const char* name, int32_t priority, size_t stack);,先執(zhí)行readyToRun(),創(chuàng)建完成后,通過(guò)調(diào)用threadLoop()函數(shù),線(xiàn)程請(qǐng)求退出方法,實(shí)現(xiàn)requestExit()函數(shù)。
3.1源碼分析
run()方法,可以看到它也是用的pthread那套線(xiàn)程api,Android的native層的線(xiàn)程就是基于linux的pthread方案進(jìn)行封裝的。
進(jìn)入_threadLoop
int Thread::_threadLoop(void* user)
{Thread* const self = static_cast<Thread*>(user);sp<Thread> strong(self->mHoldSelf);wp<Thread> weak(strong);self->mHoldSelf.clear();#if defined(__ANDROID__)// this is very useful for debugging with gdbself->mTid = gettid();
#endifbool first = true;do {bool result;if (first) {first = false;//我們一旦調(diào)用了線(xiàn)程的run方法之后首先執(zhí)行的就是這個(gè)readyToRun方法。self->mStatus = self->readyToRun();result = (self->mStatus == OK);if (result && !self->exitPending()) {// Binder threads (and maybe others) rely on threadLoop// running at least once after a successful ::readyToRun()// (unless, of course, the thread has already been asked to exit// at that point).// This is because threads are essentially used like this:// (new ThreadSubclass())->run();// The caller therefore does not retain a strong reference to// the thread and the thread would simply disappear after the// successful ::readyToRun() call instead of entering the// threadLoop at least once.result = self->threadLoop();}} else {result = self->threadLoop();}// establish a scope for mLock{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 scopeself->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 loopstrong = weak.promote();} while(strong != nullptr);return 0;
}
測(cè)試
#ifndef _MYTHREAD_H
#define _MYTHREAD_H#include <utils/threads.h>namespace android {class MyThread: public Thread {
public:MyThread();virtual void onFirstRef();virtual status_t readyToRun();virtual bool threadLoop();virtual void requestExit();
private:int hasRunCount = 0;
};}
#endif
#define LOG_TAG "MyThread"#include <utils/Log.h>
#include "MyThread.h"namespace android {MyThread::MyThread() :Thread(false) {ALOGD("MyThread");}bool MyThread::threadLoop() {ALOGD("threadLoop hasRunCount = %d",hasRunCount);hasRunCount++;if (hasRunCount == 10) {return false; }return true;}void MyThread::onFirstRef() {ALOGD("onFirstRef");}status_t MyThread::readyToRun() {ALOGD("readyToRun");return 0;}void MyThread::requestExit() {ALOGD("requestExit");}
}
同上linux_thread操作編譯push即可。
4.native層堆棧調(diào)試方法
android::CallStack()。所在線(xiàn)程的堆棧調(diào)用打印出來(lái)。
進(jìn)入對(duì)應(yīng)的cpp文件,解開(kāi)注釋,并且修改值為1
聲明頭文件
調(diào)用方法,
android::CallStack cs("zxx");cs.update();cs.log("zxx",ANDROID_LOG_ERROR,"=======================");
測(cè)試