android IPC及原理简介

什么是Android操作系统,所谓的Android:是基于Linux内核的软件平台和操作系统,早期由Google开发,后由开放手机联盟Open
Handset Alliance)开发。

Linux系统中进程间通信的方式有:socket, named pipe,message queque, signal,share
memory。Java系统中的进程间通信方式有socket, named
pipe等。android应用程序理所当然可以应用JAVA的IPC机制实现进程间的通信,

取而代之的是Binder通信。Google为什么要采用这种方式呢,这取决于Binder通信方式的高效率。
Binder通信是通过linux的binder driver来实现的。Binder通信操作类似线程迁移(thread
migration),两个进程间IPC看起来就象是一个进程进入另一个进程执行代码然后带着执行的结果返回。

Binder的用户空间为每一个进程维护着一个可用的线程池,线程池用于处理到来的IPC以及执行进程本地消息,Binder通信是同步而不是异步。Android中的Binder通信是基于Service与Client的,所有需要IBinder通信的进程都必须创建一个IBinder接口。

系统中有一个进程管理所有的system service,Android虚拟机不允许用户添加非授权的System
service,当然现在源码开发了,我们可以修改一些代码来实现添加底层system Service的目的。

对用户程序来说,我们也要创建server,或者Service用于进程间通信,这里有一ActivityManagerService管理JAVA应用层所有的service创建与连接(connect)。disconnect,所有的
Activity也是通过这个service来启动,加载的。ActivityManagerService也是加载在Systems Servcie中的。

Android虚拟机启动之前系统会先启动service Manager进程,service Manager打开binder驱动,并通知binder
kernel驱动程序这个进程将作为System Service Manager。然后该进程将进入一个循环,等待处理来自其他进程的数据。用户创建一个System
service后,通过defaultServiceManager得到一个远程ServiceManager的接口。

通过这个接口我们可以调用 addService函数将System service添加到Service
Manager进程中,然后client可以通过getService获取到需要连接的目的Service的IBinder对象。这个IBinder是
Service的BBinder在binder kernel的一个参考,所以service IBinder 在binder
kernel中不会存在相同的两个IBinder对象。

每一个Client进程同样需要打开Binder驱动程序。对用户程序而言,我们获得这个对象就可以通过binder
kernel访问service对象中的方法。Client与Service在不同的进程中,通过这种方式实现了类似线程间的迁移的通信方式,对用户程序而言当调用Service返回的IBinder接口后,访问Service中的方法就如同调用自己的函数。

实现接口时有几个原则:

抛出的异常不要返回给调用者.
跨进程抛异常处理是不可取的。IPC调用是同步的。如果你知道一个IPC服务需要超过几毫秒的时间才能完成地话,你应该避免在Activity的主线程中调用。

也就是IPC调用会挂起应用程序导致界面失去响应. 这种情况应该考虑单起一个线程来处理,能在AIDL接口中声明静态属性。IPC的调用步骤:

1. 声明一个接口类型的变量,该接口类型在.aidl文件中定义。

2. 实现ServiceConnection。

3.
调用ApplicationContext.bindService(),并在ServiceConnection实现中进行传递.

4. 在ServiceConnection.onServiceConnected()实现中,你会接收一个IBinder实例(被调用的Service).
调用  
 YourInterfaceName.Stub.asInterface((IBinder)service)将参数转换YourInterface类型。

5. 调用接口中定义的方法。 你总要检测到DeadObjectException异常,该异常在连接断开时被抛出。它只会被远程方法抛出。

6. 断开连接,调用接口实例中的ApplicationContext.unbindService()

IPC 及原理

IBinder接口

IBinder接口是对跨进程的对象的抽象。普通对象在当前进程可以访问,如果希望对象能被其它进程访问,那就必须实现IBinder接口。IBinder接口可以指向本地对象,也可以指向远程对象,调用者不需要关心指向的对象是本地的还是远程。

transact是IBinder接口中一个比较重要的函数,它的函数原型如下:

virtual status_t transact(uint32_t code, const Parcel& data, Parcel*
reply, uint32_t flags = 0) = 0;

android中的IPC的基本模型是基于客户/服务器(C/S)架构的。

客户端

请求通过内核模块中转

服务端

如果IBinder指向的是一个客户端代理,那transact只是把请求发送给服务器。服务端的IBinder的transact则提供了实际的服务。

o 客户端

BpBinder是远程对象在当前进程的代理,它实现了IBinder接口。它的transact函数实现如下:

status_t BpBinder::transact(

uint32_t code, const Parcel& data, Parcel* reply,
uint32_t flags)

{

// Once a binder has died, it will never come back to
life.

if (mAlive) {

status_t status =
IPCThreadState::self()->transact(

mHandle, code, data, reply,
flags);

if (status == DEAD_OBJECT) mAlive = 0;

return status;

}

return DEAD_OBJECT;

}

参数说明:

?  code 是请求的ID号。

?  data 是请求的参数。

?  reply 是返回的结果。

?  flags 一些额外的标识,如FLAG_ONEWAY。通常为0。

transact只是简单的调用了IPCThreadState::self()的transact,在IPCThreadState::transact中:

status_t IPCThreadState::transact(int32_t handle,

uint32_t code, const
Parcel& data,

Parcel* reply, uint32_t
flags)

{

status_t err = data.errorCheck();

flags |= TF_ACCEPT_FDS;

IF_LOG_TRANSACTIONS() {

TextOutput::Bundle _b(alog);

alog << "BC_TRANSACTION thr " <<
(void*)pthread_self() << " / hand "

<< handle << " / code
" << TypeCode(code) << ": "

<< indent << data
<< dedent << endl;

}

if (err == NO_ERROR) {

LOG_ONEWAY(">>>> SEND from pid %d
uid %d %s", getpid(), getuid(),

(flags & TF_ONE_WAY) == 0 ?
"READ REPLY" : "ONE WAY");

err = writeTransactionData(BC_TRANSACTION,
flags, handle, code, data, NULL);

}

if (err != NO_ERROR) {

if (reply) reply->setError(err);

return (mLastError = err);

}

if ((flags & TF_ONE_WAY) == 0) {

if (reply) {

err =
waitForResponse(reply);

} else {

Parcel fakeReply;

err =
waitForResponse(&fakeReply);

}

IF_LOG_TRANSACTIONS() {

TextOutput::Bundle
_b(alog);

alog << "BR_REPLY thr "
<< (void*)pthread_self() << " / hand "

<< handle
<< ": ";

if (reply) alog << indent
<< *reply << dedent << endl;

else alog << "(none
requested)" << endl;

}

} else {

err = waitForResponse(NULL, NULL);

}

return err;

}

status_t IPCThreadState::waitForResponse(Parcel *reply, status_t
*acquireResult)

{

int32_t cmd;

int32_t err;

while (1) {

if ((err=talkWithDriver()) < NO_ERROR)
break;

err = mIn.errorCheck();

if (err < NO_ERROR) break;

if (mIn.dataAvail() == 0) continue;

cmd = mIn.readInt32();

IF_LOG_COMMANDS() {

alog << "Processing
waitForResponse Command: "

<<
getReturnString(cmd) << endl;

}

switch (cmd) {

case BR_TRANSACTION_COMPLETE:

if (!reply &&
!acquireResult) goto finish;

break;

case BR_DEAD_REPLY:

err = DEAD_OBJECT;

goto finish;

case BR_FAILED_REPLY:

err = FAILED_TRANSACTION;

goto finish;

case BR_ACQUIRE_RESULT:

{

LOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT");

const int32_t
result = mIn.readInt32();

if (!acquireResult)
continue;

*acquireResult =
result ? NO_ERROR : INVALID_OPERATION;

}

goto finish;

case BR_REPLY:

{

binder_transaction_data tr;

err =
mIn.read(&tr, sizeof(tr));

LOG_ASSERT(err ==
NO_ERROR, "Not enough command data for brREPLY");

if (err !=
NO_ERROR) goto finish;

if (reply) {

if
((tr.flags & TF_STATUS_CODE) == 0) {

reply->ipcSetDataReference(

reinterpret_cast(tr.data.ptr.buffer),

tr.data_size,

reinterpret_cast(tr.data.ptr.offsets),

tr.offsets_size/sizeof(size_t),

freeBuffer, this);

}
else {

err = *static_cast(tr.data.ptr.buffer);

freeBuffer(NULL,

reinterpret_cast(tr.data.ptr.buffer),

tr.data_size,

reinterpret_cast(tr.data.ptr.offsets),

tr.offsets_size/sizeof(size_t), this);

}

} else {

freeBuffer(NULL,

reinterpret_cast(tr.data.ptr.buffer),

tr.data_size,

reinterpret_cast(tr.data.ptr.offsets),

tr.offsets_size/sizeof(size_t), this);

continue;

}

}

goto finish;

default:

err = executeCommand(cmd);

if (err != NO_ERROR) goto
finish;

break;

}

}

finish:

if (err != NO_ERROR) {

if (acquireResult) *acquireResult = err;

if (reply) reply->setError(err);

mLastError = err;

}

return err;

}

这里transact把请求经内核模块发送了给服务端,服务端处理完请求之后,沿原路返回结果给调用者。这里也可以看出请求是同步操作,它会等待直到结果返回为止。

在BpBinder之上进行简单包装,我们可以得到与服务对象相同的接口,调用者无需要关心调用的对象是远程的还是本地的。拿ServiceManager来说:

(frameworks/base/libs/utils/IServiceManager.cpp)

class BpServiceManager : public BpInterface

{

public:

BpServiceManager(const sp& impl)

: BpInterface(impl)

{

}

...

virtual status_t addService(const String16& name, const
sp& service)

{

Parcel data, reply;

data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());

data.writeString16(name);

data.writeStrongBinder(service);

status_t err =
remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);

return err == NO_ERROR ? reply.readInt32() :
err;

}

...

};

BpServiceManager实现了
IServiceManager和IBinder两个接口,调用者可以把BpServiceManager的对象看作是一个IServiceManager对象或者IBinder对象。当调用者把BpServiceManager对象当作IServiceManager对象使用时,所有的请求只是对BpBinder::transact的封装。这样的封装使得调用者不需要关心IServiceManager对象是本地的还是远程的了。

客户通过defaultServiceManager函数来创建BpServiceManager对象:

(frameworks/base/libs/utils/IServiceManager.cpp)

sp<IServiceManager> defaultServiceManager()

{

if (gDefaultServiceManager != NULL) return
gDefaultServiceManager;

{

AutoMutex _l(gDefaultServiceManagerLock);

if (gDefaultServiceManager == NULL) {

gDefaultServiceManager =
interface_cast<IServiceManager>(

ProcessState::self()->getContextObject(NULL));

}

}

return gDefaultServiceManager;

}

先通过ProcessState::self()->getContextObject(NULL)创建一个Binder对象,然后通过interface_cast和IMPLEMENT_META_INTERFACE(ServiceManager,
“android.os.IServiceManager”)把Binder对象包装成
IServiceManager对象。原理上等同于创建了一个BpServiceManager对象。

ProcessState::self()->getContextObject调用ProcessState::getStrongProxyForHandle创建代理对象:

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t
handle)

{

sp<IBinder> result;

AutoMutex _l(mLock);

handle_entry* e = lookupHandleLocked(handle);

if (e != NULL) {

// We need to create a new BpBinder if there
isn‘t currently one, OR we

// are unable to acquire a weak reference on
this current one.  See comment

// in getWeakProxyForHandle() for more info
about this.

IBinder* b = e->binder;

if (b == NULL ||
!e->refs->attemptIncWeak(this)) {

b = new BpBinder(handle);

e->binder = b;

if (b) e->refs =
b->getWeakRefs();

result = b;

} else {

// This little bit of nastyness
is to allow us to add a primary

// reference to the remote proxy
when this team doesn‘t have one

// but another team is sending
the handle to us.

result.force_set(b);

e->refs->decWeak(this);

}

}

return result;

}

如果handle为空,默认为context_manager对象,context_manager实际上就是ServiceManager。

o 服务端

服务端也要实现IBinder接口,BBinder类对IBinder接口提供了部分默认实现,其中transact的实现如下:

status_t BBinder::transact(

uint32_t code, const Parcel& data, Parcel* reply,
uint32_t flags)

{

data.setDataPosition(0);

status_t err = NO_ERROR;

switch (code) {

case PING_TRANSACTION:

reply->writeInt32(pingBinder());

break;

default:

err = onTransact(code, data,
reply, flags);

break;

}

if (reply != NULL) {

reply->setDataPosition(0);

}

return err;

}

PING_TRANSACTION请求用来检查对象是否还存在,这里简单的把
pingBinder的返回值返回给调用者。其它的请求交给onTransact处理。onTransact是BBinder里声明的一个protected类型的虚函数,这个要求它的子类去实现。比如CameraService里的实现如下:

status_t CameraService::onTransact(

uint32_t code, const Parcel& data, Parcel* reply,
uint32_t flags)

{

// permission checks...

switch (code) {

case BnCameraService::CONNECT:

IPCThreadState* ipc =
IPCThreadState::self();

const int pid =
ipc->getCallingPid();

const int self_pid =
getpid();

if (pid != self_pid) {

// we‘re called
from a different process, do the real check

if
(!checkCallingPermission(

String16("android.permission.CAMERA")))

{

const
int uid = ipc->getCallingUid();

LOGE("Permission Denial: "

"can‘t use the camera pid=%d, uid=%d", pid,
uid);

return PERMISSION_DENIED;

}

}

break;

}

status_t err = BnCameraService::onTransact(code, data, reply,
flags);

LOGD("+++ onTransact err %d code %d", err, code);

if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED)
{

// the ‘service‘ command interrogates this
binder for its name, and then supplies it

// even for the debugging commands.  that
means we need to check for it here, using

// ISurfaceComposer (since we delegated the
INTERFACE_TRANSACTION handling to

// BnSurfaceComposer before falling through to
this code).

LOGD("+++ onTransact code %d", code);

CHECK_INTERFACE(ICameraService, data,
reply);

switch(code) {

case 1000:

{

if (gWeakHeap != 0) {

sp h =
gWeakHeap.promote();

IMemoryHeap *p =
gWeakHeap.unsafe_get();

LOGD("CHECKING WEAK
REFERENCE %p (%p)", h.get(), p);

if (h != 0)

h->printRefs();

bool
attempt_to_delete = data.readInt32() == 1;

if
(attempt_to_delete) {

//
NOT SAFE!

LOGD("DELETING WEAK REFERENCE %p (%p)", h.get(), p);

if
(p) delete p;

}

return
NO_ERROR;

}

}

break;

default:

break;

}

}

return err;

}

由此可见,服务端的onTransact是一个请求分发函数,它根据请求码(code)做相应的处理。

o 消息循环

服务端(任何进程都可以作为服务端)有一个线程监听来自客户端的请求,并循环处理这些请求。

如果在主线程中处理请求,可以直接调用下面的函数:

IPCThreadState::self()->joinThreadPool(mIsMain);

如果想在非主线程中处理请求,可以按下列方式:

sp

proc = ProcessState::self();

if (proc->supportsProcesses()) {

LOGV("App process: starting
thread pool.\n");

proc->startThreadPool();

}

startThreadPool的实现原理:

void ProcessState::startThreadPool()

{

AutoMutex _l(mLock);

if (!mThreadPoolStarted) {

mThreadPoolStarted = true;

spawnPooledThread(true);

}

}

void ProcessState::spawnPooledThread(bool isMain)

{

if (mThreadPoolStarted) {

int32_t s = android_atomic_add(1,
&mThreadPoolSeq);

char buf[32];

sprintf(buf, "Binder Thread #%d", s);

LOGV("Spawning new pooled thread, name=%s\n",
buf);

sp

t = new PoolThread(isMain);

t->run(buf);

}

}

这里创建了PoolThread的对象,实现上就是创建了一个线程。所有的线程类都要实现threadLoop虚函数。PoolThread的threadLoop的实现如下:

virtual bool threadLoop()

{

IPCThreadState::self()->joinThreadPool(mIsMain);

return false;

}

上述代码,简而言之就是创建了一个线程,然后在线程里调用
IPCThreadState::self()->joinThreadPool函数。

下面再看joinThreadPool的实现:

do

{

...

result = talkWithDriver();

if (result >= NO_ERROR) {

size_t IN =
mIn.dataAvail();

if (IN < sizeof(int32_t))
continue;

cmd = mIn.readInt32();

IF_LOG_COMMANDS() {

alog <<
"Processing top-level Command: "

<< getReturnString(cmd) << endl;

}

result =
executeCommand(cmd);

}

...

while(...);

这个函数在循环中重复执行下列动作:

talkWithDriver 通过ioctl(mProcess->mDriverFD, BINDER_WRITE_READ,
&bwr)读取请求和写回结果。

executeCommand 执行相应的请求

在IPCThreadState::executeCommand(int32_t cmd)函数中:

对于控制对象生命周期的请求,像BR_ACQUIRE/BR_RELEASE直接做了处理。

对于BR_TRANSACTION请求,它调用被请求对象的transact函数。

按下列方式调用实际的对象:

if (tr.target.ptr) {

sp<BBinder> b((BBinder*)tr.cookie);

const status_t error = b->transact(tr.code, buffer,
&reply, 0);

if (error < NO_ERROR) reply.setError(error);

} else {

const status_t error =
the_context_object->transact(tr.code, buffer, &reply, 0);

if (error < NO_ERROR) reply.setError(error);

}

如果tr.target.ptr不为空,就把tr.cookie转换成一个Binder对象,并调用它的transact函数。如果没有目标对象,就调用
the_context_object对象的transact函数。奇怪的是,根本没有谁对the_context_object进行初始化,the_context_object是空指针。原因是context_mgr的请求发给了ServiceManager,所以根本不会走到else语句里来。

o 内核模块

android使用了一个内核模块binder来中转各个进程之间的消息。模块源代码放在binder.c里,它是一个字符驱动程序,主要通过binder_ioctl与用户空间的进程交换数据。其中BINDER_WRITE_READ用来读写数据,数据包中有一个cmd域用于区分不同的请求:

binder_thread_write用于发送请求或返回结果。

binder_thread_read用于读取结果。

从binder_thread_write中调用binder_transaction中转请求和返回结果,binder_transaction的实现如下:

对请求的处理:

通过对象的handle找到对象所在的进程,如果handle为空就认为对象是context_mgr,把请求发给context_mgr所在的进程。

把请求中所有的binder对象全部放到一个RB树中。

把请求放到目标进程的队列中,等待目标进程读取。

如何成为context_mgr呢?内核模块提供了BINDER_SET_CONTEXT_MGR调用:

static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long
arg)

{

...

case BINDER_SET_CONTEXT_MGR:

if
(binder_context_mgr_node != NULL) {

printk(KERN_ERR "binder: BINDER_SET_CONTEXT_MGR already
set\n");

ret = -EBUSY;

goto err;

}

if
(binder_context_mgr_uid != -1) {

if (binder_context_mgr_uid != current->euid) {

printk(KERN_ERR "binder:
BINDER_SET_"

"CONTEXT_MGR bad uid %d != %d\n",

current->euid,

binder_context_mgr_uid);

ret = -EPERM;

goto err;

}

} else

binder_context_mgr_uid = current->euid;

binder_context_mgr_node = binder_new_node(proc, NULL, NULL);

if
(binder_context_mgr_node == NULL) {

ret = -ENOMEM;

goto err;

}

binder_context_mgr_node->local_weak_refs++;

binder_context_mgr_node->local_strong_refs++;

binder_context_mgr_node->has_strong_ref = 1;

binder_context_mgr_node->has_weak_ref = 1;

break;

ServiceManager(frameworks/base/cmds/servicemanager)通过下列方式成为了context_mgr进程:

int binder_become_context_manager(struct binder_state *bs)

{

return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);

}

int main(int argc, char **argv)

{

struct binder_state *bs;

void *svcmgr = BINDER_SERVICE_MANAGER;

bs = binder_open(128*1024);

if (binder_become_context_manager(bs)) {

LOGE("cannot become context manager (%s)\n",
strerror(errno));

return -1;

}

svcmgr_handle = svcmgr;

binder_loop(bs, svcmgr_handler);

return 0;

}

o 如何得到服务对象的handle

服务提供者通过defaultServiceManager得到ServiceManager对象,然后调用addService向服务管理器注册。

服务使用者通过defaultServiceManager得到ServiceManager对象,然后调用getService通过服务名称查找到服务对象的handle。

o 如何通过服务对象的handle找到服务所在的进程

0表示服务管理器的handle,getService可以查找到系统服务的handle。这个handle只是代表了服务对象,内核模块是如何通过handle找到服务所在的进程的呢?

对于ServiceManager:
ServiceManager调用了binder_become_context_manager使用自己成为context_mgr,所有handle为0的请求都会被转发给ServiceManager。

对于系统服务和应用程序的Listener,在第一次请求内核模块时(比如调用addService),内核模块在一个RB树中建立了服务对象和进程的对应关系。

off_end = (void *)offp +
tr->offsets_size;

for (; offp < off_end; offp++) {

struct
flat_binder_object *fp;

if (*offp
> t->buffer->data_size - sizeof(*fp)) {

binder_user_error("binder: %d:%d got transaction with
"

"invalid offset,
%d\n",

proc->pid,
thread->pid, *offp);

return_error = BR_FAILED_REPLY;

goto err_bad_offset;

}

fp = (struct
flat_binder_object *)(t->buffer->data + *offp);

switch
(fp->type) {

case
BINDER_TYPE_BINDER:

case
BINDER_TYPE_WEAK_BINDER: {

struct binder_ref *ref;

struct binder_node *node = binder_get_node(proc,
fp->binder);

if (node == NULL) {

node =
binder_new_node(proc, fp->binder, fp->cookie);

if (node == NULL) {

return_error = BR_FAILED_REPLY;

goto err_binder_new_node_failed;

}

node->min_priority =
fp->flags & FLAT_BINDER_FLAG_PRIORITY_MASK;

node->accept_fds =
!!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);

}

if (fp->cookie != node->cookie) {

binder_user_error("binder: %d:%d sending u%p "

"node %d, cookie mismatch %p != %p\n",

proc->pid, thread->pid,

fp->binder, node->debug_id,

fp->cookie, node->cookie);

goto
err_binder_get_ref_for_node_failed;

}

ref = binder_get_ref_for_node(target_proc, node);

if (ref == NULL) {

return_error =
BR_FAILED_REPLY;

goto
err_binder_get_ref_for_node_failed;

}

if (fp->type == BINDER_TYPE_BINDER)

fp->type =
BINDER_TYPE_HANDLE;

else

fp->type =
BINDER_TYPE_WEAK_HANDLE;

fp->handle = ref->desc;

binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE,
&thread->todo);

if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)

printk(KERN_INFO "  
     node %d u%p -> ref %d desc %d\n",

node->debug_id, node->ptr, ref->debug_id, ref->desc);

}
break;

请求服务时,内核先通过handle找到对应的进程,然后把请求放到服务进程的队列中。

o C调用JAVA

前面我们分析的是C代码的处理。对于JAVA代码,JAVA调用C的函数通过JNI调用即可。从内核时读取请求是在C代码(executeCommand)里进行了,那如何在C代码中调用那些用JAVA实现的服务呢?

android_os_Binder_init里的JavaBBinder对Java里的Binder对象进行包装。

JavaBBinder::onTransact调用Java里的execTransact函数:

jboolean res =
env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,

code, (int32_t)&data,
(int32_t)reply, flags);

jthrowable excep =
env->ExceptionOccurred();

if (excep) {

report_exception(env,
excep,

"*** Uncaught
remote exception!  "

"(Exceptions are
not yet supported across processes.)");

res = JNI_FALSE;

/* clean up JNI local ref -- we
don‘t return to Java code */

env->DeleteLocalRef(excep);

}

o 广播消息

binder不提供广播消息,不过可以ActivityManagerService服务来实现广播。

(frameworks/base/core/java/android/app/ActivityManagerNative.java)

接收广播消息需要实现接口BroadcastReceiver,然后调用ActivityManagerProxy::registerReceiver注册。

触发广播调用ActivityManagerProxy::broadcastIntent。(应用程序并不直接调用它,而是调用Context对它的包装)

时间: 2024-10-01 04:59:54

android IPC及原理简介的相关文章

(转载)Android显示原理简介

Android应用程序显示的过程:Android应用程序调用SurfaceFlinger服务把经过测量.布局和绘制后的Surface渲染到显示屏幕上. 名词解释 SurfaceFlinger:Android系统服务,负责管理Android系统的帧缓冲区,即显示屏幕. Surface:Android应用的每个窗口对应一个画布(Canvas),即Surface,可以理解为Android应用程序的一个窗口. Android应用程序的显示过程包含了两个部分(应用侧绘制.系统侧渲染).两个机制(进程间通讯

Android IPC机制(五)用Socket实现跨进程聊天程序

相关文章: Android IPC机制(一)开启多进程 Android IPC机制(二)用Messenger进行进程间通信 Android IPC机制(三)在Android Studio中使用AIDL实现跨进程方法调用 Android IPC机制(四)用ContentProvider进行进程间通信 1.Socket简介 Socket也称作"套接字",是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信.它分为流式套接字和

Android IPC机制(三):浅谈Binder的使用

一.前言 在上一篇博客Android IPC机制(二):AIDL的基本用法中,笔者讲述了安卓进程间通讯的一个主要方式.利用AIDL进行通讯.并介绍了AIDL的基本用法. 事实上AIDL方式利用了Binder来进行跨进程通讯.Binder是Android中的一种跨进程通讯方式.其底层实现原理比較复杂.限于笔者水平,不能展开详谈.所以这篇文章主要谈谈以AIDL为例,谈谈Binder的用法. 二.原理 上一篇文章中创建了一个IMyAidl.aidl文件,即接口文件,随即编译了该文件.生成了一个.jav

android IPC通信(下)-AIDL

android IPC通信(上)-sharedUserId&&Messenger android IPC通信(中)-ContentProvider&&Socket 这篇我们将会着重介绍AIDL的使用方式和原理,要介绍AIDL先要简单介绍一下Binder,而且Messenger,ContentProvider和AIDL的最底层都是使用的Binder. Binder 直观来说,Binder是Android中的一个类,它实现了IBinder接口.从IPC角度来说,Binder是A

android IPC通信(上)-sharedUserId&amp;amp;&amp;amp;Messenger

看了一本书,上面有一章解说了IPC(Inter-Process Communication,进程间通信)通信.决定结合曾经的一篇博客android 两个应用之间的通信与调用和自己的理解来好好整理总结一下这块的知识.因为内容较多,这部分会分上中下三篇博客来细致分析解说,第一篇上篇要解说的是sharedUserId和Messenger的使用方式. android IPC通信(中)-ContentProvider&&Socket android IPC通信(下)-AIDL sharedUserI

GitHub Android Libraries Top 100 简介

GitHub Android Libraries Top 100 简介 排名完全是根据 GitHub 搜索 Java 语言选择 (Best Match) 得到的结果, 然后过滤了跟 Android 不相关的项目, 所以排名并不具备任何官方效力, 仅供参考学习, 方便初学者快速了解当前一些流行的 Android 开源库. 项目名称 项目简介 1. react-native 这个是 Facebook 在 React.js Conf 2015 大会上推出的基于 JavaScript 的开源框架 Rea

android Binder机制原理

Android Binder机制原理(史上最强理解,没有之一)(转) 原文地址: http://blog.csdn.net/universus/article/details/6211589 Binder是Android系统进程间通信(IPC)方式之一.Linux已经拥有的进程间通信IPC手段包括(Internet Process Connection): 管道(Pipe).信号(Signal)和跟踪(Trace).插口(Socket).报文队列(Message).共享内存(Share Memo

Android加壳原理分析

0x00 阅读本文前,建议读者首先阅读Android加壳原理,参考文章Android中的Apk的加固(加壳)原理解析和实现.如果没有看过这篇文章,本文理解起来比较困难. 0x01 下面我们来分析脱壳代码为什么要这样写,核心脱壳代码在ProxyApplication类里面,首先执行成员方法attachBaseContext,然后执行成员方法onCreate. 那么attachBaseContext是什么时候被执行的呢,为什么先于onCreate执行呢?那就需要看Android的源码了,我们选用的是

【转】浏览器的渲染原理简介

How Browsers Work 这篇文章把浏览器的很多细节讲的很细,也有中文的翻译版本,现在转载的这篇是陈皓写的,目的的为了能在上班途中,或是坐马桶时就能读完,并能从中学会一些能用在工作上的东西. 浏览器工作大流程 先看个图 从图中,可以看到: 1) 浏览器会解析三个东西 * 一个 HTML/SVG/XHTML,事实上,Webkit 有三个C++的类对应这三类文档.解析这三种文件会产生一个DOM Tree * CSS,解析CSS会产生CSS规则树 * JavaScript 脚本,主要是通过