深入解析Binder源码

Linux鼻祖LinusTorvalds曾说过的一句话:Read The Fucking Source Code。

注:以下记录需对照着源码看

目录

一、Binder核心方法:

二、Binder通信协议:

三、Binder启动ServiceManager:

四、获取ServiceManager

五、注册服务addService

六、获取服务getService()

七、Framework层分析


一、Binder核心方法:

java 复制代码
binder_init()驱动设备的初始化
	misc_register()注册misc设备
binder_open()打开binder驱动设备
	binder_proc对象 管理IPC所需的各种信息,并拥有其他结构体的根结构体
	filp->private_data = proc;  把binder_proc对象保存到文件指针filp
binder_mmap() 用户空间的Buffer和内核空间的Buffer映射
	area=get_vm_area() 分配一个连续的内核虚拟空间,与用户虚拟空间大小一致
	binder_update_page_range() 分配物理页面,同时映射到内核空间和用户空间
		alloc_page() 分配一个page的物理内存
		ret=map_kernel_range_noflush() 物理空间映射到虚拟内核空间
		ret=vm_insert_page() 物理空间映射到虚拟用户空间
	//binder_alloc_buf() 用于分配内存
 binder_ioctl() 数据操作( ioctl(文件描述符,ioctl命令,数据类型))
	binder_get_thread() 获取binder_thread
		 //根据当前进程的pid,从binder_proc中查找相应的binder_thread
		 //如果不存在则创建binderthread,并将当前线程添加到当前的proc
	binder_ioctl_write_read() 进行binder读写操作
		copy_from_user() 把用户空间的数据ubuf拷贝到内核空间bwr
			if(bwr.write_size>0即bwr写缓存有数据) 
				ret=binder_thread_write() 执行binder写操作
				if(ret<0写失败)
					copy_to_user将bwr数据写回用户空间
			if(bwr.read_size>0读缓存中有数据)
				ret=binder_thread_read() 执行binder读操作
				if(ret<0读失败)
					copy_to_user将bwr数据写回用户空间
			if(copy_to_user()) 将内核数据bwr拷贝到用户空间ubuf

二、Binder通信协议:

java 复制代码
binder_thread_write() 处理Binder协议中的请求码。
	请求码为BC_TRANSACTION或BC_REPLY
		copy_from_user()//拷贝用户空间tr到内核
		binder_transaction()
			分配两个结构体内存
			从target_proc分配一块buffer
			向目标进程的target_list添加BINDER_WORK_TRANSACTION事务
			向当前线程的todo队列添加BINDER_WORK_TRANSACTION_COMPLETE事务
binder_thread_read() 根据不同的binder_work->type以及不同状态,生成相应的响应码。
	根据wait_for_proc_work来决定wait在当前线程还是进程的等待队列

三、Binder启动ServiceManager:

java 复制代码
1.打开bndier驱动,binder_open
2.注册成为binder服务的大管家:binder_beome_context_manager
3.启动无限循环,处理client端发来的binder
service_manager.c中的main() service_manager 的入口函数
	binder_open() 打开binder驱动,申请内存
		open() 通过系统调用陷入内核,打开Binder设备驱动
		通过系统调用,ioctl获取binder版本信息
		mmap()通过系统调用,mmap内存映射,mmap必须是page的整数倍
	成为上下文管理者
	if(selinux_enabled>0)
		if(sehandle==null)
			abort()无法获取
		if(getcon(&service_manager_context)!=0)
			abort()无法获取service_manager上下文
	binder_loop() 进入无限循环,处理client端发来的请求
		binder_write() 将BC_ENTER_LOOPER命令发送给binder驱动,让service manager进入循环
			根据传进来的参数,初始化bwr
			return ioctl() 通过ioctl将bwr数据发送给binder驱动
		ioctl()进入循环,不断地binder读写过程
			binder.get_thread() 获取binder_thread
			binder_ioctl_write_read()
				copy_from_user()把用户空间数据拷贝到bwr
				binder_thread_write() 主要是设置当前线程的looper状态为BINDER_LOOPER_STATE_ENTERED
				copy_to_user()将内核数据bwr拷贝到用户空间
		binder_parse()解析binder信息	
			bio_init()
			bio_init_from_txn()
			func(bs,txn,&msg,&reply);//svcmgr_handler()
				bio_get_string16()服务名
				do_find_service() 根据名称查找相应的服务
					find_svc() 查询相应的服务
						服务存在,返回相应服务名,否则返回null		
					检查服务是否允许孤立于进程而单独存在
					服务是否满足查询条件
				bio_put_ref() 
					if(handle) bio_alloc_obj()
						bio_alloc()
					else bio_alloc()
				bio_get_string16()服务名
				bio_get_ref()
				do_add_service()注册指定服务	
					svc_can_register()权限检查
						check_mac_perms_form_lookup()检查selinux权限是否满足
					find_svc()服务检索
					svcinfo_death()服务已注册时,释放相应的服务	
					binder_acquire()
					binder_link_to death()	
						binder_write()	
			binder_send_reply()
				binder_write() 这个
binder_become_context_manager() 通 知 binder 驱 动 使 其 成 为 守 护 进 程
	return ioctl(bs->fd,BINDER_SET_CONTEXT_MGR,0)通过ioctl,传递BINDER_SET_CONTEXT_MGR指令
		binder_ioctl_set_ctx_mgr()里面调用的这个方法
			binder_new_node()创建service实体
				kzallor给新建的binder_node分配内核空间
				rb_linko_node() 将新建的node对象添加到proc红黑树

四、获取ServiceManager

java 复制代码
defaultServiceManager()
gDefaultServiceManager的创建过程:
	1.ProcessState::self() 获取ProcessState对象(单例),一个进程一个,存在则返回,否则创建
		new ProcessState 实例化ProcessState
		初始化ProcessState
		open_driver()
			open("/dev/binder",o_RDWR);打开/dev/binder设备,建立与内核的Binder驱动的交互通道
	2.getContextObject() 获取BpBinder对象
		getStrongProxyForHandle(0) 获取handle=0的IBinder
			lookupHandleLocked(handle) 查找handle对应的资源项
				根据handle查找对应的handle_entry
				当handle大于mHandleToObject的Vector长度时
					mHandleToObject.insertAt() 则向该Vector添加(handle+1-N)个结构体,
				然后再返回handle向对应位置的handle_entry结构体指针
			new BpBinder(handle) 当handle值对应的IBinder不存在或弱引用无效,则创建BpBinder对象()
			针对handle=0特殊情况,通过PING_TRANSACTION来判断是否准备就绪
	3.interface_cast<IServiceManager>() 获取BpServiceManager对象
		INTERFACE::asInterface()
		DECLARE_META_INTERFACE(ServiceManager) 
			声明asInterface(),getInterfaceDesciptor()
		IMPLEMENT_META_INTERDACE(ServiceManager,"android.os.IServiceManager")
		BpServiceManager实例化<-BpInterface<-BpRefBase //BpRefBase的mRemote指向new BpBinder(0)

五、注册服务addService

java 复制代码
media服务注册
main_mediaserver.cpp的main() 入口函数
	sp<ProcessState> proc(ProcessState::self())获得ProcessState实例
		new ProcessState 单例,保证一个进程一个ProcessState对象
			open_driver() 打开Binder驱动
				open("/dev/binder",O_RDWR) 打开/dev/binder设备,建立与内核的Binder驱动的交互通道
				ioctl() 设置binder驱动,能支持的最大线程数
			mmap() 采用内存映射函数,给binder分配一块虚拟地址空间
			close() 没有足够空间分配,关闭驱动
	defaultServiceManager() 获取BpServiceManager对象
	注册多媒体服务
	startThreadPool() 启动Binder线程池
	joinThreadPool() 当前线程加入到线程池
服务注册MediaPlayerService::instantiate()
	addService()注册服务
		Parcelle data ,reply; Parcel数据通道
		data.writeInterfaveToken(IServiceManager::getInterfaceDescriptor()) 写入头信息
		data.writeString16(name) 
		data.writeStrongBinder(service) MediaPlayerService对象
			flatten_binder()
				localBinder()
				finish_flatten_binder()
		remote()->transact() //remote()指向BpBinder对象
	BpBinder::transact	
		IPCThreadState::self()->transact() Binder代理类调用transact(),真正工作还是交给IPCThreadSate进行transact工作
			new IPCThreadState;  初始IPCThreadState
			pthread_key_creat() 创建线程的TLS
	IPC::transact
		errorCheck() 数据检查错误
		writeTransactionData() 传输数据
		waitForResponse() 等待相应
			talkWithDriver() 
				ioctl() 通过ioctl不停读写,跟Binder Driver进行通信
			executeCommand()
Binder Driver		
binder_ioctl_write_read()
	copy_from_user() 将用户空间bwr结构体拷贝到内核空间
	binder_thread_write() 将数据放入目标进程
	binder_thread_read() 读取自己队列的数据
	copy_to_user() 将内核空间bwr结构体拷贝到用户空间
binder_thread_write()
	getUser() 拷贝用户空间的cmd命令
	copy_from_user() 拷贝用户空间的binder_transaction_data
	binder_transaction() 
		binder_get_node() //从binder_proc来根据binder指针ptr指,查询相应的binder_node
		binder_new_node() 服务所在进程 创建binder_node实体
			kzaalloc() 给新创建的binder_node分配内核空间
			rb_link_node() 将新创建的node添加到proc红黑树
		binder_get_ref_for_node() servicemanager进程binder_ref
ServiceManager:
启动ServiceManager,循环在binder_loop()过程,会调用binder_parse()
binder_parse()
	bio_init_from_txn() 从txn解析出binder_io信息
	func() 收到binder事务
	binder_send_reply() 发送reply事件
svcmgr_handler()
	do_add_service() 注册指定服务
		权限检查
		服务检索
binder_rend_reply()
	binder_write() 向Binder驱动通信

六、获取服务getService()

java 复制代码
getMediaPlayService()
	defaultServiceManager() 获取驱动Service
	getService("media.player") 获取名为"media.player"的服务
		checkService() 检索服务,存在即返回,否则sleep(1)再检索,循环5次
			data.writeInterfaceToken()写入RPC头
			data.writeString16()写入服务名
			remote()->transact() remote()为BpBinder
				IPCThreadState::self()->transact() 真正工作交给IPCThreadState来进行transact
					errorCheck() 数据错误检查
					writeTransactionData() 数据传输
					waitForResponse() 等待响应
						talkWithDriver() 
							ioctl() 通过ioctl不停的读写操作,跟Binder Driver进行通信
							binder_transaction()
							binder_thread_read()
			readStrongBinder() 功能:flat_binder_object解析并创建BpBinder对象
				unflatten_binder()
					reinterpret_cast() 当请求服务的进程和服务属于同一进程
					getStrongProxyForHandle() 请求服务的进程与服务属于不同进程
						lookupHandleLocked() 查找handle对应的资源项

	linkToDeath() 将死亡通知连接到binder

七、Framework层分析

java 复制代码
1.初始化
AndroidRuntime::startReg() //完成jni方法的注册
	register_jni_procs(gRegJNI, NELEM(gRegJNI),env) //注册jni(), gRegJNI是数组,记录所有需要注册的jni(),比如REG_JNI(register_android_os_Binder)
register_android_os_Binder()
	int_register_android_os_Binder() //注册Binder类的jni()
		gBinderOffsets //是全局静态结构体,保存了类本身及成员方法,execTransat(),mObject属性。
		gBinderMethodsOrDie //将gBinderMethods数组完成映射关系,从而为Java层访问JNI层提供通道
	int_register_android_os_BinderInternal() //注册BinderInternal类的jni()
		gBinderInternalOffsetd() //保存了BinderInternal的forceBinderIGc()
	int_register_android_os_BinderProxy() //注册BinderProxy类的jni()
		gBinderProxyOffsets //保存了BinderProxy的构造方法,sendDeayhNotice(),mObject,mySelf,mOrgue
2.注册服务(有点乱)
ServiceManager.addService()
	getIServiceManager() //先获取SMP对象,则执行注册服务操作
		getContextObject() //等价于new BinderProxy()
			getContextObject() //等价于new BpBinder(0)
			javaObjectForIBinder() //创建BinderProxy对象,并存到BinderProxy.mObject成员变量            
ServiceManagerNative.asInterface()
	new ServiceManagerProxy() //SMP初始化
ServiceManagerProxy.addService()
	writeStrongBinder()
		nativewriteStrongBinder()//此处为native调用
			android_os_Parcel_writeStrongBinder()
				reinterpret_cast() //将Java层Parcel转换为native
				ibinderForJavaObject() //创建JavaBBinderHolder对象,并把地址保存到Binder.mObject成员变量
					JavaBBinderHolder.get()
						new JavaBinder() //首次进来,创建JavaBBinder对象
	mRemote.transact()	
BinderProxy.transact
	checkParcel() //用于检测Parcel大小
	transactNative()
		 //最终交由Native层的BpBinder::transact()完成	
3.获取服务
ServiceManager.getService()
	sCache.get() //先从缓存中查看
	getIServiceManager().getService() //getIServiceManager()等价于ServiceManagerProxy(new BinderProxy())
		ServiceManagerProxy.getService()
			mRemote.transact() //mRemote为BinderProxy:
				android_os_BinderProxy_transact()
					parcelForJavaObject() //Java Parcel转为native parcel
					gBinderProxyOffsets.mObject()// 保存的是new BpBinder(0)对象
					transact() //此处便是BpBinder::transact(),经过native层
						IPCThreadState::transact()
							errorCheck() //数据错误检查
							writeTransactionData() //传输数据
							waitForResponse() //等待回应事件
								//当reply对象回收时,则会调用freeBuffer来回收内存。
								//reply来源:binder_send_reply
			reply.readStrongBinder() //从reply里面解析出获取的IBinder对象,基本是writeStrongBinder逆过程
				readStrongBinder()
					unflatten_binder()
						getStrongProxyForHandle()
							lookupHandleLocked()//查找handle对应的资源项
							new BpBinder() //当handle值所对应的IBinder不存在或弱引用无效,则创建BpBinder对象
相关推荐
千里马学框架3 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台3 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone3 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc3 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo4 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077004 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼4 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone4 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen4 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone4 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui