android的ashmem和pmem确实通过BpMemoryHeap和mm..
时间:2010-11-05 来源:gliethttp
《关于AudioFlinger中ashmem匿名共享内存的理解》
binder驱动binder_transaction
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); binder_debug(BINDER_DEBUG_TRANSACTION, " fd %ld -> %d\n", fp->handle, target_fd); /* TODO: fput? */ fp->handle = target_fd; } break; 以上的file = fget(fp->handle)和task_get_unused_fd_flags共同完成dup包含操作集fops的file,然后assertReallyMapped将再次执行mmap,映射ashmem或pmem申请到的同一块物理内存. BpMemoryHeap::assertReallyMapped remote()->transact(HEAP_ID, data, &reply); 会被binder另一端的onTransact函数接收并处理 BnMemoryHeap::onTransact 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); } }
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); }
void* BpMemoryHeap::getBase() const { assertMapped(); return mBase; }
BpMemoryHeap::assertMapped 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(); // 这会做实际的map工作 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(); // 在驱动binder_transaction中BINDER_TYPE_FD // 然后remote的file结构体,在kernel中被执行file = fget(fp->handle);获取设备描述符号 ssize_t size = reply.readInt32(); uint32_t flags = reply.readInt32();
LOGE_IF(err, "binder=%p transaction failed fd=%d, size=%ld, err=%d (%s)", asBinder().get(), parcel_fd, size, err, strerror(-err));
int fd = dup( parcel_fd ); LOGE_IF(fd==-1, "cannot dup fd=%d, size=%ld, err=%d (%s)", parcel_fd, size, err, strerror(errno));
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); } } } }
BootAnimation::BootAnimation() : Thread(false) { mSession = new SurfaceComposerClient(); // 与SurfaceFlinger创建一个Connection,也叫session }
SurfaceComposerClient::SurfaceComposerClient() sp<ISurfaceComposer> sm(getComposerService()); // 就是binder获取"SurfaceFlinger"系统服务,即SurfaceFlinger::instantiate()添加的service _init(sm, sm->createConnection());
SurfaceFlinger::createConnection() ==> sp<Client> client = new Client(token, this); ==> sp<BClient> bclient = new BClient(this, token, client->getControlBlockMemory());
frameworks/base/libs/surfaceflinger/SurfaceFlinger.cpp Client::Client(ClientID clientID, const sp<SurfaceFlinger>& flinger) : ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger) { const int pgsize = getpagesize(); const int cblksize = ((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1));
mCblkHeap = new MemoryHeapBase(cblksize, 0, "SurfaceFlinger Client control-block");
ctrlblk = static_cast<SharedClient *>(mCblkHeap->getBase()); if (ctrlblk) { // construct the shared structure in-place. new(ctrlblk) SharedClient; } }
首先在上面通过createConnection()创建一个client,然后才能创建SurfaceFlinger::createSurface
SurfaceComposerClient::createSurface
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); binder_debug(BINDER_DEBUG_TRANSACTION, " fd %ld -> %d\n", fp->handle, target_fd); /* TODO: fput? */ fp->handle = target_fd; } break; 以上的file = fget(fp->handle)和task_get_unused_fd_flags共同完成dup包含操作集fops的file,然后assertReallyMapped将再次执行mmap,映射ashmem或pmem申请到的同一块物理内存. BpMemoryHeap::assertReallyMapped remote()->transact(HEAP_ID, data, &reply); 会被binder另一端的onTransact函数接收并处理 BnMemoryHeap::onTransact 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); } }
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); }
void* BpMemoryHeap::getBase() const { assertMapped(); return mBase; }
BpMemoryHeap::assertMapped 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(); // 这会做实际的map工作 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(); // 在驱动binder_transaction中BINDER_TYPE_FD // 然后remote的file结构体,在kernel中被执行file = fget(fp->handle);获取设备描述符号 ssize_t size = reply.readInt32(); uint32_t flags = reply.readInt32();
LOGE_IF(err, "binder=%p transaction failed fd=%d, size=%ld, err=%d (%s)", asBinder().get(), parcel_fd, size, err, strerror(-err));
int fd = dup( parcel_fd ); LOGE_IF(fd==-1, "cannot dup fd=%d, size=%ld, err=%d (%s)", parcel_fd, size, err, strerror(errno));
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); } } } }
BootAnimation::BootAnimation() : Thread(false) { mSession = new SurfaceComposerClient(); // 与SurfaceFlinger创建一个Connection,也叫session }
SurfaceComposerClient::SurfaceComposerClient() sp<ISurfaceComposer> sm(getComposerService()); // 就是binder获取"SurfaceFlinger"系统服务,即SurfaceFlinger::instantiate()添加的service _init(sm, sm->createConnection());
SurfaceFlinger::createConnection() ==> sp<Client> client = new Client(token, this); ==> sp<BClient> bclient = new BClient(this, token, client->getControlBlockMemory());
frameworks/base/libs/surfaceflinger/SurfaceFlinger.cpp Client::Client(ClientID clientID, const sp<SurfaceFlinger>& flinger) : ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger) { const int pgsize = getpagesize(); const int cblksize = ((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1));
mCblkHeap = new MemoryHeapBase(cblksize, 0, "SurfaceFlinger Client control-block");
ctrlblk = static_cast<SharedClient *>(mCblkHeap->getBase()); if (ctrlblk) { // construct the shared structure in-place. new(ctrlblk) SharedClient; } }
首先在上面通过createConnection()创建一个client,然后才能创建SurfaceFlinger::createSurface
SurfaceComposerClient::createSurface
相关阅读 更多 +