binder ---service add到 service manager

以一个MediaPlayerService添加为例子:

int main(int argc, char** argv)
{
    sp<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> sm = defaultServiceManager();
    LOGI("ServiceManager: %p", sm.get());
    AudioFlinger::instantiate();
    MediaPlayerService::instantiate();
    CameraService::instantiate();
    AudioPolicyService::instantiate();
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
}

1、创建一个ProcessState实例
a)、打开binder驱动
b)、获取binder版本
c)、设置线程数


2、添加service到serviceManager(一般调用 defaultServiceManager()->addService(name,service))
	 virtual status_t addService(const String16& name, const sp<IBinder>& 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.readExceptionCode()   
    } 
a)、service binder实体是如何传到binder驱动
  1)、通过writeStrongBinder将其写入Parcel序列化对象,修改其mDataPos,mObjectsSize等
  2)、在writeTransactionData将参数以binder_transaction_data结构组织写入mOut
  3)、将mOut中的数据传到 binder_write_read bwr; 的write_buffer
  4)、驱动中获取传入的数据后重新转化成binder_transaction_data结构,然后获取binder实体位置
  5)、new一个binder_node结构保存在该service的内核中,添加到它的binder_proc中
  
b)、service与binder驱动交互流程
1)、调用ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr);
2)、驱动进入binder_thread_write
(1)、分配了一个待处理事务t和待完成工作项tcomplete
(2)、把处理线程设置为service manager
(3)、在处理线程中分配空间 binder_alloc_buf,并把参数拷贝进来
(4)、获取binder结构地址,在内核中为其分配一个binder_node结构,插入该线程binder_proc
(5)、为该binder实体分配一个引用,把分配到service manager中的binder改为引用,赋值引用值
(6)、把待处理的事务加入到service manager处理线程的todo列表,唤醒它
(7)、待完成工作项加入到本线程的todo队列

3)、驱动进入binder_thread_read
(1)、写入用户空间参数BR_NOOP,修改ptr
(2)、从todo队列取得前面加入的待完成项
(3)、写入用户空间参数BR_TRANSACTION_COMPLETE,修改ptr,删除前面取得的待完成项
(4)、修改consumed
4)、回到用户态
(1)、先取到BR_NOOP,不做事
(2)、再次进入 talkWithDriver,bwr.write_size和bwr.read_size全为0直接返回
(3)、进入 waitForResponse,由于reply不为空,再次返回到talkWithDriver
(4)、needRead就为true了,而outAvail仍为0,所以bwr.read_size不为0,bwr.write_size为0,通过ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) 进入 wait_event_interruptible睡眠
 
c)、service manager唤醒后处理client请求
1)、从binder_thread_read唤醒
2)、获取事务t,把相应的数据拷贝到本地局部变量struct binder_transaction_data tr(指针映射到用户空间)
3)、把事务t从todo列表中删除,放在thread->transaction_stack队列的头部
4)、本地变量struct binder_write_read bwr的内容拷贝回到用户传进来的缓冲区中,返回
5)、调用binder_parse进行解析
6)、获取service名称和一个弱引用的binder,构造一个个struct svcinfo结构,插入到链接svclist的头部
7)、调用binder_send_reply往驱动发送两个命令BC_FREE_BUFFER,BC_REPLY,第一个用于释放binder_transaction分配的空间( binder_alloc_buf),后者用于告诉 service它 的addService操作已经完成了,错误码是0,保存在data.txn.data中
8)、返回驱动,处理第一个命令,先释放前面的空间
9)、对于BC_REPLY,调用binder_transaction分配一个事件t,target_thread 设为请求add service的进程,把事务t放到它的todo队列,并唤醒它
10)、service manager重新回到binder_loop,等待下一个client的请求

d)、service被manager唤醒后
1)、从binder_thread_read唤醒
2)、将写在t->buffer->data里面的数据映射成用户空间地址(加上proc->user_buffer_offset)
3)、回到用户空间IPCThreadState::talkWithDriver函数
4)、处理BR_REPLY,把结果保存在reply里,跳出入循环


3、service等待处理client请求
1)、调用startThreadPool最终调用spwanPooledThread创建一个线程并执行
2)、threadLoop函数即为PoolThread::threadLoop函数,调用joinThreadPool
3)、joinThreadPool调用 talkWithDriver和Binder驱动程序进行交互,再调用executeCommand来处理请求
4)、对于BR_TRANSACTION调用b->transact(tr.code, buffer, &reply, tr.flags); 
5)、b->transact最终调用onTransact处理请求

最后引用老罗的一个图:


你可能感兴趣的:(binder ---service add到 service manager)