系列文章目录
目录
2.1.1 ProcessState::ProcessState
2.1.6 设置binder最大线程数binder_ioctl
2.1.8 binder_update_page_range
2.2.2 ProcessState::getContextObject
2.2.3 ProcessState::getStrongProxyForHandle
2.2.4 ProcessState::lookupHandleLocked
2.2.8 IPCThreadState::IPCThreadState
2.2.9 IPCThreadState::incWeakHandle
2.2.13 BpServiceManager::BpServiceManager
2.2.14 BpInterface::BpInterface
2.3.1 MediaPlayerService::instantiate
2.3.2 IServiceManager::addService
2.3.6 IPCThreadState::transact
2.3.7 IPCThreadState::writeTransactionData
2.3.8 IPCThreadState::waitForResponse向驱动发送请求add服务的消息
2.3.9 IPCThreadState::talkWithDriver
2.3.11 binder_thread_write(增加SM对应的句柄0的引用计数)
2.3.12 binder_thread_write(处理media服务请求add的消息)
2.4.3 IPCThreadState::talkWithDriver
2.4.4 IPCThreadState::waitForResponse
2.4.5 talkWithDriver第三次循环(同步消息才会有):
2.6 Servicemanager服务发送reply消息给meidaservice
2.7 servicemanager处理未完成事务,并再次陷休眠
2.8 唤醒meidaservice服务,meida服务处理reply消息
2.8.5 Parcel::ipcSetDataReference
2.9 ProcessState::startThreadPool
2.9.1 ProcessState::spawnPooledThread
2.9.3 IPCThreadState::joinThreadPool
2.9.4 IPCThreadState::getAndExecuteCommand
2.9.5 IPCThreadState::talkWithDriver
2.10.1 IPCThreadState::joinThreadPool
2.10.2 IPCThreadState::getAndExecuteCommand
2.10.3 IPCThreadState::talkWithDriver
1.简介
此篇我们便从源码的角度来看注册服务的过程,此篇以MediaPlayerService注册进入到servicemanager中为例子。
1.1 时序图

(为了保证流程的完整性,较为模糊,可保存到本地,放大仔细观看)
1.1流程介绍
此处举例为MediaPlayerService注册进入到servicemanager中。
第一步:首先mediaservice会获取ProcessState实例对象,此ProcessState对象会打开binder驱动,驱动中会创建meidaservice服务对应的porc进程信息对象。同时meidaservice作为服务,会申请一块内存,通过mmap的进行内存映射,将meidaservice服务的用户空间映射到驱动中,从而会减少数据的拷贝。
第二步:获取BpServiceManager对象,即通过handle0获取ServiceManager的binder代理对象,用于和servicemanager对象通信。
第三步:初始化MediaPlayerService服务,内部首先会创建MediaPlayerService对象,此对象是一个BnMediaPlayerService(binder实体对象),然后调用BpServiceManager代理对象的addservice将此服务注册到中。
第四步:在BpServiceManager代理对象的addservice函数中,会构建Parcel对象,并将meidapalyservice服务的binder实体对象,服务名称,等信息写入Parcel对象中。然后调用bpbinder的通信接口transact函数。
第五步:然后transact函数会将数据再次进行封装,然后调用ioctl函数向驱动发送请求add服务的消息,此时进入内核态。
第六步:ioctl函数对应驱动的binder_ioctl函数,驱动会先将mediapalyservice服务的用户空间的数据拷贝到内核空间,并取出add的标志,处理add服务的消息。然后会走到binder_transaction中。
第七步:binder_transaction函数中首先会找到目标的进程的proc对象和目标进程的线程,然后取出meidapalyservice服务塞入Parcel对象中binder实体对象,并在驱动中创建meidapalyservice服务对应的bbbinder实体,并将此bbbinder实体添加到meidiaplayservice服务的比红黑树中,然后在目标进程(SM进程)的binder_proc中创建对应的binder_ref红黑树节点,将mediaservice的引用添加到SM进程的引用的红黑树中。然后在sm之前映射的进程中分配一块内核buffer空间,将add添加服务的消息数据放入sm进程的缓冲区中。然后将此add服务的消息添加到sm进程的todo队列中。然后唤醒目标进程(SM进程的队列)队列。同时也会生成一个完成的事务消息放入到meidaplayservice的进程队列中。
第八步:meidaplayservice服务作为客户端,会陷入休眠,等待服务端返回reply消息。
第九步:我们知道SM启动后,在向驱动成为binder的管理者后,就会循环从驱动中读取数据,由于驱动无数据,所以会陷入休眠状态等待在todo队列上。在第七步我们已经唤醒了sm进程。此时sm进程会从队列中读取到消息。然后处理add服务的消息。
第十步:sm将meidaplayservice服务的hanle和服务名称保存到svclist,完成注册。然后sm向驱动发送回复消息。同样也是通过binder_transaction函数去找到meidaplayservice服务的porc对象,并向meida服务的todo队列中插入回复消息,并唤醒mediaservice服务。并且往自己的队列中插入未完成事务。然后sm处理完后,再次陷入等待,等待来自驱动的消息。
第十一步:meidaplayservice服务处理reply消息。
第十二步:mediaplayservice服务创建一个新的线程加入binder线程池中,并向驱动发送要进入线程循环的指令,
然后此新线程进入死循环,用于读取来自驱动的消息,如果没有消息,则会休眠阻塞。
第十三步:mediaplayservice服务主线程也加入binder线程池中,也会进入死循环,用于读取来自驱动的消息,如果没有消息,则会休眠阻塞。用于不让主服务退出。
2 meidaservice的启动——源码分析
此例子以meidaservice注册到servcicemanager为例。
//此函数的作用是:驱动多媒体服务,并注册到serivcemanager中
int main(int argc __unused, char **argv __unused)
{
signal(SIGPIPE, SIG_IGN);
sp<ProcessState> proc(ProcessState::self()); //获得ProcessState实例对象
sp<IServiceManager> sm(defaultServiceManager()); //获取BpServiceManager对象
ALOGI("ServiceManager: %p", sm.get());
AIcu_initializeIcuOrDie();
MediaPlayerService::instantiate(); //注册多媒体服务
ResourceManagerService::instantiate();
registerExtensions();
ProcessState::self()->startThreadPool(); //启动Binder线程池
IPCThreadState::self()->joinThreadPool(); //当前线程加入到线程池
}
注意:startThreadPool,本质上是创建了一个新的线程,并向binder驱动注册为主线程。然后一直循环。joinThreadPool是将当前线程加入到binder主线程。此时有两个binder主线程。
2.1 获取ProcessState对象
2.1.1 ProcessState::ProcessState
1.此处是单例模式。在一个进程中,只会创建一次。ProcessState作为进程状态的记录器,主要用来打开Binder驱动获取句柄,mmap申请一块(1M-8K)的内存空间,设置Binder线程最大个数。
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != nullptr) {
return gProcess;
}
gProcess = new ProcessState(kDefaultDriver);//sp<ProcessState> gProcess;
//根据VNDK的宏定义来决定当前进程使用"/dev/binder" 还是"/dev/vndbinder"kDefaultDriver此时值是= "/dev/binder";
return gProcess;
}
2.1.2 ProcessState::init
1.创建了ProcessState对象。此对象用于打开binder驱动,并完成内存的映射,将用户空间的一块内存映射到内核空间,映射关系建立后,用户对这块内存区域的修改可直接反映到内核空间,反之内核空间对其修改也能反映到用户空间。
ProcessState::ProcessState(const char *driver)
: mDriverName(String8(driver))//driver是/dev/binder
, mDriverFD(open_driver(driver))//打开binder驱动返回的fd文件描述符
, mVMStart(MAP_FAILED)
, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)//保护线程数量的锁,pthread_mutex_t mThreadCountLock;
, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)//条件变量。pthread_cond_t mThreadCountDecrement;
, mExecutingThreadsCount(0)//当前执行命令的binder线程数
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)//最大线程数15
, mStarvationStartTimeMs(0)//线程池被清空的时间
, mManagesContexts(false)
, mBinderContextCheckFunc(nullptr)
, mBinderContextUserData(nullptr)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
, mCallRestriction(CallRestriction::NONE)//无呼叫限制
{
if (mDriverFD >= 0) {
//mmap binder,内存映射。128k的内存地址,申请128k的内存地址用来接收事务,对应binder驱动的binder_mmap函数。
//启动分析中有,故不再分析
mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
/**
if (mVMStart == MAP_FAILED) {//如果内存映射失败
// *sigh*
ALOGE("Using %s failed: unable to mmap transaction memory.\n", mDriverName.c_str());
close(mDriverFD);
mDriverFD = -1;
mDriverName.clear();
}
*/
}
LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating.");
}
2.1.3 open_driver
主要作用为:
1.open打开binder驱动,通过系统调用_open,最后会调用到binder_open,陷入内核态。获取fd。
2.通过ioctl,获取binder驱动版本号,用vers保存。然后对比版本号是否一致。
3.通过ioctl设置binder驱动最大线程数。
static int open_driver(const char *driver)
{
int fd = open(driver, O_RDWR | O_CLOEXEC);//driver值是/dev/binder,打开binder驱动,陷入内核,此
//open对应_open,然后对应binder驱动层的binder_open,binder_open中主要是为/dev/binder这个驱动设备节点,创建
//对应的proc对象,然后通过fd返回。这样就可以和驱动进行通信。
if (fd >= 0) {//大于0代表打开成功
int vers = 0;
status_t result = ioctl(fd, BINDER_VERSION, &vers);//获取binder驱动的版本信息,用vers保存
/**正常不执行
if (result == -1) {//如果获取信息失败,则关闭binder驱动
ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
close(fd);
fd = -1;
}
*/
/**
if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {//如果获取的版本信息不匹配,则关闭binder驱动
ALOGE("Binder driver protocol(%d) does not match user space protocol(%d)! ioctl() return value: %d",
vers, BINDER_CURRENT_PROTOCOL_VERSION, result);
close(fd);
fd = -1;
}
*/
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;//设置最大线程数15
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);//设置binder驱动最大线程数
/**
if (result == -1) {
ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
}
*/
uint32_t enable = DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION;//DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION值是1,表示默认启用更新垃圾检测
result = ioctl(fd, BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enable);//设置到binder驱动中
/**
if (result == -1) {
ALOGD("Binder ioctl to enable oneway spam detection failed: %s", strerror(errno));
}
*/
}
/**
else {
ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno));
}
*/
return fd;
}
2.1.4 binder_open
1.为当前sm服务进程分配保存binder_proc的对象。binder_proc结构体保存的是sm服务的进程的信息。
2.对sm服务的binder_proc的对象进行初始化,如初始化todo队列,设置进程优先级等。
3.将sm服务的binder_proc添加到binder_procs队列中,驱动有一个全局的binder_procss的列表,用于存储所有进程的binder_proc对象。
//主要作用:binder驱动为用户进程创建了用户进程自己的binder——proc实体
static int binder_open(struct inode *nodp, struct file *filp)
{
struct binder_proc *proc;//proc表示驱动中binder进程
proc = kzalloc(sizeof(*proc), GFP_KERNEL);//为binder_proc结构体在分配kernel内存空间
if (proc == NULL)
return -ENOMEM;
//下面是对binder_proc进行初始化,binder_proc用于管理数据的记录体
get_task_struct(current);
proc->tsk = current;//current代表当前线程。当前线程此时是servicemanager的主线程,当前线程的task保存在binder进程的tsk
INIT_LIST_HEAD(&proc->todo);//初始化to列表
init_waitqueue_head(&proc->wait);//初始化wait列表
proc->default_priority = task_nice(current);//当前进程的nice值转化为进程优先级
binder_lock(__func__);
binder_stats_created(BINDER_STAT_PROC);//BINDER_PROC对象创建+1
hlist_add_head(&proc->proc_node, &binder_procs);//将proc_node节点添加到binder_procs为表头的队列
proc->pid = current->group_leader->pid;
INIT_LIST_HEAD(&proc->delivered_death);
filp->private_data = proc;//将 proc 保存到filp中,这样下次可以通过filp找到此proc
binder_unlock(__func__);
if (binder_debugfs_dir_entry_proc) {
char strbuf[11];
snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
proc->debugfs_entry = debugfs_create_file(strbuf, S_IRUGO,
binder_debugfs_dir_entry_proc, proc, &binder_proc_fops);
}
return 0;
}
//进程相关的参数
struct binder_proc {
struct hlist_node proc_node;//hlist_node表示哈希表中的一个节点。哈希表中的一个节点,用于标记该进程
struct rb_root threads;// rb_root表示红黑树。Binder线程池每一个Binder进程都有一个线程池,
//由Binder驱动来维护,Binder线程池中所有线程由一个红黑树来组织,RB树以线程ID为关键字 */
//上述红黑树的根节点
struct rb_root nodes;// 一系列Binder实体对象(binder_node)和Binder引用对象(binder_ref) */
//在用户空间:运行在Server端称为Binder本地对象,运行在Client端称为Binder代理对象*/
//在内核空间:Binder实体对象用来描述Binder本地对象,Binder引用对象来描述Binder代理对象 */
//Binder实体对象列表(RB树),关键字 ptr
struct rb_root refs_by_desc;//记录binder引用, 便于快速查找,binder_ref红黑树的根节点(以handle为key),它是Client在Binder驱动中的体现。
//Binder引用对象,关键字 desc
struct rb_root refs_by_node;//记录binder引用, 便于快速查找,binder_ref红黑树的根节点(以ptr为key),它是Client在Binder驱动中的体现,
//Binder引用对象,关键字 node
struct list_head waiting_threads;
int pid;//进程组pid
struct task_struct *tsk;//任务控制模块
const struct cred *cred;
struct hlist_node deferred_work_node;
int deferred_work;
bool is_dead;
struct list_head todo;//待处理队列,进程每接收到一个通信请求,Binder将其封装成一个工作项,保存在待处理队列to_do中 */
struct binder_stats stats;
struct list_head delivered_death;
int max_threads;// Binder驱动程序最多可以请求进程注册线程的最大数量,
//进程可以调用ioctl注册线程到Binder驱动程序中,当线程池中没有足够空闲线程来处理事务时,Binder驱动可以主动要求进程注册更多的线程到Binder线程池中 */
// Binder驱动程序最多可以请求进程注册线程的最大数量
int requested_threads;
int requested_threads_started;
int tmp_ref;
long default_priority;
struct dentry *debugfs_entry;
struct binder_alloc alloc;
struct binder_context *context;//存储binder_node和binder_context_mgr_uid以及name
spinlock_t inner_lock;
spinlock_t outer_lock;
struct dentry *binderfs_entry;
};
2.1.5 获取版本号binder_ioctl
主要作用为:
1.此时用于获取版本号。
//获取binder版本号分析
static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
int ret;
struct binder_proc *proc = filp->private_data;
struct binder_thread *thread;//binder线程
unsigned int size = _IOC_SIZE(cmd);
void __user *ubuf = (void __user *)arg;
trace_binder_ioctl(cmd, arg);
ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);//binder_stop_on_user_error值是0,
//binder_stop_on_user_error < 2为假时,休眠,故此处不休眠
if (ret)
goto err_unlocked;
binder_lock(__func__);
thread = binder_get_thread(proc);//获取当前sm的proc实体对象的binder_thread
if (thread == NULL) {
ret = -ENOMEM;
goto err;
}
switch (cmd) {
case BINDER_VERSION://获取版本号
if (size != sizeof(struct binder_version)) {
ret = -EINVAL;
goto err;
}
if (put_user(BINDER_CURRENT_PROTOCOL_VERSION, &((struct binder_version *)ubuf)->protocol_version)) {
//将驱动程序的BINDER_CURRENT_PROTOCOL_VERSION变量地址,拷贝sizeof(*ptr)的ubuf用户空间地址。
//分析,此处是有一次拷贝的。
ret = -EINVAL;
goto err;
}
break;
default:
ret = -EINVAL;
goto err;
}
ret = 0;
err:
if (thread)
thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN;
binder_unlock(__func__);
wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);//不休眠
if (ret && ret != -ERESTARTSYS)
printk(KERN_INFO "binder: %d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
err_unlocked:
trace_binder_ioctl_done(ret);
return ret;
}
2.1.6 设置binder最大线程数binder_ioctl
//设置binder最大线程数分析
//ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);maxThreads值为15
static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
int ret;
struct binder_proc *proc = filp->private_data;
struct binder_thread *thread;//binder线程
unsigned int size = _IOC_SIZE(cmd);
void __user *ubuf = (void __user *)arg;//ubuf是15的地址
trace_binder_ioctl(cmd, arg);
ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);//不休眠
if (ret)
goto err_unlocked;
binder_lock(__func__);
thread = binder_get_thread(proc);//获取当前sm的proc实体的binder_thread
if (thread == NULL) {
ret = -ENOMEM;
goto err;
}
switch (cmd) {
case BINDER_SET_MAX_THREADS://设置binder最大线程数量
if (copy_from_user(&proc->max_threads, ubuf, sizeof(proc->max_threads))) {//拷贝用户空间的地址到内核空间
ret = -EINVAL;
goto err;
}
break;
ret = 0;
err:
if (thread)
thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN;
binder_unlock(__func__);
wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
if (ret && ret != -ERESTARTSYS)
printk(KERN_INFO "binder: %d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
err_unlocked:
trace_binder_ioctl_done(ret);
return ret;
}
2.1.7 binder_mmap
主要作用为:
1.get_vm_area分配一个连续的内核虚拟空间,与用户进程虚拟空间大小一致。
2.binder_update_page_range,分配物理页面,同时映射到内核空间和用户进程空间。
即,此时servermanager服务在其内部分配了一块地址映射进入了内核空间。减少了拷贝。
//filp对应fp,vma代表用户地址空间
static int binder_mmap(struct file *filp, struct vm_area_struct *vma)//vma描述了应用程序使用的用户虚拟空间
{
int ret;
struct vm_struct *area;//内核虚拟空间
struct binder_proc *proc = filp->private_data;//取出sm进程对应的binder_proc对象
const char *failure_string;
struct binder_buffer *buffer;//用于binder传输数据的缓冲区
if ((vma->vm_end - vma->vm_start) > SZ_4M)//保证映射内存大小不超过4M
vma->vm_end = vma->vm_start + SZ_4M;
if (vma->vm_flags & FORBIDDEN_MMAP_FLAGS) {//判断是否禁止mmap
ret = -EPERM;
failure_string = "bad vm_flags";
goto err_bad_arg;
}
vma->vm_flags = (vma->vm_flags | VM_DONTCOPY) & ~VM_MAYWRITE;
mutex_lock(&binder_mmap_lock);
if (proc->buffer) {//如果buffer不为空,则代表已经mmap过了
ret = -EBUSY;
failure_string = "already mapped";
goto err_already_mapped;
}
area = get_vm_area(vma->vm_end - vma->vm_start, VM_IOREMAP);//分配一个连续的内核虚拟空间,与用户进程虚拟空间大小一致
if (area == NULL) {
ret = -ENOMEM;
failure_string = "get_vm_area";
goto err_get_vm_area_failed;
}
proc->buffer = area->addr;//binder_proc对象的buffer指向内核虚拟空间的地址
proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer;//计算偏移量,地址偏移量=用户空间地址-内核空间地址
mutex_unlock(&binder_mmap_lock);
proc->pages = kzalloc(sizeof(proc->pages[0]) * ((vma->vm_end - vma->vm_start) / PAGE_SIZE), GFP_KERNEL);//分配
//分配物理页的指针数组,大小等于用户虚拟内存/4K,此数组用于指示binder申请的物理页的状态
if (proc->pages == NULL) {
ret = -ENOMEM;
failure_string = "alloc page array";
goto err_alloc_pages_failed;
}
proc->buffer_size = vma->vm_end - vma->vm_start;//计算大小
vma->vm_ops = &binder_vm_ops;
vma->vm_private_data = proc;
if (binder_update_page_range(proc, 1, proc->buffer, proc->buffer + PAGE_SIZE, vma)) {//分配物理页面,同时映射到内核空间和进程空间,
//目前只分配1个page的物理页
ret = -ENOMEM;
failure_string = "alloc small buf";
goto err_alloc_small_buf_failed;
}
buffer = proc->buffer;//binder_buffer对象,指向proc的buffer地址,proc的buffer地址又指向内核虚拟空间的地址
INIT_LIST_HEAD(&proc->buffers);
list_add(&buffer->entry, &proc->buffers);//将内核虚拟空间的地址加入到所属进程的buffer队列
buffer->free = 1;
binder_insert_free_buffer(proc, buffer);//将空闲的buffer放入proc->free_buffer中
proc->free_async_space = proc->buffer_size / 2;
barrier();
proc->files = get_files_struct(proc->tsk);
proc->vma = vma;//binder_proc对象保存了用户空间的地址
proc->vma_vm_mm = vma->vm_mm;
/*printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p\n",
proc->pid, vma->vm_start, vma->vm_end, proc->buffer);*/
return 0;
////错误跳转
err_alloc_small_buf_failed:
kfree(proc->pages);
proc->pages = NULL;
err_alloc_pages_failed:
mutex_lock(&binder_mmap_lock);
vfree(proc->buffer);
proc->buffer = NULL;
err_get_vm_area_failed:
err_already_mapped:
mutex_unlock(&binder_mmap_lock);
err_bad_arg:
printk(KERN_ERR "binder_mmap: %d %lx-%lx %s failed %d\n",
proc->pid, vma->vm_start, vma->vm_end, failure_string, ret);
return ret;
}
2.1.8 binder_update_page_range
主要作用为:
1.分配物理内存空间。
2.将物理空间映射到内核空间。
3.将物理空间映射到用户进程空间。
当然binder_update_page_range 既可以分配物理页面,也可以释放物理页面。
//binder_update_page_range 主要完成工作:分配物理内存空间,将物理空间映射到内核空间,将物理空间映射到进程空间。
//当然binder_update_page_range 既可以分配物理页面,也可以释放物理页面
static int binder_update_page_range(struct binder_proc *proc, int allocate,
void *start, void *end,
struct vm_area_struct *vma)
//参数说明:
//proc对应的进程的proc对象
//allocate表示是申请还是释放
//start,表示内核虚拟空间起始地址
//end,内核虚拟空间末尾地址
//用户空间地址
{
void *page_addr;
unsigned long user_page_addr;
struct vm_struct tmp_area;
struct page **page;
struct mm_struct *mm;
if (end <= start)
return 0;
trace_binder_update_page_range(proc, allocate, start, end);
if (vma)
mm = NULL;
else
mm = get_task_mm(proc->tsk);
if (mm) {
down_write(&mm->mmap_sem);
vma = proc->vma;
if (vma && mm != proc->vma_vm_mm) {
pr_err("binder: %d: vma mm and task mm mismatch\n",
proc->pid);
vma = NULL;
}
}
if (allocate == 0)
goto free_range;
if (vma == NULL) {
printk(KERN_ERR "binder: %d: binder_alloc_buf failed to "
"map pages in userspace, no vma\n", proc->pid);
goto err_no_vma;
}
//前面都在判断参数是否合法
//
for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) {
int ret;
struct page **page_array_ptr;
page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];
BUG_ON(*page);
//分配物理内存
*page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO);
if (*page == NULL) {
printk(KERN_ERR "binder: %d: binder_alloc_buf failed "
"for page at %p\n", proc->pid, page_addr);
goto err_alloc_page_failed;
}
tmp_area.addr = page_addr;//tmp_area是内核地址,此时指向物理地址
tmp_area.size = PAGE_SIZE + PAGE_SIZE /* guard page? */;
page_array_ptr = page;
ret = map_vm_area(&tmp_area, PAGE_KERNEL, &page_array_ptr);//映射物理页地址到内核地址tmp_area
if (ret) {
printk(KERN_ERR "binder: %d: binder_alloc_buf failed "
"to map page at %p in kernel\n",
proc->pid, page_addr);
goto err_map_kernel_failed;
}
user_page_addr =
(uintptr_t)page_addr + proc->user_buffer_offset;
ret = vm_insert_page(vma, user_page_addr, page[0]);//映射物理页地址到虚拟用户地址空间vma
if (ret) {
printk(KERN_ERR "binder: %d: binder_alloc_buf failed "
"to map page at %lx in userspace\n",
proc->pid, user_page_addr);
goto err_vm_insert_page_failed;
}
/* vm_insert_page does not seem to increment the refcount */
}
if (mm) {
up_write(&mm->mmap_sem);
mmput(mm);
}
return 0;
free_range:
for (page_addr = end - PAGE_SIZE; page_addr >= start;
page_addr -= PAGE_SIZE) {
page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];
if (vma)
zap_page_range(vma, (uintptr_t)page_addr +
proc->user_buffer_offset, PAGE_SIZE, NULL);
err_vm_insert_page_failed:
unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE);
err_map_kernel_failed:
__free_page(*page);
*page = NULL;
err_alloc_page_failed:
;
}
err_no_vma:
if (mm) {
up_write(&mm->mmap_sem);
mmput(mm);
}
return -ENOMEM;
}
2.2 获取bpServiceManager对象
2.2.1 defaultServiceManager
1.此处最重要的是gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(nullptr));
因此我们需要查看getContextObject和interface_cast的作用。
可以提前说一下,最终sm是bpServiceManager对象。我们看一下是如何分析的。
sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager != nullptr) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
while (gDefaultServiceManager == nullptr) {
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(nullptr));
if (gDefaultServiceManager == nullptr)
sleep(1);//当ServiceManager还未准备好,等待1秒后重新获取ServiceManager对象
}
}
return gDefaultServiceManager;//gDefaultServiceManager是一个bpServiceManager
}
2.2.2 ProcessState::getContextObject
1.最终获取了servicemanager的句柄对应的BpBinder对象。
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
return getStrongProxyForHandle(0);//0就是servicemanager的句柄
}
2.2.3 ProcessState::getStrongProxyForHandle
1.创建了一个handle为0的BpBinder,即SM的bpbinder
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)//传入的是0,代表serviceManager的句柄
{
sp<IBinder> result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);//查找SM的handle对应的资源项。
if (e != nullptr) {
IBinder* b = e->binder;//此时b为空
if (b == nullptr || !e->refs->attemptIncWeak(this)) {
if (handle == 0) {
//执行一个伪事务以确保上下文管理器已注册。通过ping操作测试binder是否准备就绪
Parcel data;
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, nullptr, 0);
if (status == DEAD_OBJECT)
return nullptr;
}
b = BpBinder::create(handle);//创建了一个handle为0的BpBinder,即SM的bpbinder
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;//返回一个handle为0的BpBinder
}
2.2.4 ProcessState::lookupHandleLocked
ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)//此时值是0,0代表sm的binder代理对象的句柄
{
const size_t N=mHandleToObject.size();//第一次N=0
if (N <= (size_t)handle) {
handle_entry e;
e.binder = nullptr;
e.refs = nullptr;
status_t err = mHandleToObject.insertAt(e, N, handle+1-N);//mHandleToObject是保存handle_entry的容器
if (err < NO_ERROR) return nullptr;
}
return &mHandleToObject.editItemAt(handle);//返回了一个空的handle_entry
}
2.2.5 BpBinder::create
1.创建了SM对应的BpBinder对象。
BpBinder* BpBinder::create(int32_t handle) {
int32_t trackedUid = -1;
//sCountByUidEnabled默认是false
/**
if (sCountByUidEnabled) {
trackedUid = IPCThreadState::self()->getCallingUid();
AutoMutex _l(sTrackingLock);
uint32_t trackedValue = sTrackingMap[trackedUid];
if (CC_UNLIKELY(trackedValue & LIMIT_REACHED_MASK)) {
if (sBinderProxyThrottleCreate) {
return nullptr;
}
} else {
if ((trackedValue & COUNTING_VALUE_MASK) >= sBinderProxyCountHighWatermark) {
ALOGE("Too many binder proxy objects sent to uid %d from uid %d (%d proxies held)",
getuid(), trackedUid, trackedValue);
sTrackingMap[trackedUid] |= LIMIT_REACHED_MASK;
if (sLimitCallback) sLimitCallback(trackedUid);
if (sBinderProxyThrottleCreate) {
ALOGI("Throttling binder proxy creates from uid %d in uid %d until binder proxy"
" count drops below %d",
trackedUid, getuid(), sBinderProxyCountLowWatermark);
return nullptr;
}
}
}
sTrackingMap[trackedUid]++;
}
*/
return new BpBinder(handle, trackedUid);//创建了BpBinder对象
}
2.2.6 BpBinder::BpBinder
BpBinder::BpBinder(int32_t handle, int32_t trackedUid)//此时handle=0,trackedUid是-1
: mHandle(handle)//是0,代表SM的Bpbinder的句柄
, mAlive(1)
, mObitsSent(0)
, mObituaries(nullptr)
, mTrackedUid(trackedUid)
{
ALOGV("Creating BpBinder %p handle %d\n", this, mHandle);
extendObjectLifetime(OBJECT_LIFETIME_WEAK);//扩展生命周期为弱引用管理
IPCThreadState::self()->incWeakHandle(handle, this);//增加BPbinder的弱引用计数
}
2.2.7 IPCThreadState::self
IPCThreadState* IPCThreadState::self()
{
/**不执行
if (gHaveTLS.load(std::memory_order_acquire)) {//定义时是false。static std::atomic<bool> gHaveTLS(false);
restart:
const pthread_key_t k = gTLS;
IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
if (st) return st;
return new IPCThreadState;
}
// Racey, heuristic test for simultaneous shutdown.
if (gShutdown.load(std::memory_order_relaxed)) {//定义是false。static std::atomic<bool> gShutdown = false;
ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n");
return nullptr;
}
*/
pthread_mutex_lock(&gTLSMutex);
if (!gHaveTLS.load(std::memory_order_relaxed)) {
int key_create_value = pthread_key_create(&gTLS, threadDestructor);//分配用于表示进程中线程特定数据的键,键对进程中的所有线程来说是全局的.
//pthread_key_create第一个参数为指向一个键值的指针,第二个参数指明了一个destructor函数,
//如果这个参数不为空,那么当每个线程结束时,系统将调用这个函数来释放绑定在这个键上的内存块。
//key_create_value成功返回0,其他是失败
/**
if (key_create_value != 0) {
pthread_mutex_unlock(&gTLSMutex);
ALOGW("IPCThreadState::self() unable to create TLS key, expect a crash: %s\n",
strerror(key_create_value));
return nullptr;
}
*/
gHaveTLS.store(true, std::memory_order_release);//将gHaveTLS值设置为true。static std::atomic<bool> gHaveTLS(false);
}
pthread_mutex_unlock(&gTLSMutex);
goto restart;
}
2.2.8 IPCThreadState::IPCThreadState
IPCThreadState::IPCThreadState()
: mProcess(ProcessState::self()),//保存当前的ProcessState对象
mServingStackPointer(nullptr),
mWorkSource(kUnsetWorkSource),
mPropagateWorkSource(false),
mIsLooper(false),
mIsFlushing(false),
mStrictModePolicy(0),
mLastTransactionBinderFlags(0),
mCallRestriction(mProcess->mCallRestriction) {
pthread_setspecific(gTLS, this);//将自己即IPCThreadState对象存储到gTLS中。
clearCaller();
mIn.setDataCapacity(256);//设置输入缓存区大小
mOut.setDataCapacity(256);//设置输出缓存区大小
}
2.2.9 IPCThreadState::incWeakHandle
void IPCThreadState::incWeakHandle(int32_t handle, BpBinder *proxy)
{
LOG_REMOTEREFS("IPCThreadState::incWeakHandle(%d)\n", handle);
mOut.writeInt32(BC_INCREFS);//向驱动请求增加binder的引用计数
mOut.writeInt32(handle);//此时是0,代表SM的句柄
if (!flushIfNeeded()) {//flushIfNeeded返回值是false,因为当前线程还没有进入循环,故无法贺binder驱动通信。
// Create a temp reference until the driver has handled this command.
proxy->getWeakRefs()->incWeak(mProcess.get());
mPostWriteWeakDerefs.push(proxy->getWeakRefs());
}
}
所以gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(nullptr));
就变成了
gDefaultServiceManager = interface_cast<IServiceManager>(BpBinder(0,trackedUid));
我们接下来继续查看interface_cast的作用。
2.2.10 interface_cast
这个是一个模板类。
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
此时INTERFACE的值是IServiceManager,转换后为:
inline sp<IServiceManager> interface_cast(const sp<IBinder>& obj)
{
return IServiceManager::asInterface(obj);//此时obj是BpBinder(0,trackedUid)
//真正返回的是BpServiceManager(BpBinder(0,trackedUid)) 对象
}
继续查看asInterface的作用。
2.2.11 asInterface
#define DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(INTERFACE, NAME)\
const ::android::String16 I##INTERFACE::descriptor(NAME); \
const ::android::String16& \
I##INTERFACE::getInterfaceDescriptor() const { \
return I##INTERFACE::descriptor; \
} \
::android::sp<I##INTERFACE> I##INTERFACE::asInterface( \
const ::android::sp<::android::IBinder>& obj) \
{ \
::android::sp<I##INTERFACE> intr; \
if (obj != nullptr) { \
intr = static_cast<I##INTERFACE*>( \
obj->queryLocalInterface( \
I##INTERFACE::descriptor).get()); \
if (intr == nullptr) { \
intr = new Bp##INTERFACE(obj); \
} \
} \
return intr; \
}
替换后为:
#define DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager")
const ::android::String16 IServiceManager::descriptor("android.os.IServiceManager");
::android::sp<IServiceManager> IServiceManager::asInterface(
const ::android::sp<::android::IBinder>& obj)
{
::android::sp<IServiceManager> intr;
if (obj != nullptr) {//此时obj是BpBinder(0,trackedUid)
intr = static_cast<IServiceManager*>(
obj->queryLocalInterface(IServiceManager::descriptor).get());//查询"android.os.IServiceManager"对应的本地服务
if (intr == nullptr) {
intr = new BpServiceManager(obj);
}
}
return intr; //返回的是BpServiceManager(BpBinder(0,trackedUid))
}
2.2.12 queryLocalInterface
//此时obj是BpBinder对象,查看其queryLocalInterface方法。
sp<IInterface> IBinder::queryLocalInterface(const String16& /*descriptor*/)
{
return nullptr;//返回为空
}
所以此时
gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(nullptr));
就变成了
gDefaultServiceManager = interface_cast<IServiceManager>(BpBinder(0,trackedUid));
等价于
gDefaultServiceManager =new BpServiceManager(new BpBinder(0,trackedUid));
2.2.13 BpServiceManager::BpServiceManager
explicit BpServiceManager(const sp<IBinder>& impl)//此时impl是BpBinder(0,trackedUid)
: BpInterface<IServiceManager>(impl)
{
}
2.2.14 BpInterface::BpInterface
class BpInterface : public INTERFACE, public BpRefBase
inline BpInterface<IServiceManager>::BpInterface(const sp<IBinder>& remote)//remote是BpBinder(0,trackedUid)
: BpRefBase(remote)
{
}
替换后,等价于
class BpInterface : public IServiceManager, public BpRefBase
inline BpInterface<IServiceManager>::BpInterface(const sp<IBinder>& remote)//remote是BpBinder(0,trackedUid)
: BpRefBase(remote)
{
}
2.2.15 BpRefBase::BpRefBase
BpRefBase::BpRefBase(const sp<IBinder>& o)//o是BpBinder(0,trackedUid)
: mRemote(o.get()), mRefs(nullptr), mState(0)//mRemote就是BpBinder(0,trackedUid)
{
extendObjectLifetime(OBJECT_LIFETIME_WEAK);//扩展对象生命周期为弱周期管理
if (mRemote) {
mRemote->incStrong(this); //增加对象引用计数
mRefs = mRemote->createWeak(this); //持有一个mRemote的弱引用对象
}
}
2.3 注册多媒体服务到servicemanager
2.3.1 MediaPlayerService::instantiate
主要作用为:
1.MediaPlayerService调用Bpservicemanager对象的addService接口。
void MediaPlayerService::instantiate() {
defaultServiceManager()->addService(String16("media.player"), new MediaPlayerService());//BpServiceManager的addService方法
}
2.3.2 IServiceManager::addService
1.生成发送到驱动的数据data和请求恢复的reply。
2.将MediaPlayerService这个binder实体对象,对应的string名称,写入data。
3.通过bpbinder的transact接口将消息发送出去,并等待回复的消息。
[/frameworks/native/libs/binder/IServiceManager.cpp]
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated, int dumpsysPriority) {
//参数:name是"media.player",service是new MediaPlayerService,也是一个BBbinder实体
//allowIsolated是fasle,dumpsysPriority是8,默认优先级
Parcel data, reply;//发送到驱动的data,和请求回复的reply
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());//写入RPC头信息"android.os.IServiceManager"
data.writeString16(name);//写入"media.player"
data.writeStrongBinder(service);//把一个binder实体“打扁”并写入parcel, 服务的实体对象:new MediaPlayerService
data.writeInt32(allowIsolated ? 1 : 0);//写入0
data.writeInt32(dumpsysPriority);//写入8
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);//remote() 函数{ return mRemote; }
//故mRemote是SM对应的BpBinder(0,-1)的transact方法。ADD_SERVICE_TRANSACTION是3
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
status_t Parcel::writeInterfaceToken(const String16& interface)
{
const IPCThreadState* threadState = IPCThreadState::self();//获取IPCThreadState对象
writeInt32(threadState->getStrictModePolicy() | STRICT_MODE_PENALTY_GATHER);
updateWorkSourceRequestHeaderPosition();
writeInt32(threadState->shouldPropagateWorkSource() ?
threadState->getCallingWorkSourceUid() : IPCThreadState::kUnsetWorkSource);
// currently the interface identification token is just its name as a string
return writeString16(interface);//interface是"android.os.IServiceManager"
}
2.3.3 writeStrongBinder
status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
return flatten_binder(ProcessState::self(), val, this);//ProcessState是进程状态,val是new MediaPlayerService,BBinder实体。
//this是Parcel对象data
}
2.3.4 flatten_binder
1.parcel对象内部会有一个buffer,记录着parcel中所有扁平化的数据,有些扁平数据是普通数据,而另一些扁平数据则记录着binder对象。所以parcel中会构造另一个mObjects数组,专门记录那些binder扁平数据所在的位置,
status_t flatten_binder(const sp<ProcessState>& /*proc*/,
const sp<IBinder>& binder, Parcel* out)
{
flat_binder_object obj;
if (IPCThreadState::self()->backgroundSchedulingDisabled()) {
/* minimum priority for all nodes is nice 0 */
obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;
} else {
/* minimum priority for all nodes is MAX_NICE(19) */
obj.flags = 0x13 | FLAT_BINDER_FLAG_ACCEPTS_FDS;
}
if (binder != nullptr) {
BBinder *local = binder->localBinder();//如果是BBinder则返回BBinder,如果是Bpbinder则返回空
/**
if (!local) {//如果是bpbinder,代理
BpBinder *proxy = binder->remoteBinder();//返回Bpbinder
if (proxy == nullptr) {
ALOGE("null proxy");
}
const int32_t handle = proxy ? proxy->handle() : 0;//记录此Binder代理的句柄
obj.hdr.type = BINDER_TYPE_HANDLE;//设置type为binder句柄
obj.binder = 0; /* Don't pass uninitialized stack data to a remote process
obj.handle = handle;//将此binder代理的句柄,放入flat_binder_object中。
obj.cookie = 0;
}
*/
else {//是binder实体
if (local->isRequestingSid()) {
obj.flags |= FLAT_BINDER_FLAG_TXN_SECURITY_CTX;//安全上下文
}
obj.hdr.type = BINDER_TYPE_BINDER;//设置type为binder实体
obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());//存储BBbinder
obj.cookie = reinterpret_cast<uintptr_t>(local);//cookie记录Binder实体的指针
}
}
/**
else {
obj.hdr.type = BINDER_TYPE_BINDER;
obj.binder = 0;
obj.cookie = 0;
}
*/
return finish_flatten_binder(binder, obj, out);//参数binder是new MediaPlayerService的BBbinder实体,obj是扁平的flat_binder_object,out是Parcel对象。
//finish_flatten_binder()函数。这个函数内部会记录下刚刚被扁平化的flat_binder_object在parcel中的位置。
//说得更详细点儿就是,parcel对象内部会有一个buffer,记录着parcel中所有扁平化的数据,
//有些扁平数据是普通数据,而另一些扁平数据则记录着binder对象。
//所以parcel中会构造另一个mObjects数组,专门记录那些binder扁平数据所在的位置,
}
BBinder* BBinder::localBinder()//如果是BBinder则返回BBinder,
{
return this;
}
BBinder* IBinder::localBinder()//如果是Bpbinder则返回空
{
return nullptr;
}
BpBinder* BpBinder::remoteBinder()//返回Bpbinder
{
return this;
}
2.3.5 BpBinder::transact
//transact(ADD_SERVICE_TRANSACTION, data, &reply);
status_t BpBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
//参数分析:
//code是3,也是ADD_SERVICE_TRANSACTION
//data中包含要注册的media服务的名字和media服务的BBinder实体。
//reply为空
//flag是0
{
// Once a binder has died, it will never come back to life.
if (mAlive) {//291行,BpBinder构造函数中是1,表示是否活着
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);
//mHandle是0,代表SMBPbinder的句柄,
//code是code是3,也是ADD_SERVICE_TRANSACTION
//data是data中包含要注册的media服务的名字和media服务的BBinder实体。
//reply为空
//flag是0
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}
return DEAD_OBJECT;
}
2.3.6 IPCThreadState::transact
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
//mHandle是0,代表SMBPbinder的句柄,
//code是code是3,也是ADD_SERVICE_TRANSACTION
//data是data中包含要注册的media服务的名字和media服务的BBinder实体。
//reply为空
//flag是0
{
status_t err;
flags |= TF_ACCEPT_FDS;//TF_ACCEPT_FDS表示允许使用文件描述符进行答复
LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),
(flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");//是否异步回复,此处应该是阻塞的
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, nullptr);//将消息打包成结构体写入mout中
/**
if (err != NO_ERROR) {//如果出错
if (reply) reply->setError(err);
return (mLastError = err);
}
*/
if ((flags & TF_ONE_WAY) == 0) {//如果是同步的。
if (UNLIKELY(mCallRestriction != ProcessState::CallRestriction::NONE)) {
if (mCallRestriction == ProcessState::CallRestriction::ERROR_IF_NOT_ONEWAY) {
ALOGE("Process making non-oneway call but is restricted.");
CallStack::logStack("non-oneway call", CallStack::getCurrent(10).get(),
ANDROID_LOG_ERROR);
} else /* FATAL_IF_NOT_ONEWAY */ {
LOG_ALWAYS_FATAL("Process may not make oneway calls.");
}
}
if (reply) {//reply存在,则waitForResponse
err = waitForResponse(reply);
} else {//如果reply不存在,则构造一个出来
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
} else {
err = waitForResponse(nullptr, nullptr);
}
return err;
}
2.3.7 IPCThreadState::writeTransactionData
1.再对数据封装填充到binder_transaction_data结构体中。
2.将要发送给驱动的数据写入mout中。
status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
//参数分析:
//cmd是BC_TRANSACTION,代表请求运输
//binderFlags是允许使用文件描述符进行答复,值是0X10
//mHandle是0,代表SM 的BPbinder的句柄,
//code是code是3,也是ADD_SERVICE_TRANSACTION
//data是data中包含要注册的media服务的名字和media服务的BBinder实体。
//statusBuffer是空
{
binder_transaction_data tr;//此结构体可查看驱动结构体全代码分析
tr.target.ptr = 0; //不用ptr,因为此时要发送的是SM服务的handle句柄
tr.target.handle = handle;//SM服务的handle句柄0
tr.code = code;//code是3,也是ADD_SERVICE_TRANSACTION
tr.flags = binderFlags;//允许使用文件描述符进行答复,值是0X10
tr.cookie = 0;//实体的cookie才有用
tr.sender_pid = 0;//发送方pid
tr.sender_euid = 0;//发送方uid
const status_t err = data.errorCheck();//检查数据是否有错
if (err == NO_ERROR) {
tr.data_size = data.ipcDataSize();//设置数据的大小
tr.data.ptr.buffer = data.ipcData();//指向数据的首地址
tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t);//ipcObjectsCount函数返回的是mObjectsSize,而mObjects
//存储的是多个扁平的binder对象的位置。是offsets_size的偏移大小
tr.data.ptr.offsets = data.ipcObjects();//指向mObjects数组的首地址。mObjects里面记录了所有binder实体或引用在buffer中的位置。
}
/**
else if (statusBuffer) {
tr.flags |= TF_STATUS_CODE;
*statusBuffer = err;
tr.data_size = sizeof(status_t);
tr.data.ptr.buffer = reinterpret_cast<uintptr_t>(statusBuffer);
tr.offsets_size = 0;
tr.data.ptr.offsets = 0;
} else {
return (mLastError = err);
}
*/
mOut.writeInt32(cmd);//mOut中写入BC_TRANSACTION,注意309行,此时还有一个BC_INCREFS的命令
mOut.write(&tr, sizeof(tr));//写入tr结构体
return NO_ERROR;
}
2.3.8 IPCThreadState::waitForResponse向驱动发送请求add服务的消息
//第一次循环时,向驱动发送请求add服务的消息,mout中有值
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)//acquireResult默认是nullptr
{
uint32_t cmd;
int32_t err;
while (1) {
if ((err=talkWithDriver()) < NO_ERROR) break;//第一次循环时,向驱动发送请求add消息,mout中有值
//后面则是对reply回复消息的处理
err = mIn.errorCheck();
if (err < NO_ERROR) break;
if (mIn.dataAvail() == 0) continue;
cmd = (uint32_t)mIn.readInt32();
IF_LOG_COMMANDS() {
alog << "Processing waitForResponse Command: "
<< getReturnString(cmd) << endl;
}
switch (cmd) {
case BR_TRANSACTION_COMPLETE:
if (!reply && !acquireResult) goto finish;
break;
case BR_DEAD_REPLY:
err = DEAD_OBJECT;
goto finish;
case BR_FAILED_REPLY:
err = FAILED_TRANSACTION;
goto finish;
case BR_ACQUIRE_RESULT:
{
ALOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT");
const int32_t result = mIn.readInt32();
if (!acquireResult) continue;
*acquireResult = result ? NO_ERROR : INVALID_OPERATION;
}
goto finish;
case BR_REPLY:
{
binder_transaction_data tr;
err = mIn.read(&tr, sizeof(tr));
ALOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY");
if (err != NO_ERROR) goto finish;
if (reply) {
if ((tr.flags & TF_STATUS_CODE) == 0) {
reply->ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t),
freeBuffer, this);
} else {
err = *reinterpret_cast<const status_t*>(tr.data.ptr.buffer);
freeBuffer(nullptr,
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), this);
}
} else {
freeBuffer(nullptr,
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), this);
continue;
}
}
goto finish;
default:
err = executeCommand(cmd);
if (err != NO_ERROR) goto finish;
break;
}
}
finish:
if (err != NO_ERROR) {
if (acquireResult) *acquireResult = err;
if (reply) reply->setError(err);
mLastError = err;
}
return err;
}
2.3.9 IPCThreadState::talkWithDriver
status_t IPCThreadState::talkWithDriver(bool doReceive)//doReceive默认是true
{
/**
if (mProcess->mDriverFD < 0) {
return -EBADF;
}
*/
binder_write_read bwr;
//struct binder_write_read {
//binder_size_t write_size;//要写入的字节数,write_buffer的总字节数
//binder_size_t write_consumed;//驱动程序占用的字节数,write_buffer已消费的字节数
//binder_uintptr_t write_buffer;//写缓冲数据的指针
//binder_size_t read_size;//要读的字节数,read_buffer的总字节数
//binder_size_t read_consumed;//驱动程序占用的字节数,read_buffer已消费的字节数
//binder_uintptr_t read_buffer;//读缓存数据的指针
//};
// Is the read buffer empty?
const bool needRead = mIn.dataPosition() >= mIn.dataSize();//此时needRead是ture
//因为mIn.dataPosition返回值和mIn.dataSize相等
//当我们正在从min中读取数据,或者调用方打算读取下一条数据(doReceive为true时),我们不会写入任何内容。
//此时outAvail值等于mOut.dataSize()
const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
bwr.write_size = outAvail;//write_size是mOut.dataSize()
bwr.write_buffer = (uintptr_t)mOut.data();
if (doReceive && needRead) {//当我们需要从驱动中读的时候。
bwr.read_size = mIn.dataCapacity();//设置大小为256字节
bwr.read_buffer = (uintptr_t)mIn.data();
}
/*
else {//当不读的时候,设置读的大小和buffer为0
bwr.read_size = 0;
bwr.read_buffer = 0;
}*/
// 如果读缓冲区和写缓冲区都为0,代表无事可做,立即返回,此时write_size中有数据。
/**
if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;
*/
bwr.write_consumed = 0;
bwr.read_consumed = 0;
status_t err;
do {
#if defined(__ANDROID__)
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)//向binder驱动区写,因为此时是add服务,所以mout有数据
err = NO_ERROR;
else
err = -errno;
#else
err = INVALID_OPERATION;
#endif
/**
if (mProcess->mDriverFD < 0) {
err = -EBADF;
}
*/
} while (err == -EINTR);
if (err >= NO_ERROR) {//代表驱动收到了消息
if (bwr.write_consumed > 0) {
if (bwr.write_consumed < mOut.dataSize())//如果驱动消费的数据大小小于mout的大小,则说明驱动没有消费mout数据
LOG_ALWAYS_FATAL("Driver did not consume write buffer. "
"err: %s consumed: %zu of %zu",

最低0.47元/天 解锁文章
754





