一、Ashmem驱动程序
~/Android/kernel/goldfish
----include
----linux
----ashmem.h
----mm
----ashmem.c
驱动程序详解请看《Android系统源代码情景分析》,作者罗升阳。
二、运行时库cutils的匿名共享内存访问接口
~/Android/system/core
----libcutils
----ashmem-dev.c
详解请看《Android系统源代码情景分析》,作者罗升阳。
三、MemoryHeapBase
1、Server端实现
我们只分析下面3个类
IMemoryHeap--->IMemory.h,IMemory.cpp
BnMemoryHeap--->IMemory.h,IMemory.cpp
MemoryHeapBase--->MemoryHeapBase.h,MemoryHeapBase.cpp
详解请看《Android系统源代码情景分析》,作者罗升阳,这里只列出代码。
IMemoryHeap(IMemory.h)
class IMemoryHeap : public IInterface { public: DECLARE_META_INTERFACE(MemoryHeap); // flags returned by getFlags() enum { READ_ONLY = 0x00000001 }; virtual int getHeapID() const = 0; virtual void* getBase() const = 0; virtual size_t getSize() const = 0; virtual uint32_t getFlags() const = 0; // these are there just for backward source compatibility int32_t heapID() const { return getHeapID(); } void* base() const { return getBase(); } size_t virtualSize() const { return getSize(); } };
BnMemoryHeap(IMemory.cpp)
status_t BnMemoryHeap::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { case HEAP_ID: { CHECK_INTERFACE(IMemoryHeap, data, reply); reply->writeFileDescriptor(getHeapID()); reply->writeInt32(getSize()); reply->writeInt32(getFlags()); return NO_ERROR; } break; default: return BBinder::onTransact(code, data, reply, flags); } }
MemoryHeapBase(MemoryHeapBase.cpp)
MemoryHeapBase::MemoryHeapBase(size_t size, uint32_t flags, char const * name) : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags), mDevice(0), mNeedUnmap(false) { const size_t pagesize = getpagesize(); size = ((size + pagesize-1) & ~(pagesize-1)); int fd = ashmem_create_region(name == NULL ? "MemoryHeapBase" : name, size); LOGE_IF(fd<0, "error creating ashmem region: %s", strerror(errno)); if (fd >= 0) { if (mapfd(fd, size) == NO_ERROR) { if (flags & READ_ONLY) { ashmem_set_prot_region(fd, PROT_READ); } } } } ...... status_t MemoryHeapBase::mapfd(int fd, size_t size, uint32_t offset) { ..... if ((mFlags & DONT_MAP_LOCALLY) == 0) { void* base = (uint8_t*)mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset); ...... mBase = base; mNeedUnmap = true; } else { ..... } mFD = fd; mSize = size; return NO_ERROR; } ......... int MemoryHeapBase::getHeapID() const { return mFD; } void* MemoryHeapBase::getBase() const { return mBase; } size_t MemoryHeapBase::getSize() const { return mSize; } uint32_t MemoryHeapBase::getFlags() const { return mFlags; }
2、Client端实现
我们只分析下面2个类
IMemoryHeap--->IMemory.h,IMemory.cpp
BpMemoryHeap--->IMemory.cpp
详解请看《Android系统源代码情景分析》,作者罗升阳。
BpMemoryHeap(IMemory.cpp)
BpMemoryHeap::BpMemoryHeap(const sp<IBinder>& impl) : BpInterface<IMemoryHeap>(impl), mHeapId(-1), mBase(MAP_FAILED), mSize(0), mFlags(0), mRealHeap(false) { } ....... void BpMemoryHeap::assertMapped() const { if (mHeapId == -1) { sp<IBinder> binder(const_cast<BpMemoryHeap*>(this)->asBinder()); sp<BpMemoryHeap> heap(static_cast<BpMemoryHeap*>(find_heap(binder).get())); heap->assertReallyMapped(); if (heap->mBase != MAP_FAILED) { Mutex::Autolock _l(mLock); if (mHeapId == -1) { mBase = heap->mBase; mSize = heap->mSize; android_atomic_write( dup( heap->mHeapId ), &mHeapId ); } } else { // something went wrong free_heap(binder); } } } void BpMemoryHeap::assertReallyMapped() const { if (mHeapId == -1) { // remote call without mLock held, worse case scenario, we end up // calling transact() from multiple threads, but that's not a problem, // only mmap below must be in the critical section. Parcel data, reply; data.writeInterfaceToken(IMemoryHeap::getInterfaceDescriptor()); status_t err = remote()->transact(HEAP_ID, data, &reply); int parcel_fd = reply.readFileDescriptor(); ssize_t size = reply.readInt32(); uint32_t flags = reply.readInt32(); ......... int fd = dup( parcel_fd ); ........ int access = PROT_READ; if (!(flags & READ_ONLY)) { access |= PROT_WRITE; } Mutex::Autolock _l(mLock); if (mHeapId == -1) { mRealHeap = true; mBase = mmap(0, size, access, MAP_SHARED, fd, 0); if (mBase == MAP_FAILED) { LOGE("cannot map BpMemoryHeap (binder=%p), size=%ld, fd=%d (%s)", asBinder().get(), size, fd, strerror(errno)); close(fd); } else { mSize = size; mFlags = flags; android_atomic_write(fd, &mHeapId); } } } } int BpMemoryHeap::getHeapID() const { assertMapped(); return mHeapId; } void* BpMemoryHeap::getBase() const { assertMapped(); return mBase; } size_t BpMemoryHeap::getSize() const { assertMapped(); return mSize; } uint32_t BpMemoryHeap::getFlags() const { assertMapped(); return mFlags; }
四、MemoryBase
1、Server端实现
我们只分析下面3个类
IMemory--->IMemory.h,IMemory.cpp
BnMemory--->IMemory.h,IMemory.cpp
MemoryBase--->MemoryBase.h,MemoryBase.cpp
详解请看《Android系统源代码情景分析》,作者罗升阳。
IMemory(IMemory.h)
class IMemory : public IInterface { public: DECLARE_META_INTERFACE(Memory); virtual sp<IMemoryHeap> getMemory(ssize_t* offset=0, size_t* size=0) const = 0; // helpers void* fastPointer(const sp<IBinder>& heap, ssize_t offset) const; void* pointer() const; size_t size() const; ssize_t offset() const; };IMemory(IMemory.cpp)
void* IMemory::pointer() const { ssize_t offset; sp<IMemoryHeap> heap = getMemory(&offset); void* const base = heap!=0 ? heap->base() : MAP_FAILED; if (base == MAP_FAILED) return 0; return static_cast<char*>(base) + offset; } size_t IMemory::size() const { size_t size; getMemory(NULL, &size); return size; } ssize_t IMemory::offset() const { ssize_t offset; getMemory(&offset); return offset; }
status_t BnMemory::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { case GET_MEMORY: { CHECK_INTERFACE(IMemory, data, reply); ssize_t offset; size_t size; reply->writeStrongBinder( getMemory(&offset, &size)->asBinder() ); reply->writeInt32(offset); reply->writeInt32(size); return NO_ERROR; } break; default: return BBinder::onTransact(code, data, reply, flags); } }
MemoryBase::MemoryBase(const sp<IMemoryHeap>& heap, ssize_t offset, size_t size) : mSize(size), mOffset(offset), mHeap(heap) { } sp<IMemoryHeap> MemoryBase::getMemory(ssize_t* offset, size_t* size) const { if (offset) *offset = mOffset; if (size) *size = mSize; return mHeap; }
2、Client端实现
我们只分析下面2个类
IMemory--->IMemory.h,IMemory.cpp
BpMemory--->IMemory.cpp
详解请看《Android系统源代码情景分析》,作者罗升阳。
BpMemory(IMemory.cpp)
sp<IMemoryHeap> BpMemory::getMemory(ssize_t* offset, size_t* size) const { if (mHeap == 0) { Parcel data, reply; data.writeInterfaceToken(IMemory::getInterfaceDescriptor()); if (remote()->transact(GET_MEMORY, data, &reply) == NO_ERROR) { sp<IBinder> heap = reply.readStrongBinder(); ssize_t o = reply.readInt32(); size_t s = reply.readInt32(); if (heap != 0) { mHeap = interface_cast<IMemoryHeap>(heap);//mHeap if (mHeap != 0) { mOffset = o;//mOffset mSize = s;//mSize } } } } if (offset) *offset = mOffset; if (size) *size = mSize; return mHeap; }
五、应用实例
~/Android/external/ashmem
----common
----ISharedBuffer.h
----ISharedBuffer.cpp
----server
----SharedBufferServer.cpp
----Android.mk
----client
----SharedBufferClient.cpp
----Android.mk
1、Server端实现
想象上面的图。
我们只分析下面3个类
ISharedBuffer--->ISharedBuffer.h,ISharedBuffer.cpp
BnSharedBuffer--->ISharedBuffer.h,ISharedBuffer.cpp
SharedBufferService--->SharedBufferServer.cpp
详解请看《Android系统源代码情景分析》,作者罗升阳。
ISharedBuffer(ISharedBuffer.h)
class ISharedBuffer: public IInterface { public: DECLARE_META_INTERFACE(SharedBuffer); virtual sp<IMemory> getBuffer() = 0; };
BnSharedBuffer(ISharedBuffer.cpp)
status_t BnSharedBuffer::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { case GET_BUFFER: { CHECK_INTERFACE(ISharedBuffer, data, reply); sp<IMemory> buffer = getBuffer(); if(buffer != NULL) { reply->writeStrongBinder(buffer->asBinder()); } return NO_ERROR; } default: { return BBinder::onTransact(code, data, reply, flags); } } }
class SharedBufferService : public BnSharedBuffer { public: SharedBufferService() { sp<MemoryHeapBase> heap = new MemoryHeapBase(SHARED_BUFFER_SIZE, 0, "SharedBuffer"); if(heap != NULL) { mMemory = new MemoryBase(heap, 0, SHARED_BUFFER_SIZE); int32_t* data = (int32_t*)mMemory->pointer(); if(data != NULL) { *data = 0; } } } virtual ~SharedBufferService() { mMemory = NULL; } public: static void instantiate() { defaultServiceManager()->addService(String16(SHARED_BUFFER_SERVICE), new SharedBufferService()); } virtual sp<IMemory> getBuffer() { return mMemory; } private: sp<MemoryBase> mMemory; };
2、Client端实现
想象上面的图。我们只分析下面2个类
ISharedBuffer--->ISharedBuffer.h,ISharedBuffer.cpp
BpSharedBuffer--->ISharedBuffer.cpp
详解请看《Android系统源代码情景分析》,作者罗升阳。
BpSharedBuffer(ISharedBuffer.cpp)
class BpSharedBuffer: public BpInterface<ISharedBuffer> { public: BpSharedBuffer(const sp<IBinder>& impl) : BpInterface<ISharedBuffer>(impl) { } public: sp<IMemory> getBuffer() { Parcel data; data.writeInterfaceToken(ISharedBuffer::getInterfaceDescriptor()); Parcel reply; remote()->transact(GET_BUFFER, data, &reply); sp<IMemory> buffer = interface_cast<IMemory>(reply.readStrongBinder()); return buffer; } };
六、执行代码
SharedBufferServer.cpp
........ int main(int argc, char** argv) { SharedBufferService::instantiate(); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); return 0; }
int main() { sp<IBinder> binder = defaultServiceManager()->getService(String16(SHARED_BUFFER_SERVICE)); if(binder == NULL) { printf("Failed to get service: %s.\n", SHARED_BUFFER_SERVICE); return -1; } sp<ISharedBuffer> service = ISharedBuffer::asInterface(binder); if(service == NULL) { return -2; } sp<IMemory> buffer = service->getBuffer(); if(buffer == NULL) { return -3; } int32_t* data = (int32_t*)buffer->pointer(); if(data == NULL) { return -4; } printf("The value of the shared buffer is %d.\n", *data); *data = *data + 1; printf("Add value 1 to the shared buffer.\n"); return 0; }
我们从service->getBuffer()开始分析,下面的执行流程如下图:
由于第5步reply->writeStrongBinder(buffer->asBinder());//SharedBufferServer的本地对象,writeStrongBinder请参考http://blog.csdn.net/jltxgcy/article/details/26059215。
在第6步和第7步之间,经历的过程是下面:
static void binder_transaction(struct binder_proc *proc, struct binder_thread *thread, struct binder_transaction_data *tr, int reply) { struct binder_transaction *t; struct binder_work *tcomplete; size_t *offp, *off_end; struct binder_proc *target_proc; struct binder_thread *target_thread = NULL; struct binder_node *target_node = NULL; struct list_head *target_list; wait_queue_head_t *target_wait; struct binder_transaction *in_reply_to = NULL; struct binder_transaction_log_entry *e; uint32_t return_error; ...... offp = (size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *))); ...... off_end = (void *)offp + tr->offsets_size; for (; offp < off_end; offp++) { struct flat_binder_object *fp; ...... 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; ...... } } ...... }形成了SharedBufferServer的实体对象和SharedBufferClient引用对象,传递给Client。
接下来执行:
sp<IMemory> buffer = interface_cast<IMemory>(reply.readStrongBinder());
又形成了SharedBufferClient代理对象。readStrongBinder请参考http://blog.csdn.net/jltxgcy/article/details/26370733。
interface_cast<IMemory>( )的实现请参考,http://blog.csdn.net/jltxgcy/article/details/25953361。
接下来执行:
int32_t* data = (int32_t*)buffer->pointer();调用IMemory的pointer,然后调用BpMemory的getMemory函数, 又执行了一遍上图的流程,只是把BpSharedBuffer变成BpMemory,把BnSharedBuffer变成BnMemory。
然后接着执行:
void* const base = heap!=0 ? heap->base() : MAP_FAILED;调用IMemoryHeap的base函数,最终调用到BpMemoryHeap的getBase函数,又调用到BpMemoryHeap的assertReallyMapped函数, 又执行了一遍上图的流程,只是把BpSharedBuffer变成BpMemoryHeap,把BnSharedBuffer变成BnMemoryHeap。此时有一点不同,就是第6步到第7步执行过程如下:
static void binder_transaction(struct binder_proc *proc, struct binder_thread *thread, struct binder_transaction_data *tr, int reply) { struct binder_transaction *t; struct binder_work *tcomplete; size_t *offp, *off_end; struct binder_proc *target_proc; struct binder_thread *target_thread = NULL; struct binder_node *target_node = NULL; struct list_head *target_list; wait_queue_head_t *target_wait; struct binder_transaction *in_reply_to = NULL; struct binder_transaction_log_entry *e; uint32_t return_error; ...... offp = (size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *))); ...... off_end = (void *)offp + tr->offsets_size; for (; offp < off_end; offp++) { struct flat_binder_object *fp; ...... fp = (struct flat_binder_object *)(t->buffer->data + *offp); switch (fp->type) { ...... case BINDER_TYPE_FD: { int target_fd; struct file *file; if (reply) { if (!(in_reply_to->flags & TF_ACCEPT_FDS)) { binder_user_error("binder: %d:%d got reply with fd, %ld, but target does not allow fds\n", proc->pid, thread->pid, fp->handle); return_error = BR_FAILED_REPLY; goto err_fd_not_allowed; } } else if (!target_node->accept_fds) { binder_user_error("binder: %d:%d got transaction with fd, %ld, but target does not allow fds\n", proc->pid, thread->pid, fp->handle); return_error = BR_FAILED_REPLY; goto err_fd_not_allowed; } file = fget(fp->handle); if (file == NULL) { binder_user_error("binder: %d:%d got transaction with invalid fd, %ld\n", proc->pid, thread->pid, fp->handle); return_error = BR_FAILED_REPLY; goto err_fget_failed; } target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC); if (target_fd < 0) { fput(file); return_error = BR_FAILED_REPLY; goto err_get_unused_fd_failed; } task_fd_install(target_proc, target_fd, file); if (binder_debug_mask & BINDER_DEBUG_TRANSACTION) printk(KERN_INFO " fd %ld -> %d\n", fp->handle, target_fd); /* TODO: fput? */ fp->handle = target_fd; } break; ...... } } ...... }
status_t Parcel::writeFileDescriptor(int fd) { flat_binder_object obj; obj.type = BINDER_TYPE_FD; obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; obj.handle = fd; obj.cookie = (void*)0; return writeObject(obj, true); }
int Parcel::readFileDescriptor() const { const flat_binder_object* flat = readObject(true); if (flat) { switch (flat->type) { case BINDER_TYPE_FD: //LOGI("Returning file descriptor %ld from parcel %p\n", flat->handle, this); return flat->handle; } } return BAD_TYPE; }
接下来的分析,请看Android系统匿名共享内存Ashmem(Anonymous Shared Memory)在进程间共享的原理分析http://blog.csdn.net/luoshengyang/article/details/6666491。
注意上文中的这句话, 这里, 我们需要关注的便是虚线框部分了,它在Binder驱动程序中实现了在两个进程中共享同一个打开文件的方法。我们知道,在Linux系统中,文件描述符其实就是一个整数。每一个进程在内核空间都有一个打开文件的数组,这个文件描述符的整数值就是用来索引这个数组的,而且,这个文件描述符只是在本进程内有效,也就是说,在不同的进程中,相同的文件描述符的值,代表的可能是不同的打开文件。因此,在进程间传输文件描述符时,不能简要地把一个文件描述符从一个进程传给另外一个进程,中间必须做一过转换,使得这个文件描述在目标进程中是有效的,并且它和源进程的文件描述符所对应的打开文件是一致的,这样才能保证共享。
也就是根据fd,得到的file结构,在两个进程是一样的,即使两个进程的fd不一样。
也就是在Server端的文件描述符,不能在Client端直接使用,而需要经过上面的转换,这时候得到文件描述符,再调用mmap映射到Client进程地址空间,就与Server共享一个匿名共享内存了。
接着:
printf("The value of the shared buffer is %d.\n", *data); *data = *data + 1; printf("Add value 1 to the shared buffer.\n");和
sp<MemoryHeapBase> heap = new MemoryHeapBase(SHARED_BUFFER_SIZE, 0, "SharedBuffer"); if(heap != NULL) { mMemory = new MemoryBase(heap, 0, SHARED_BUFFER_SIZE); int32_t* data = (int32_t*)mMemory->pointer(); if(data != NULL) { *data = 0; } }
它们两个操作的是同一个内存。
最后附上一张,整体的流程图: