-
打开binder设备:
service_manager.c 源码中:if (argc > 1) { driver = argv[1]; } else { driver = "/dev/binder"; //打开binder设备文件,返回文件描述符 } bs = binder_open(driver, 128*1024); // binder 的 buffer缓冲区创建,用于进程间数据的传输
-
打开一个binder设备文件,并且开启一个128k的内存映射。
binder.c 有内存映射mmap()
函数调用bs->fd = open(driver, O_RDWR | O_CLOEXEC); // 打开binder设备 // ... bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0); // 开启内存映射
mmap 函数是在系统启动的时候就开启了binder映射,查看源码System.map
-
ServiceManager启动
init.rc中启动ServiceManager服务
-
打包Parcel中,数据写入binder设备,copy_from_user
- IServiceManager.cpp源码中,搜索
addService
parcel对象,将Service相关的信息打包到parcel对象,并且通过virtual status_t addService(const String16& name, const sp<IBinder>& service, bool allowIsolated, int dumpsysPriority) { Parcel data, reply; //parcel对象,将Service相关的信息打包 data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); data.writeString16(name); data.writeStrongBinder(service); data.writeInt32(allowIsolated ? 1 : 0); data.writeInt32(dumpsysPriority); status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply); return err == NO_ERROR ? reply.readExceptionCode() : err; }
remote()->transact
方法传输到下一步,
- 如何将数据写入binder设备,查看IIPCThreadState.cpp源码,IPCThreadState.h
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
- IServiceManager.cpp源码中,搜索
-
服务注册,添加到链表svclist中
int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint32_t handle, uid_t uid, int allow_isolated, uint32_t dumpsys_priority, pid_t spid) { struct svcinfo *si; //ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle, // allow_isolated ? "allow_isolated" : "!allow_isolated", uid); if (!handle || (len == 0) || (len > 127)) return -1; if (!svc_can_register(s, len, spid, uid)) {//检查服务权限, ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n", str8(s, len), handle, uid); return -1; } si = find_svc(s, len);//检查服务是否已经在svclist链表上注册过 if (si) { if (si->handle) { ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n", str8(s, len), handle, uid); svcinfo_death(bs, si); } si->handle = handle; } else { si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t)); //没有注册过,分配服务管理结构svcinfo,并将其添加到链表的list当中。 if (!si) { ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n", str8(s, len), handle, uid); return -1; } si->handle = handle; si->len = len; memcpy(si->name, s, (len + 1) * sizeof(uint16_t)); si->name[len] = '\0'; si->death.func = (void*) svcinfo_death; si->death.ptr = si; si->allow_isolated = allow_isolated; si->dumpsys_priority = dumpsys_priority; si->next = svclist; //将代表该服务的结构添加到链表中 svclist = si; } binder_acquire(bs, handle); // 增加binder的应用 计数 binder_link_to_death(bs, handle, &si->death);//如果服务退出之后,就需要通知ServiceManager return 0; }
以上整个过程,就是Server如何向ServerManager添加服务的注册过程。
-
定义主线程的线程池,不停地读写
查看IIPCThreadState.cpp源码void IPCThreadState::joinThreadPool(bool isMain) { LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid()); 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); LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%d\n", (void*)pthread_self(), getpid(), result); mOut.writeInt32(BC_EXIT_LOOPER); talkWithDriver(false); }
-
循环从
mIn mOut
中取出读写请求,发送的binder的设备中pthread_setspecific(gTLS, this); //将对象设置为当前线程的私有 clearCaller(); mIn.setDataCapacity(256); //输入分配256字节的空间 mOut.setDataCapacity(256);//输出分配256字节的空间
输入/出 预分配256字节的空间,主要工作循环从
mIn mOut
中进行IO的读写工作,然后发送的binder的设备中来。继续往下,是如何检查是否有数据要读?
binder_write_read bwr; // Is the read buffer empty? const bool needRead = mIn.dataPosition() >= mIn.dataSize(); //检查是否有读数据的请求 // We don't want to write anything if we are still reading // from data left in the input buffer and the caller // has requested to read the next data. const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0; // //检查是否有写数据的请求 // 省略代码.... if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0) //将读写的请求 发送到binder中来 err = NO_ERROR; else err = -errno;
平时项目中,碰到的第三方登录,分享。实际就是跨进行。