当初跟踪Camera的代码中的时候一直追到了HAL层,而在Framework中的代码看见了许许多多的Thread。它们普遍的特点就是有一个threadLoop方法。按照字面的意思应该是这个线程能够循环处理数据。对应我想到到了java上层中的HandlerThread,这个估计也差不多,但当时心里总有一个疙瘩,想弄清楚它为什么能够循环,还有它到底是怎么循环起来的? Android中java世界的Thread我们先来看看java是怎么创建一个线程的。这个是最舒服的,也是我最熟悉的。 new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub ... }}).start();
当然,你也可以在android中创建一个消息循环的HandlerThread HandlerThread mThread = new HandlerThread('test');mThread.start();Handler mHandler = new Handler(mThread.getLooper()){ @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super.handleMessage(msg); }};
上面中通过mHandler发送消息就可以在mThread中处理了,并且这个mThread不是UIThread,不会阻塞主线程。 Linux下c语言的Threadjava世界的Thread很方便,那么c呢? 我把里面的例子改良了一下 #include
然后编译 gcc -o test test.c -lpthread./test
运行结果如下 main thread running ,count : 0the pthread running ,count: 0main thread running ,count : 1the pthread running ,count: 1main thread running ,count : 2the pthread running ,count: 2main thread running ,count : 3the pthread running ,count: 3main thread running ,count : 4the pthread running ,count: 4main thread will exit when pthread is overthe pthread running ,count: 5the pthread running ,count: 6the pthread running ,count: 7main thread exit
例子比较简单,主要是创建一个线程,然后主线程等待子线程运行完毕再退出。 Android Framework中的Thread下面焦点回到文章的主题当中,我们来看看Framework中常用的Thread是个何种形态。 #ifndef AUDIO_WATCHDOG_H#define AUDIO_WATCHDOG_H#include
我们可以看到AudioWatchDog确实是Thread的子类,那好,下面看实现。 #define LOG_TAG 'AudioWatchdog'//#define LOG_NDEBUG 0#include <utils/Log.h>#include 'AudioWatchdog.h'namespace android {bool AudioWatchdog::threadLoop(){ { AutoMutex _l(mMyLock); if (mPaused) { mMyCond.wait(mMyLock); // ignore previous timestamp after resume() mOldTsValid = false; // force an immediate log on first underrun after resume() mLogTs.tv_sec = MIN_TIME_BETWEEN_LOGS_SEC; mLogTs.tv_nsec = 0; // caller will check for exitPending() return true; } } struct timespec newTs; int rc = clock_gettime(CLOCK_MONOTONIC, &newTs); if (rc != 0) { pause(); return false; } if (!mOldTsValid) { mOldTs = newTs; mOldTsValid = true; return true; } time_t sec = newTs.tv_sec - mOldTs.tv_sec; long nsec = newTs.tv_nsec - mOldTs.tv_nsec; if (nsec < 0) { --sec; nsec += 1000000000; } mOldTs = newTs; // cycleNs is same as sec*1e9 + nsec, but limited to about 4 seconds uint32_t cycleNs = nsec; if (sec > 0) { if (sec < 4) { cycleNs += sec * 1000000000; } else { cycleNs = 4000000000u; } } mLogTs.tv_sec += sec; if ((mLogTs.tv_nsec += nsec) >= 1000000000) { mLogTs.tv_sec++; mLogTs.tv_nsec -= 1000000000; } if (cycleNs > mMaxCycleNs) { mDump->mUnderruns = ++mUnderruns; if (mLogTs.tv_sec >= MIN_TIME_BETWEEN_LOGS_SEC) { mDump->mLogs = ++mLogs; mDump->mMostRecent = time(NULL); ALOGW('Insufficient CPU for load: expected=%.1f actual=%.1f ms; underruns=%u logs=%u', mPeriodNs * 1e-6, cycleNs * 1e-6, mUnderruns, mLogs); mLogTs.tv_sec = 0; mLogTs.tv_nsec = 0; } } struct timespec req; req.tv_sec = 0; req.tv_nsec = mPeriodNs; rc = nanosleep(&req, NULL); if (!((rc == 0) || (rc == -1 && errno == EINTR))) { pause(); return false; } return true;}void AudioWatchdog::requestExit(){ // must be in this order to avoid a race condition Thread::requestExit(); resume();}void AudioWatchdog::pause(){ AutoMutex _l(mMyLock); mPaused = true;}void AudioWatchdog::resume(){ AutoMutex _l(mMyLock); if (mPaused) { mPaused = false; mMyCond.signal(); }}} // namespace android
很明显,它的核心方法就是threadLoop(),在本文中我们不关心它具体的功能,只想确定它是怎么启动的呢?又是怎么循环运行的呢?带着疑问我又在源码中搜索关键字AudioWatchdog /frameworks/av/services/audioflinger/AudioFlinger.h/frameworks/av/services/audioflinger/AudioFlinger.cpp
在AudioFlinger.h中MixerThread中有个AudioWatchdog的sp对象 class MixerThread : public PlaybackThread { public: MixerThread (const sp
我们再看代码 AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device, type_t type) : PlaybackThread(audioFlinger, output, id, device, type), // mAudioMixer below // mFastMixer below mFastMixerFutex(0) // mOutputSink below // mPipeSink below // mNormalSink below{......#ifdef AUDIO_WATCHDOG // create and start the watchdog mAudioWatchdog = new AudioWatchdog(); mAudioWatchdog->setDump(&mAudioWatchdogDump); //AudioWatchdog的run方法在此调用,所以线程启动 mAudioWatchdog->run('AudioWatchdog', PRIORITY_URGENT_AUDIO); tid = mAudioWatchdog->getTid(); err = requestPriority(getpid_cached, tid, kPriorityFastMixer); if (err != 0) { ALOGW('Policy SCHED_FIFO priority %d is unavailable for pid %d tid %d; error %d', kPriorityFastMixer, getpid_cached, tid, err); }#endif......}
删掉不相关代码,我们看到AudioWatchdog对象确实创建了,并且调用了它的run方法。在java中Thread的run方法就是启动,这个也应该如此。但是如之前的源码所示AudioWatchdog.cpp中并没有实现run方法,怎么办呢?别紧张,它还有父类Thread. /frameworks/native/include/utils/Thread.h #ifndef _LIBS_UTILS_THREAD_H#define _LIBS_UTILS_THREAD_H#include
可以看到确实有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; if (mCanCallJava) { res = createThreadEtc(_threadLoop, this, name, priority, stack, &mThread); } else { 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}
run()方法中有这么一段 if (mCanCallJava) { res = createThreadEtc(_threadLoop, this, name, priority, stack, &mThread); } else { res = androidCreateRawThreadEtc(_threadLoop, this, name, priority, stack, &mThread); }
mCanCallJava的意思是能不能被JNI层调用,然后根据值去创建Thread,这里有两个分支,我们就选择createThreadEtc() int androidCreateRawThreadEtc(android_thread_func_t entryFunction, void *userData, const char* threadName, int32_t threadPriority, size_t threadStackSize, android_thread_id_t *threadId){ ...... entryFunction = (android_thread_func_t)&thread_data_t::trampoline; userData = t; }#endif if (threadStackSize) { pthread_attr_setstacksize(&attr, threadStackSize); } errno = 0; pthread_t thread; //在此创建,文章开头我有写例子怎么用c语言创建一个线程 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; } ...... return 1;}
删除了不相关代码,大家看看是不是很熟悉啊。我在文章开始的部分就写出了linux下c语言pthread创建线程的例子,大家可以回头看看。也就是pthread_create()。这里面传进来的entryFunction是Thread中的_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();#ifdef HAVE_ANDROID_OS // this is very useful for debugging with gdb self->mTid = gettid();#endif bool first = true; do { bool result; if (first) { first = false; self->mStatus = self->readyToRun(); result = (self->mStatus == NO_ERROR); 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. //调用threadLoop() 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 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;}
_threadLoop()这个方法就是Thread的最大秘密,它是一个while循环。
所以在这里,我开始时的疑问—为什么线程Thread中的threadLoop()能够循环处理数据就到此做了说明。 !!! 特殊情况有的时候Android Framework中Thread的run()方法很难发现在哪里被调用。如SurfaceFlinger它也是一个Thread子类。在源码中搜索可以发现它的创建位置 class SurfaceFlinger : public BinderService
去找它创建的地方 extern 'C' status_t system_init(){ ALOGI('Entered system_init()'); sp
我们可以看到 SurfaceFlinger::instantiate();
但它本身并没有实现instantiate()方法,那之类找它的父类了。 namespace android {template
会调用publish()方法。 然后我们看SurfaceFlinger的构造函数 SurfaceFlinger::SurfaceFlinger() : BnSurfaceComposer(), Thread(false), mTransactionFlags(0), mTransactionPending(false), mAnimTransactionPending(false), mLayersRemoved(false), mRepaintEverything(0), mBootTime(systemTime()), mVisibleRegionsDirty(false), mHwWorkListDirty(false), mDebugRegion(0), mDebugDDMS(0), mDebugDisableHWC(0), mDebugDisableTransformHint(0), mDebugInSwapBuffers(0), mLastSwapBufferTime(0), mDebugInTransaction(0), mLastTransactionTime(0), mBootFinished(false){ ALOGI('SurfaceFlinger is starting'); // debugging stuff... char value[PROPERTY_VALUE_MAX]; property_get('debug.sf.showupdates', value, '0'); mDebugRegion = atoi(value); property_get('debug.sf.ddms', value, '0'); mDebugDDMS = atoi(value); if (mDebugDDMS) { if (!startDdmConnection()) { // start failed, and DDMS debugging not enabled mDebugDDMS = 0; } } ALOGI_IF(mDebugRegion, 'showupdates enabled'); ALOGI_IF(mDebugDDMS, 'DDMS debugging enabled');}
但是遗憾的是没有发现run()方法的影踪,没有办法只得去父类构造方法看 没有办法,继续在源码中搜索SurfaceFlinger,结果发现与之相关的信息大多是sp 上面的链接讲得还算详细。这里纠结sp的过多细节,长话短说,总之第一次对SurfaceFlinger引用调用sp void SurfaceFlinger::onFirstRef(){ mEventQueue.init(this); //run方法在此被调用 run('SurfaceFlinger', PRIORITY_URGENT_DISPLAY); // Wait for the main thread to be done with its initialization mReadyToRunBarrier.wait();}
看见没有?run()方法在这里调用了。 所以,在Framework中如果你找不到一个Thread在何处被启动,那么去它的onFirstRef()方法中去看看吧 |
|
来自: Elaine个人小馆 > 《C 学习》