アプリプロセス初期化Binder、ServiceManagerサービスの取得
63982 ワード
データ構造
ProcesState:ユーザー空間でプロセス状態を表し、個々のプロセスはProcessiteオブジェクトだけです.Binderドライバのオープンとスレッドプールの作成を担当しています.
IPCThreadState:ユーザ空間下のスレッドはIPCthreadStateを通じて、binder駆動とコマンドインタラクションを行う.
アプリプロセス起動
Initプロセスはzygoteプロセス、system_を起動しました.serverプロセス、ServiceManagerプロセス、lwkdサービスなど
zygoteは、binder通信を利用していません.socketを利用して情報を受信し、ZygoteInit.main()を実行した後、runSelectLoop()の循環体内に入り、クライアント接続があるとZygoteConnection.runOnce()の方法を実行し、再度呼び出した後、forkに新しいアプリケーションを作成します.
java層Process.start()は、ZygoteConnection.run Once()でプロセスを開始します.
startThreadPoolはPool Threadを作成して現在のスレッドを表し、binderスレッドとして登録します.
IPCThreadStateスレッドでは、ioctlを行い、binderカーネルでbinder_uに入る.ioctl_write_read、bwrが読み出しキャッシュのデータがあれば、
二つのプロセスの間で相互に渡されるデータフォーマットはbinder_である.トランスアクションダタ
プロセスとドライバが互いに転送するデータフォーマットはbinder_です.write_read
それはもっと多くのbinderスレッドが必要かもしれません.binder_を処理します.トランスアクションデータ
その前に、いくつかのデータ構造を紹介します.
IBinder
ユーザプロセス空間において、binderエンティティを表す.
ユーザプロセス空間で、binderエージェントを表します.
アプリでServiceManagerを取得すると、ServiceManagerの代理を取得し、binder駆動の角度から見ると、App対応のbinder_です.procは対応するビッドカーを取得します.refは、Appユーザーのプロセスを見て、AppはServiceManagerに対応するBpBinderを取得します.
ProcesStateはプロセスの一例で、現在のプロセス状態を表します.
Processistate::self()->get Contect Object(NULL)アプリを利用してServiceManagerのBpBinderを取得しましたが、BpBinderのhandleは0です.
gDefault ServiceManager=interface_cast(Processist::self()->get Contect Object(NULL);IServiceManagerに変換し、続いてAppプロセスはServiceManagerに照会する必要があるサービスですが、実はbinderのプロセスをまたぐ通信です.
ProcesState:ユーザー空間でプロセス状態を表し、個々のプロセスはProcessiteオブジェクトだけです.Binderドライバのオープンとスレッドプールの作成を担当しています.
IPCThreadState:ユーザ空間下のスレッドはIPCthreadStateを通じて、binder駆動とコマンドインタラクションを行う.
アプリプロセス起動
Initプロセスはzygoteプロセス、system_を起動しました.serverプロセス、ServiceManagerプロセス、lwkdサービスなど
zygoteは、binder通信を利用していません.socketを利用して情報を受信し、ZygoteInit.main()を実行した後、runSelectLoop()の循環体内に入り、クライアント接続があるとZygoteConnection.runOnce()の方法を実行し、再度呼び出した後、forkに新しいアプリケーションを作成します.
java層Process.start()は、ZygoteConnection.run Once()でプロセスを開始します.
// ZygoteConnection.runOnce
boolean runOnce(ZygoteServer zygoteServer) throws Zygote.MethodAndArgsCaller {
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
parsedArgs.appDataDir);
...
if (pid == 0) { // fork , pid 0,
zygoteServer.closeServerSocket(); // zygote socket
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
return true;
}
}
private void handleChildProc(Arguments parsedArgs,
FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
throws Zygote.MethodAndArgsCaller {
...
ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs, null /* classLoader */);
}
// ZygoteInit.java
public static final void zygoteInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {
RuntimeInit.commonInit();
ZygoteInit.nativeZygoteInit();
RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
ZygontenInit//frameworks/base/core/jni/AndroidRuntime.cpp
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}
// frameworks/base/cmds/app_process/App_main.cpp
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
proc->startThreadPool();
}
プロセスはProcessStateの例しかなく、Processistateオブジェクトが確立された時にのみBinderデバイスを開け、メモリマッピングを行う.// frameworks/native/libs/binder/ProcessState.cpp
//
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
return gProcess;
}
gProcess = new ProcessState("/dev/binder");
return gProcess;
}
ProcessState::ProcessState(const char *driver)
: mDriverName(String8(driver))
, mDriverFD(open_driver(driver))
, mVMStart(MAP_FAILED)
, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
, mExecutingThreadsCount(0)
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
, mStarvationStartTimeMs(0)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
{
if (mDriverFD >= 0) {
// mmap the binder, providing a chunk of virtual address space to receive transactions.
mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
close(mDriverFD);
mDriverFD = -1;
mDriverName.clear();
}
}
}
open_driver、mmapは分析しましたので、参考にしてください.https://blog.csdn.net/qq_15893929/articale/detail/10395875startThreadPoolはPool Threadを作成して現在のスレッドを表し、binderスレッドとして登録します.
void ProcessState::startThreadPool()
{
AutoMutex _l(mLock);
if (!mThreadPoolStarted) {
mThreadPoolStarted = true;
spawnPooledThread(true);
}
}
//
void ProcessState::spawnPooledThread(bool isMain)
{
if (mThreadPoolStarted) {
String8 name = makeBinderThreadName();
sp<Thread> t = new PoolThread(isMain);
t->run(name.string());
}
}
PoolThreadはbinderスレッドを表します.class PoolThread : public Thread
{
public:
explicit PoolThread(bool isMain)
: mIsMain(isMain)
{
}
protected:
virtual bool threadLoop()
{
IPCThreadState::self()->joinThreadPool(mIsMain);
return false;
}
const bool mIsMain;
};
IPCThreadStateとbinderドライバのインタラクティブvoid IPCThreadState::joinThreadPool(bool isMain)
{
// , BC_ENTER_LOOPER, BC_REGISTER_LOOPER
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
status_t result;
do {
processPendingDerefs(); //
// now get the next command to be processed, waiting if necessary
result = getAndExecuteCommand(); //
if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) {
ALOGE("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",
mProcess->mDriverFD, result);
abort();
}
// Let this thread exit the thread pool if it is no longer
// needed and it is not the main process thread.
if(result == TIMED_OUT && !isMain) {
break;
}
} while (result != -ECONNREFUSED && result != -EBADF);
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}
status_t IPCThreadState::getAndExecuteCommand()
{
status_t result;
int32_t cmd;
result = talkWithDriver();
if (result >= NO_ERROR) {
...
pthread_mutex_unlock(&mProcess->mThreadCountLock);
result = executeCommand(cmd);
pthread_mutex_lock(&mProcess->mThreadCountLock);
...
}
return result;
}
// binder ioctl, bwr, mOut、mIn
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
binder_write_read bwr;
…
bwr.write_consumed = 0;
bwr.read_consumed = 0;
status_t err;
do {
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
err = NO_ERROR;
else
err = -errno;
} while (err == -EINTR);
if (err >= NO_ERROR) {
if (bwr.write_consumed > 0) {
if (bwr.write_consumed < mOut.dataSize())
mOut.remove(0, bwr.write_consumed);
else
mOut.setDataSize(0);
}
if (bwr.read_consumed > 0) {
mIn.setDataSize(bwr.read_consumed);
mIn.setDataPosition(0);
}
return NO_ERROR;
}
return err;
}
status_t IPCThreadState::executeCommand(int32_t cmd)
{
BBinder* obj;
RefBase::weakref_type* refs;
status_t result = NO_ERROR;
switch ((uint32_t)cmd) {
case BR_ACQUIRE:
...
break;
case BR_TRANSACTION:
...
break;
}
return result;
}
どのように新しいbinderスレッドを追加しますか?同時に複数のタスクが実行されますので.IPCThreadStateスレッドでは、ioctlを行い、binderカーネルでbinder_uに入る.ioctl_write_read、bwrが読み出しキャッシュのデータがあれば、
二つのプロセスの間で相互に渡されるデータフォーマットはbinder_である.トランスアクションダタ
プロセスとドライバが互いに転送するデータフォーマットはbinder_です.write_read
それはもっと多くのbinderスレッドが必要かもしれません.binder_を処理します.トランスアクションデータ
static int binder_thread_read(struct binder_proc *proc, struct binder_thread *thread, binder_uintptr_t binder_buffer, size_t size,binder_size_t *consumed, int non_block)
{
void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
void __user *ptr = buffer + *consumed;
void __user *end = buffer + size;
int ret = 0;
int wait_for_proc_work;
retry:
binder_inner_proc_lock(proc);
// , todo
wait_for_proc_work = binder_available_for_proc_work_ilocked(thread);
binder_inner_proc_unlock(proc);
// , BINDER_LOOPER_STATE_WAITING*/
thread->looper |= BINDER_LOOPER_STATE_WAITING;
if (non_block) {
if (!binder_has_work(thread, wait_for_proc_work))
ret = -EAGAIN;
} else {
// wait_for_proc_work ,
ret = binder_wait_for_work(thread, wait_for_proc_work);
}
thread->looper &= ~BINDER_LOOPER_STATE_WAITING;
if (ret)
return ret;
while (1) {
uint32_t cmd;
struct binder_transaction_data_secctx tr;
struct binder_transaction_data *trd = &tr.transaction_data;
struct binder_work *w = NULL;
switch (w->type) {
case BINDER_WORK_TRANSACTION: {
...
} break;
case BINDER_WORK_RETURN_ERROR: {
...
} break;
…
}
done:
*consumed = ptr - buffer;
binder_inner_proc_lock(proc);
// , binder_thread, BR_SPAWN_LOOPER
if (proc->requested_threads == 0 && list_empty(&thread->proc->waiting_threads) && proc->requested_threads_started < proc->max_threads &&
(thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) /* the user-space code fails to */
/*spawn a new thread if we leave this out */) {
proc->requested_threads++;
binder_inner_proc_unlock(proc);
// BR_SPAWN_LOOPER
if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer))
return -EFAULT;
binder_stat_br(proc, thread, BR_SPAWN_LOOPER);
} else
binder_inner_proc_unlock(proc);
return 0;
}
引き続きユーザープロセスIPCThreadStateを見て、どうやってBR_を処理しますか?SPAWN_LOOPARstatus_t IPCThreadState::executeCommand(int32_t cmd)
{
switch ((uint32_t)cmd) {
mProcess->spawnPooledThread(false);
break;
}
return result;
}
ServiceManagerサービスの取得その前に、いくつかのデータ構造を紹介します.
IBinder
class IBinder : public virtual RefBase
{
public:
virtual sp<IInterface> queryLocalInterface(const String16& descriptor);
// IInterface
virtual status_t pingBinder() = 0;
virtual status_t transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) = 0;
// IPC
virtual status_t linkToDeath(const sp<DeathRecipient>& recipient, void* cookie = NULL,
uint32_t flags = 0) = 0;
//
virtual BBinder* localBinder();
// , BBinder, binder
virtual BpBinder* remoteBinder();
// , BpBinder, binder
}
BBinderユーザプロセス空間において、binderエンティティを表す.
class BBinder : public IBinder
{
protected:
virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
// IPC
private:
std::atomic<Extras*> mExtras;
void* mReserved0;
}
BPBinderユーザプロセス空間で、binderエージェントを表します.
// , binder_ref handle
class BpBinder : public IBinder
{
public:
inline int32_t handle() const { return mHandle; }
virtual status_t transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
// IPC
KeyedVector<const void*, entry_t> mObjects;
};
private:
const int32_t mHandle;
mutable Mutex mLock;
volatile int32_t mAlive;
volatile int32_t mObitsSent;
Vector<Obituary>* mObituaries;
ObjectManager mObjects;
Parcel* mConstantData;
mutable String16 mDescriptorCache;
};
すべてのプロセスがServiceMangerを取得するのはIServiceMnager.cppの静的な方法である.アプリでServiceManagerを取得すると、ServiceManagerの代理を取得し、binder駆動の角度から見ると、App対応のbinder_です.procは対応するビッドカーを取得します.refは、Appユーザーのプロセスを見て、AppはServiceManagerに対応するBpBinderを取得します.
// framework/native/libs/binder/IServiceMnager.cpp
sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
while (gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
if (gDefaultServiceManager == NULL)
sleep(1);
}
}
return gDefaultServiceManager;
}
ProcessState::self()->get Contact Object(NULL)からServiceManagerを取得し、空であればServiceManagerプロセスがまだ起きていないと説明し、sleepに入り、再度循環して取得し、空でないまで再度取得します.ProcesStateはプロセスの一例で、現在のプロセス状態を表します.
// frameworks/native/libs/binder/ProcessState.cppkkj
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
// 0, ServiceManager BpBinder
return getStrongProxyForHandle(0);
}
struct handle_entry {
IBinder* binder; // BBinder BpBinder
RefBase::weakref_type* refs;
};
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
// BBinder BpBinder, BpBinder
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
if (handle == 0) { // handle 0, ServiceManager
Parcel data;
// binder_ioctl, handle binder
status_t status = IPCThreadState::self()->transact(0, IBinder::PING_TRANSACTION, data, NULL, 0);
if (status == DEAD_OBJECT)
return NULL;
}
// BpBinder
b = new BpBinder(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
詳細な参照:http://gityuan.com/2016/10/29/binder-thread-pool/Processistate::self()->get Contect Object(NULL)アプリを利用してServiceManagerのBpBinderを取得しましたが、BpBinderのhandleは0です.
gDefault ServiceManager=interface_cast(Processist::self()->get Contect Object(NULL);IServiceManagerに変換し、続いてAppプロセスはServiceManagerに照会する必要があるサービスですが、実はbinderのプロセスをまたぐ通信です.