欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 社会 > 进程间通信机制 Binder原理讲解笔记

进程间通信机制 Binder原理讲解笔记

2025/3/31 10:00:04 来源:https://blog.csdn.net/xiaoxiangyuhai/article/details/146297841  浏览:    关键词:进程间通信机制 Binder原理讲解笔记

       为了保证进程空间不被其他进程破坏或千扰,Linux中的进程是相互独立或相互隔离的。进程空间分为用户空间和内核空间。用户空间不可以进行数据交互;内核空间可以进行数据交互,所有进程共用一个内核空间。在这样的设计基础上,进程与进程间进行通信,就需要通过内核空间空间进行桥接,Android从而就形成了跨进程通信的方式:Binder。Android中进行进程间通信主要通过Binder类(已经实现了IBinder接口的类),即具备了跨进程通信的能力。

1 Binder整体简介

在拆解分析Binder之前先上一张Binder架构图,总体对Binder有一个整体了解:

Binder跨进程通信机制:基于C/S架构,由Client、Server、Server Manager和Binder驱动组成。下面的介绍我们主要也是从这几个方面进行分析。一直在说Binder,那么Binder到底是什么东西呢?概括来说Binder:

  • 跨Android进程通信的机制

  • Binder是一个驱动

  • Binder.java实现了IBinder接口从而具备了跨进程的能力

1.1 什么是多进程,多进程的优点

平时自己创建的进程:webVIew  视频播放、音乐、大图浏览、推送等应用。还有系统服务:打电话,闹钟等等。都要用到多进程,接下来直观的感受一下多进程:

上面的图展示了多进程的样子,简单来说就是一个APP可以有多个进程存在,一部手机上可以同时存在多个APP的进程,也是多进程。那在一个APP中为什么要用多进程呢? 

1. 内存:现在手机的内存越来越大比如6G,8G,16G,32G等等, 那一个app(只有一个进程的情况下)在手机上分配的内存(根据版本的不同大小不同):

那这512兆的大小有时候在加载一个大的图片时就会出现崩溃,内存不足,所以有时候一个APP为了获取到更多的内存空间,采用多进程的方式就可以分配到更多的内存空间。

2. 风险隔离:每一个进程都可以认为是一个单独的app,那其中一个app(进程)发生异常,并不会影响到另一个app(进程)。

1.2 Binder有什么优势

Android使用Binder有什么优势没那就需要做一个对比,传统的进程间通信的方式有很多,比如管道、信号量、socket 、共享内存等等。Binder与传统IPC对比:

性能方面:binder性能小于共享内存优于其他IPC

共享内存的特点是使用比较复杂,我们可以对比理解多线程间的内存共享,因为并发问题引起各种数据异常,安全性比较低,需要各种同步操作处理。所以共享内存很难进行万无一失的数据安全的控制。

Binder中每个APP的UID是系统分配的能够进行准确的身份识别,UID作假也无效并且binder中的服务可以是实名和匿名的,当为实名时,通过getService(名字)的方式获取更安全。对于匿名的服务,其他的APP进程更是无法获取的到,这就更增加了安全性。

共享内存或者Socket方式,对身份的校验是通过长层调用者传入的PID,那既然是上层传入的PID那就存在不安全性,可以是随便的一个数值,也无法对这个PID进行一个校验。并且接入点比较的开放,就比如坐公交车,只需要知道坐哪一路公交,只需要到对应的站点等待就可以坐,无需记性身份的验证。

Binder机制相对于Linux内传统的进程间通信方式:

  1. 性能更好;Binder机制只需要拷贝数据一次,管道、消息队列、Socket等都需要拷贝数据两次;而共享内存虽然不需要拷贝,但实现复杂度高。
  2. 安全性更高;Binder机制通过UID/PID在内核空间添加了身份标识,安全性更高。

1.3 Binder的一次拷贝

举个例子进程1 里面有一个类A;进程2里面有一个类B,B类中有一个方法叫test();进程1中的A类型想要调用到进程2中B类的test方法,是不用直接new B().test()的方式的,因为进程间的内存是隔离的。与线程不一样,线程间的内存是共享的。

内存划分


内存被操作系统划分成两块:用户空间和内核空间,用户空间是用户程序代码运行的地方,内核空间是内核代码运行的地方。为了安全,它们是隔离的,即使用户的程序崩溃了,内核也不受影响。

内存被操作系统划分成两块:用户空间和内核空间,用户空间是用户程序代码运行的地方,内核空间是内核代码运行的地方。为了安全,它们是隔离的,即使用户的程序崩溃了,内核也不受影响。

32位系统,即2^32,即总共可访问地址为4G。内核空间为1G,用户空间为3G。

64位系统,低位:0~47位才是有效的可变地址(寻址空间256T),高位:48~63位全补0或全补1。一般高位全补0对应的地址空间是用户空间。高位全补1对应的是内核空间。如下图所示:

2次拷贝

2次拷贝是什么意思,我们来举个例子:

假如说A家现在有一箱苹果,那么B家是不能随便到A家去拿苹果的。这都不用解释哈,因为你家的东西我是不能随便过去拿的,那么怎么办呢?可以通过快递:

A家将苹果打包好,然后拿给快递员(从用户空间进入内核空间,第一次拷贝),快递员经过运输之后,又将苹果转交给了B家(从内核空间又回到用户空间,第二次拷贝)。

经过这个例子就充分说明了,传统的IPC的方式:2次拷贝。用一张图来说明一下具体的2次拷贝的实现:

Binder的1次拷贝

做了半天的铺垫,那么Binder到底是怎么实现1次拷贝的呢?同样还是上面的例子:

这是什么意思呢?就是A家将苹果交给快递员(从用户空间进入内核空间,一次拷贝完成),这一步不可避免的要产生一次拷贝操作,那接下来快递员直接将包裹存放到了一个共享区域中(丰巢柜),然后用户在丰巢柜中将苹果取走(没有了拷贝,共用了一块区域共同放包裹,没有了内存拷贝)。是不是感觉这个柜子有点意思啊~~丰巢柜有个很重要的特点就是快递员可以存放快递,同样的收件方也有权限存放快递到丰巢柜中,这个特点就有点意思了。丰巢柜就相当于一个共享的物理内存,那么用户和快递员就相当于用户空间和内核空间,用户空间和内核空间分别存放着这块物理内存的虚拟地址,这也就是说相当于有那么一块地方,用户和快递员是共享的,都可以访问。这样的骚操作下来,导致Binder就少了一次内存的拷贝操作。来看一下图示:

上面的图示很清楚了,就是用户空间和内核空间共用了一块真实的物理内存,从而减少了一次从内核空间到用户空间的数据的拷贝操作,那是如何实现内核空间与用户空间公用一块物理内存的呢?mmap就闪亮登场了。

mmap()

Linux通过将一个虚拟内存区域与一个磁盘上的对象关联起来,以初始化这个虚拟内存区域的内容,这个过程称为内存映射(memory mapping)。

对文件进行mmap,会在进程的虚拟内存分配地址空间,创建映射关系。实现这样的映射关系后,就可以采用指针的方式读写操作这一段内存,而系统会自动回写到对应的文件磁盘上。

这里牵扯到2个概念,一个是虚拟内存,一个是物理内存,举个例子就可以清晰知道这2个概念了。虚拟内存就是地球仪,物理内存就是地球。

其实到这里也可以解释共享内存为什么不需要拷贝,因为在共享内存的机制里面,接收方、内核、发送方都是用了一块物理内存,这就导致他们数据存储都是在一起的,所以不需要拷贝。但是共享内存就是存在严重的同步问题,所以在管理的时候比较费劲。


到此处有一个问题,就是用户空间可以直接操作文件吗?答案是不可以,也就是说我们应用层所有的对文件的操作,都是通过内核的函数操作实现的。所有的系统资源管理都是在内核空间中完成的。比如读写磁盘文件,分配回收内存,从网络接口读写数据等等。用户空间通过系统调用让内核空间完成这些功能。

写文件流程:

  1. 调用write,告诉内核需要写入数据的开始地址与长度。
  2. 内核将数据拷贝到内核缓存。
  3. 由操作系统调用,将数据拷贝到磁盘,完成写入。

举个简单的例子:

public class MainActivity extends AppCompatActivity {// Used to load the 'native-lib' library on application startup.static {System.loadLibrary("native-lib");}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//写 使用 mmap 映射文件 在内存当中 并操作这块内存 往这块内存中写入一块数据writeTest();readTest();}public native void writeTest();public native void readTest();
}
#include <jni.h>
#include <string>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <android/log.h>int8_t *m_ptr;
int32_t m_size;
int m_fd;extern "C"
JNIEXPORT void JNICALL
Java_com_enjoy_binder_MainActivity_writeTest(JNIEnv *env, jobject thiz) {std::string file = "/sdcard/a.txt";//打开文件m_fd = open(file.c_str(), O_RDWR | O_CREAT, S_IRWXU);//获得一页内存大小//Linux采用了分页来管理内存,即内存的管理中,内存是以页为单位,一般的32位系统一页为 4096个字节m_size = getpagesize();//将文件设置为 m_size这么大ftruncate(m_fd, m_size); // 100  1000 10000// m_size:映射区的长度。 需要是整数页个字节    byte[]m_ptr = (int8_t *) mmap(0, m_size, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd,0);std::string data("刚刚写入的数据");//将 data 的 data.size() 个数据 拷贝到 m_ptr//Java 类似的:
//        byte[] src = new byte[10];
//        byte[] dst = new byte[10];
//        System.arraycopy(src, 0, dst, 0, src.length);memcpy(m_ptr, data.data(), data.size());__android_log_print(ANDROID_LOG_ERROR, "ABC", "写入数据:%s", data.c_str());
}extern "C"
JNIEXPORT void JNICALL
Java_com_enjoy_binder_MainActivity_readTest(JNIEnv *env, jobject thiz) {//申请内存char *buf = static_cast<char *>(malloc(100));memcpy(buf, m_ptr, 100);std::string result(buf);__android_log_print(ANDROID_LOG_ERROR, "abc", "读取数据:%s", result.c_str());//取消映射munmap(m_ptr, m_size);//关闭文件close(m_fd);
}

到此时,Binder的大概的原理就已经分析完了。那么接下来我们根据Binder结构图,我们一部分一部分的拆解分析,首先来分析驱动部分:

那接下来就看一下这一块的实现。

1.4 Binder驱动启动

Binder驱动启动是基础,如果Binder连驱动都没启动,又何来跨进程的通信一说。Binder首先是一个驱动,驱动对于Linux来讲就是文件,在Linux中一切皆文件。Binder是如何启动的呢?先看一下整体:

Binder启动的是misc设备,misc设备是没有具体的硬件的,实际上misc就是一块内存。那么为什么要用misc设备呢?是因为misc设备比较的简单。从上图也可以看出,binder的启动主要是binder_init、binder_open、binder_mmap、binder_ioctl方法。接下来一个一个的看一下流程。

1.4.1 binder_init 

废话不多说直接上代码:

// Binder.c (kernel\drivers\staging\android)static int __init binder_init(void)
{int ret;char *device_name, *device_names;struct binder_device *device;struct hlist_node *tmp;// 创建名为binder的单线程的工作队列binder_deferred_workqueue = create_singlethread_workqueue("binder");if (!binder_deferred_workqueue)return -ENOMEM;// 创建一个配置文件binder_debugfs_dir_entry_root = debugfs_create_dir("binder", NULL);if (binder_debugfs_dir_entry_root)binder_debugfs_dir_entry_proc = debugfs_create_dir("proc",binder_debugfs_dir_entry_root);if (binder_debugfs_dir_entry_root) {debugfs_create_file("state",S_IRUGO,binder_debugfs_dir_entry_root,NULL,&binder_state_fops);debugfs_create_file("stats",S_IRUGO,binder_debugfs_dir_entry_root,NULL,&binder_stats_fops);debugfs_create_file("transactions",S_IRUGO,binder_debugfs_dir_entry_root,NULL,&binder_transactions_fops);debugfs_create_file("transaction_log",S_IRUGO,binder_debugfs_dir_entry_root,&binder_transaction_log,&binder_transaction_log_fops);debugfs_create_file("failed_transaction_log",S_IRUGO,binder_debugfs_dir_entry_root,&binder_transaction_log_failed,&binder_transaction_log_fops);}/** Copy the module_parameter string, because we don't want to* tokenize it in-place.*/device_names = kzalloc(strlen(binder_devices_param) + 1, GFP_KERNEL);if (!device_names) {ret = -ENOMEM;goto err_alloc_device_names_failed;}// 将binder的配置信息ANDROID_BINDER_DEVICES读取到binder_devices_param中,然后通过此方法将binder_devices_param中的信息复制到device_names中strcpy(device_names, binder_devices_param);while ((device_name = strsep(&device_names, ","))) {// 初始化binder设备ret = init_binder_device(device_name);if (ret)goto err_init_binder_device_failed;}return ret;err_init_binder_device_failed:hlist_for_each_entry_safe(device, tmp, &binder_devices, hlist) {misc_deregister(&device->miscdev);hlist_del(&device->hlist);kfree(device);}
err_alloc_device_names_failed:debugfs_remove_recursive(binder_debugfs_dir_entry_root);destroy_workqueue(binder_deferred_workqueue);return ret;
}// 设备驱动入口函数
device_initcall(binder_init);

在设备启动的过程中,会调用到device_initcall函数,此函数会执行binder_init函数,binder_init函数中重要的节点都已注释,真正的初始化会在init_binder_device函数中实现:

// Binder.c (kernel\drivers\staging\android)// binder_devices, binder设备列表初始化
static HLIST_HEAD(binder_devices);static int __init init_binder_device(const char *name)
{int ret;struct binder_device *binder_device;// 为binder设备分配内存,也就是创建Binder驱动设备binder_device = kzalloc(sizeof(*binder_device), GFP_KERNEL);// 初始化设备binder_device->miscdev.fops = &binder_fops; // 设备的文件操作结构,这是file_operations结构binder_device->miscdev.minor = MISC_DYNAMIC_MINOR; // 次设备号 动态分配binder_device->miscdev.name = name; // 设备名,"binder"binder_device->context.binder_context_mgr_uid = INVALID_UID;binder_device->context.name = name;// misc驱动注册ret = misc_register(&binder_device->miscdev);// 将hlist节点添加到binder_devices为表头的设备链表hlist_add_head(&binder_device->hlist, &binder_devices);return ret;
}//native层通过syscall调用驱动层的函数,那么就需要有一个native层函数与驱动层函数相互映射的一个绑定关系,binder_fops 就是这个映射的绑定关系
static const struct file_operations binder_fops = {.owner = THIS_MODULE,.poll = binder_poll,.unlocked_ioctl = binder_ioctl,.compat_ioctl = binder_ioctl,.mmap = binder_mmap,.open = binder_open,.flush = binder_flush,.release = binder_release,
};

在前面也介绍了,去创建一个Binder驱动,用的是这个misc设备,Binder驱动是没有真正的设备的,但是它是表示一块内存的。

  1. 分配内存:首先在init_binder_device函数中就要给他分配一块内存,也就是创建Binder驱动设备:binder_device
  2. 初始化设备:其次在初始化binder_device设备的时候,会将native层的syscall函数与驱动的函数惊醒一个绑定操作,native层要调用驱动层,要经过syscall,那就要有一个绑定关系。类似于Java层调用Native层需要经过JNI一样。其实也可以理解为native层函数映射到驱动层的函数。
  3. 放入链表binder_devices:最后通过hlist_add_head函数将创建的binder_device驱动设备添加到驱动设备列表中。

经过上面的三个步骤,那么binder的驱动初始化就完成了。

1.4.2 binder_open

// kernel/drivers/staging/android/binder.cstatic int binder_open(struct inode *nodp, struct file *filp)
{struct binder_proc *proc;struct binder_device *binder_dev;binder_debug(BINDER_DEBUG_OPEN_CLOSE, "binder_open: %d:%d\n",current->group_leader->pid, current->pid);// 为binder_proc结构体在kernel分配内存空间proc = kzalloc(sizeof(*proc), GFP_KERNEL);if (proc == NULL)return -ENOMEM;// 将当前线程current的task保存到binder进程的tskget_task_struct(current);proc->tsk = current;INIT_LIST_HEAD(&proc->todo); // 初始化todo列表init_waitqueue_head(&proc->wait); // 初始化wait队列proc->default_priority = task_nice(current); // 将当前进程的nice值转换为进程优先级binder_dev = container_of(filp->private_data, struct binder_device,miscdev);proc->context = &binder_dev->context;// 同步锁,因为binder支持多线程访问binder_lock(__func__);binder_stats_created(BINDER_STAT_PROC); // binder_proc对象创建数加1hlist_add_head(&proc->proc_node, &binder_procs); // 将proc_node节点添加到binder_procs的队列头部proc->pid = current->group_leader->pid; // 进程pidINIT_LIST_HEAD(&proc->delivered_death); // 初始化已分发的死亡通知列表filp->private_data = proc; // 将这个binder_proc与filp关联起来,这样下次通过filp就能找到这个proc了// 释放同步锁binder_unlock(__func__);if (binder_debugfs_dir_entry_proc) {char strbuf[11];snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);/** proc debug entries are shared between contexts, so* this will fail if the process tries to open the driver* again with a different context. The priting code will* anyway print all contexts that a given PID has, so this* is not a problem.*/proc->debugfs_entry = debugfs_create_file(strbuf, S_IRUGO,binder_debugfs_dir_entry_proc,(void *)(unsigned long)proc->pid,&binder_proc_fops);}return 0;
}// 每个进程调用open()打开binder驱动都会创建该结构体,用于管理IPC所需的各种信息。
struct binder_proc {struct hlist_node proc_node; // 进程节点struct rb_root threads; // binder_thread红黑树的根节点struct rb_root nodes; // binder_node红黑树的根节点struct rb_root refs_by_desc; // binder_ref红黑树的根节点(以 handle为 key)struct rb_root refs_by_node; // binder_ref红黑树的根节点(以 ptr为 key)int pid; // 相应进程 idstruct vm_area_struct *vma; // 指向进程虚拟地址空间的指针struct mm_struct *vma_vm_mm; // 相应进程的内存结构体struct task_struct *tsk; // 相应进程的 task结构体struct files_struct *files; // 相应进程的文件结构体struct hlist_node deferred_work_node;int deferred_work;void *buffer; // 内核空间的起始地址ptrdiff_t user_buffer_offset; // 内核空间与用户空间的地址偏移量struct list_head buffers; // 所有的 bufferstruct rb_root free_buffers; // 空闲的 bufferstruct rb_root allocated_buffers; // 已分配的 buffersize_t free_async_space; // 异步的可用空闲空间大小struct page **pages; // 指向物理内存页指针的指针size_t buffer_size; // 映射的内核空间大小uint32_t buffer_free; // 可用内存总大小struct list_head todo; // 进程将要做的事wait_queue_head_t wait; // 等待队列struct binder_stats stats; // binder统计信息struct list_head delivered_death; // 已分发的死亡通知int max_threads; // 最大线程数int requested_threads; // 请求的线程数int requested_threads_started; // 已启动的请求线程数int ready_threads; // 准备就绪的线程个数long default_priority; // 默认优先级struct dentry *debugfs_entry;struct binder_context *context;
};

binder_open从名字也可以看出就是设备打开嘛,这个binder_open肯定是由客户端或者服务端去打开的。假如说我们有如下的绑定服务的一段代码,那么我们在调用bindService的时候就会触发binder_open的操作。

public class ClientActivity extends AppCompatActivity {private IPersonManager iPersonManager;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Intent intent = new Intent(this, RemoteService.class);intent.setAction("com.enjoy.binder");bindService(intent, connection, Context.BIND_AUTO_CREATE);findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {try {Log.e(TAG, "------------onClick:" + Thread.currentThread());iPersonManager.addPerson(new Person(TAG, 3));List<Person> persons = iPersonManager.getPersonList();Log.e(TAG, persons.toString() + "," + Thread.currentThread());} catch (RemoteException e) {e.printStackTrace();}}});}private ServiceConnection connection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {Log.e(TAG, "onServiceConnected: success");iPersonManager = Stub.asInterface(service);// proxy}@Overridepublic void onServiceDisconnected(ComponentName name) {Log.e(TAG, "onServiceDisconnected: success");iPersonManager = null;}};
}

1. 创建binder_proc对象:在binder_open中首先会初始化(分配内存)一个结构体binder_proc,这个结构体用来保存我们进程的信息的。创建的这个proc到底是什么东西呢?通俗来讲就是例子中的ClientActivity,Binder驱动中使用一个结构体保存了所有与ClientActivity相关的信息,无论是进程信息还是线程信息包括ClientActivity的信息。这样做的目的是什么呢?就是方便后续binder通过proc的对应信息能够操作ClientActivity。

2. 当前进程信息保存到proc :

// 将当前线程current的task保存到binder进程的tsk
get_task_struct(current);
proc->tsk = current;

用来保存当前线程的信息,就是当前要获取服务的线程信息。比如上面的代码中:

bindService(intent, connection, Context.BIND_AUTO_CREATE);

平时我们绑定服务时,所在的线程信息都会被保存到proc->tsk中。

3. 对proc进行初始化,并且将proc赋值给filp->private_data,由filp->private_data来保管proc:由于filp是一个指针,所以谁拿到了file就理所当然的就拿到了proc信息。

4. 将proc中的proc_node添加到binder_procs链表中:

总结:binder_open一共做了4件事:

  1. 创建binder_proc对象
  2. 当前进程信息保存到proc
  3. 对proc进行初始化,并且将proc赋值给filp->private_data,由filp->private_data来保管proc
  4. 将proc中的proc_node添加到binder_procs链表中

1.4.3 binder_mmap

// kernel/drivers/staging/android/binder.cstatic 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; // binder_open时,已经分析到,filp->private_data存储的是proc,此处就是通过filp->private_data获取我们上一部分存储到此的proc。const char *failure_string;struct binder_buffer *buffer;if (proc->tsk != current)return -EINVAL;// 保证映射内存大小不超过4Mif ((vma->vm_end - vma->vm_start) > SZ_4M)vma->vm_end = vma->vm_start + SZ_4M;binder_debug(BINDER_DEBUG_OPEN_CLOSE,"binder_mmap: %d %lx-%lx (%ld K) vma %lx pagep %lx\n",proc->pid, vma->vm_start, vma->vm_end,(vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,(unsigned long)pgprot_val(vma->vm_page_prot));if (vma->vm_flags & FORBIDDEN_MMAP_FLAGS) {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,goto跳转,释放同步锁后结束binder_mmap方法if (proc->buffer) {ret = -EBUSY;failure_string = "already mapped";goto err_already_mapped;}// 采用 VM_IOREMAP方式,分配一个连续的内核虚拟内存,与进程虚拟内存大小一致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指针指向这块内核的虚拟内存proc->buffer = area->addr;// 计算出用户空间和内核空间的地址偏移量。地址偏移量 = 用户虚拟内存地址 - 内核虚拟内存地址// 用户的虚拟内存中放入一段数据,那内核想要访问这一段数据,就需要拿到用户空间的虚拟地址,所以用户空间  = 虚拟内存地址 + 偏移值proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer;mutex_unlock(&binder_mmap_lock);#ifdef CONFIG_CPU_CACHE_VIPTif (cache_is_vipt_aliasing()) {while (CACHE_COLOUR((vma->vm_start ^ (uint32_t)proc->buffer))) {pr_info("binder_mmap: %d %lx-%lx maps %p bad alignment\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer);vma->vm_start += PAGE_SIZE;}}
#endif// 分配物理页的指针数组,数组大小为vma的等效page个数proc->pages = kzalloc(sizeof(proc->pages[0]) * ((vma->vm_end - vma->vm_start) / PAGE_SIZE), GFP_KERNEL);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;// 分配物理页面,同时映射到内核空间和进程空间,先分配1个物理页。此方法中将会完成物理内存和2块虚拟内存地址的映射关系。if (binder_update_page_range(proc, 1, proc->buffer, proc->buffer + PAGE_SIZE, vma)) {ret = -ENOMEM;failure_string = "alloc small buf";goto err_alloc_small_buf_failed;}buffer = proc->buffer;INIT_LIST_HEAD(&proc->buffers);// 将buffer连入buffers链表中list_add(&buffer->entry, &proc->buffers);// 标记此内存可用buffer->free = 1;binder_insert_free_buffer(proc, buffer);// 将buffer插入 proc->free_buffers 链表中proc->free_async_space = proc->buffer_size / 2;// 异步的可用空闲空间大小,也就是我们常说的1M-8K的一半barrier();proc->files = get_files_struct(current);proc->vma = vma;proc->vma_vm_mm = vma->vm_mm;/*pr_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:pr_err("binder_mmap: %d %lx-%lx %s failed %d\n",proc->pid, vma->vm_start, vma->vm_end, failure_string, ret);return ret;
}
// kernel/drivers/staging/android/binder.cstatic int binder_update_page_range(struct binder_proc *proc, int allocate,void *start, void *end,struct vm_area_struct *vma)
{void *page_addr;unsigned long user_page_addr;struct page **page;struct mm_struct *mm;binder_debug(BINDER_DEBUG_BUFFER_ALLOC,"%d: %s pages %p-%p\n", proc->pid,allocate ? "allocate" : "free", start, end);if (end <= start)return 0;trace_binder_update_page_range(proc, allocate, start, end);if (vma)mm = NULL;elsemm = get_task_mm(proc->tsk);if (mm) {down_write(&mm->mmap_sem);vma = proc->vma;if (vma && mm != proc->vma_vm_mm) {pr_err("%d: vma mm and task mm mismatch\n",proc->pid);vma = NULL;}}// allocate为1,代表分配内存过程。如果为0则代表释放内存过程if (allocate == 0)goto free_range;if (vma == NULL) {pr_err("%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;page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];BUG_ON(*page);// 分配一个page的物理内存*page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO);if (*page == NULL) {pr_err("%d: binder_alloc_buf failed for page at %p\n",proc->pid, page_addr);goto err_alloc_page_failed;}// 物理空间映射到虚拟内核空间ret = map_kernel_range_noflush((unsigned long)page_addr,PAGE_SIZE, PAGE_KERNEL, page);flush_cache_vmap((unsigned long)page_addr,(unsigned long)page_addr + PAGE_SIZE);if (ret != 1) {pr_err("%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]);if (ret) {pr_err("%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;
}

1.通过用户空间的虚拟内存大小分配一块内核的虚拟内存: struct vm_struct *area;为内核的虚拟内存,vma为进程的虚拟内存,驱动中规定了一个最大4M的大小,也就是说在驱动层,最大的大小就是4M。但是在native层定义的大小是1M-8K(后面章节会介绍定义,同步是1M-8K,异步的是1M-8K的一半,一般情况下都是同步的也就是1M-8K), 1M-8K的比4M小,所以Binder最大的大小是1M-8K,但是如果Native层定义的大小为6M,那么Binder的最大传输大小就是4M,因为6M超出了驱动定的4M的大小。

为什么intent传输大小为1M,因为intent是通过Binder去传输的,Binder中定义的大小就是1M-8K,所以intent的传输大小超过1M就会有问题。

同时为内核area内存大小分配一块与vma进程的虚拟内存大小一致的区域。为后续共享一块物理内存做准备。也就是后面2个虚拟地址映射到一块物理内存的大小:


2.分配了一块物理内存  --- 4KB: binder_update_page_range函数中既可以申请内存也可以释放内存(根据allocate为1,代表分配内存过程。如果为0,则代表释放内存过程)。传       入的是1,则是申请内存。

*page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO);

首先分配了一页(大小的意思)物理内存-4KB(一页的大小就是4KB)(当前初始化的时候先分配4KB,后续根据实际使用情况,再分配足够的大小,从而避免内存浪费)。

3. 把这块物理内存分别映射到用户空间的虚拟内存和内核的虚拟内存:第2步中已经申请了一个4KB的物理内存,紧接着通过2个函数将这块物理内存分别映射到内核的虚拟内存地址和进程的虚拟内存地址上:

// 物理空间映射到虚拟内核空间
ret = map_kernel_range_noflush((unsigned long)page_addr,PAGE_SIZE, PAGE_KERNEL, page);// 物理空间映射到虚拟进程空间
ret = vm_insert_page(vma, user_page_addr, page[0]);

到这里mmap的映射已经完成了,内核虚拟地址和进程虚拟地址都映射同一块物理内存。到这里mmap的主要流程都已经介绍完了。在mmap的最后调用了binder_insert_free_buffer函数,我们来分析一下这个函数的作用:

// kernel/drivers/staging/android/binder.cstatic void binder_insert_free_buffer(struct binder_proc *proc,struct binder_buffer *new_buffer)
{struct rb_node **p = &proc->free_buffers.rb_node;struct rb_node *parent = NULL;struct binder_buffer *buffer;size_t buffer_size;size_t new_buffer_size;BUG_ON(!new_buffer->free);new_buffer_size = binder_buffer_size(proc, new_buffer);binder_debug(BINDER_DEBUG_BUFFER_ALLOC,"%d: add free buffer, size %zd, at %p\n",proc->pid, new_buffer_size, new_buffer);while (*p) {parent = *p;buffer = rb_entry(parent, struct binder_buffer, rb_node);BUG_ON(!buffer->free);// 计算得出空闲内存的大小buffer_size = binder_buffer_size(proc, buffer);if (new_buffer_size < buffer_size)p = &parent->rb_left;elsep = &parent->rb_right;}rb_link_node(&new_buffer->rb_node, parent, p);// 将 buffer插入 proc->free_buffers 链表中rb_insert_color(&new_buffer->rb_node, &proc->free_buffers);
}

这块代码并不重要,就是计算freebuffer等值。

总结:binder_mmap一共有如下的几件事

  1. 通过用户空间的虚拟内存大小分配一块内核的虚拟内存
  2. 分配了一块物理内存  --- 4KB
  3. 把这块物理内存分别映射到用户空间的虚拟内存和内核的虚拟内存

1.4.4 binder_ioctl

// kernel/drivers/staging/android/binder.cstatic 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;unsigned int size = _IOC_SIZE(cmd);void __user *ubuf = (void __user *)arg;/*pr_info("binder_ioctl: %d:%d %x %lx\n",proc->pid, current->pid, cmd, arg);*/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__);// 根据当前进程的pid,从binder_proc中查找binder_thread,// 如果当前线程已经加入到proc的线程队列则直接返回,// 如果不存在则创建binder_thread,并将当前线程添加到当前的procthread = binder_get_thread(proc);if (thread == NULL) {ret = -ENOMEM;goto err;}switch (cmd) {// 进行binder的读写操作case BINDER_WRITE_READ:ret = binder_ioctl_write_read(filp, cmd, arg, thread);if (ret)goto err;break;case BINDER_SET_MAX_THREADS:if (copy_from_user(&proc->max_threads, ubuf, sizeof(proc->max_threads))) {ret = -EINVAL;goto err;}break;case BINDER_SET_CONTEXT_MGR:ret = binder_ioctl_set_ctx_mgr(filp);if (ret)goto err;break;case BINDER_THREAD_EXIT:binder_debug(BINDER_DEBUG_THREADS, "%d:%d exit\n",proc->pid, thread->pid);binder_free_thread(proc, thread);thread = NULL;break;case BINDER_VERSION: {struct binder_version __user *ver = ubuf;if (size != sizeof(struct binder_version)) {ret = -EINVAL;goto err;}if (put_user(BINDER_CURRENT_PROTOCOL_VERSION,&ver->protocol_version)) {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)pr_info("%d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
err_unlocked:trace_binder_ioctl_done(ret);return ret;
}
// kernel/drivers/staging/android/binder.cstatic int binder_ioctl_write_read(struct file *filp,unsigned int cmd, unsigned long arg,struct binder_thread *thread)
{int ret = 0;struct binder_proc *proc = filp->private_data;unsigned int size = _IOC_SIZE(cmd);void __user *ubuf = (void __user *)arg;struct binder_write_read bwr;if (size != sizeof(struct binder_write_read)) {ret = -EINVAL;goto out;}// 把用户空间数据ubuf拷贝到bwrif (copy_from_user(&bwr, ubuf, sizeof(bwr))) {ret = -EFAULT;goto out;}binder_debug(BINDER_DEBUG_READ_WRITE,"%d:%d write %lld at %016llx, read %lld at %016llx\n",proc->pid, thread->pid,(u64)bwr.write_size, (u64)bwr.write_buffer,(u64)bwr.read_size, (u64)bwr.read_buffer);if (bwr.write_size > 0) { // 当写缓存中有数据,则执行binder写操作ret = binder_thread_write(proc, thread,bwr.write_buffer,bwr.write_size,&bwr.write_consumed);trace_binder_write_done(ret);if (ret < 0) {bwr.read_consumed = 0;if (copy_to_user(ubuf, &bwr, sizeof(bwr)))ret = -EFAULT;goto out;}}if (bwr.read_size > 0) { // 当读缓存中有数据,则执行binder读操作ret = binder_thread_read(proc, thread, bwr.read_buffer,bwr.read_size,&bwr.read_consumed,filp->f_flags & O_NONBLOCK);trace_binder_read_done(ret);// 进程todo队列不为空,则唤醒该队列中的线程if (!list_empty(&proc->todo))wake_up_interruptible(&proc->wait);if (ret < 0) {if (copy_to_user(ubuf, &bwr, sizeof(bwr)))ret = -EFAULT;goto out;}}binder_debug(BINDER_DEBUG_READ_WRITE,"%d:%d wrote %lld of %lld, read return %lld of %lld\n",proc->pid, thread->pid,(u64)bwr.write_consumed, (u64)bwr.write_size,(u64)bwr.read_consumed, (u64)bwr.read_size);// 把内核空间数据bwr拷贝到ubufif (copy_to_user(ubuf, &bwr, sizeof(bwr))) {ret = -EFAULT;goto out;}
out:return ret;
}

binder_ioctrl主要是读写操作的。ioctrl中传入的是BINDER_WRITE_READ的指令,一般情况下是ioctl(BINDER_WRITE_READ)的样子,当执行的Switch语句的时候,就会调用binder_ioctl_write_read函数执行。

1. 首先会有一个挂起中断wait_event_interruptible操作:当然正常的情况下是不会中断的,会直接走下去。

2. 根据当前进程的pid,从binder_proc中查找binder_thread。

3. 根据指令,读取或者写数据。

最后我们介绍1个结构体:

binder_buffer

struct binder_buffer {struct list_head entry; // buffer实体的地址struct rb_node rb_node; // buffer实体的地址/* by address */unsigned free:1; // 标记是否是空闲buffer,占位1bitunsigned allow_user_free:1; // 是否允许用户释放,占位1bitunsigned async_transaction:1; // 占位1bitunsigned debug_id:29; // 占位29bitstruct binder_transaction *transaction; // 该缓存区的需要处理的事务struct binder_node *target_node; // 该缓存区所需处理的Binder实体size_t data_size; // 数据大小size_t offsets_size; // 数据偏移量size_t extra_buffers_size;uint8_t data[0]; // 数据地址};

1.5 JNI层binder的启动流程

binder的启动流程就牵扯到zygote,在zygote的rc文件中,有一些启动指令:

// system\core\rootdir\init.zygote32.rcservice zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-serverclass mainsocket zygote stream 660 root systemonrestart write /sys/android_power/request_state wakeonrestart write /sys/power/state ononrestart restart mediaonrestart restart netdwritepid /dev/cpuset/foreground/tasks

在Zygote启动的时候,就会调用到框架层的app_main.cpp中的main函数中。在main方法中会有如下的逻辑执行Zygote的启动:

// frameworks\base\cmds\app_process\app_main.cppint main() {AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));// Process command line arguments// ignore argv[0]argc--;argv++;// 省略很多代码.....while (i < argc) {const char* arg = argv[i++];if (strcmp(arg, "--zygote") == 0) {zygote = true;niceName = ZYGOTE_NICE_NAME;} else if (strcmp(arg, "--start-system-server") == 0) {startSystemServer = true;} else if (strcmp(arg, "--application") == 0) {application = true;} else if (strncmp(arg, "--nice-name=", 12) == 0) {niceName.setTo(arg + 12);} else if (strncmp(arg, "--", 2) != 0) {className.setTo(arg);break;} else {--i;break;}}// 省略很多代码.....if (zygote) {runtime.start("com.android.internal.os.ZygoteInit", args, zygote);} else if (className) {runtime.start("com.android.internal.os.RuntimeInit", args, zygote);} else {fprintf(stderr, "Error: no class name or --zygote supplied.\n");app_usage();LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");return 10;}
}

执行runtime.start("com.android.internal.os.ZygoteInit", args, zygote);指令时就会调用到AppRuntime中的start方法,由于class AppRuntime : public AndroidRuntime的继承关系,所以最终就是要进入AndroidRuntime里面。来看一下AndroidRuntime中的start函数:

// frameworks\base\core\jni\AndroidRuntime.cpp/** Start the Android runtime.  This involves starting the virtual machine* and calling the "static void main(String[] args)" method in the class* named by "className".** Passes the main function two arguments, the class name and the specified* options string.*/
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{ALOGD(">>>>>> START %s uid %d <<<<<<\n",className != NULL ? className : "(unknown)", getuid());static const String8 startSystemServer("start-system-server");/** 'startSystemServer == true' means runtime is obsolete and not run from* init.rc anymore, so we print out the boot start event here.*/for (size_t i = 0; i < options.size(); ++i) {if (options[i] == startSystemServer) {/* track our progress through the boot sequence */const int LOG_BOOT_PROGRESS_START = 3000;LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,  ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));}}const char* rootDir = getenv("ANDROID_ROOT");if (rootDir == NULL) {rootDir = "/system";if (!hasDir("/system")) {LOG_FATAL("No root directory specified, and /android does not exist.");return;}setenv("ANDROID_ROOT", rootDir, 1);}//const char* kernelHack = getenv("LD_ASSUME_KERNEL");//ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);/* start the virtual machine */JniInvocation jni_invocation;jni_invocation.Init(NULL);JNIEnv* env;if (startVm(&mJavaVM, &env, zygote) != 0) {return;}onVmCreated(env);/** Register android functions.*/if (startReg(env) < 0) {ALOGE("Unable to register all android natives\n");return;}/** We want to call main() with a String array with arguments in it.* At present we have two arguments, the class name and an option string.* Create an array to hold them.*/jclass stringClass;jobjectArray strArray;jstring classNameStr;stringClass = env->FindClass("java/lang/String");assert(stringClass != NULL);strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);assert(strArray != NULL);classNameStr = env->NewStringUTF(className);assert(classNameStr != NULL);env->SetObjectArrayElement(strArray, 0, classNameStr);for (size_t i = 0; i < options.size(); ++i) {jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());assert(optionsStr != NULL);env->SetObjectArrayElement(strArray, i + 1, optionsStr);}// 省略很多代码......
}

start方法中只要关注startReg方法即可。

// frameworks\base\core\jni\AndroidRuntime.cpp/** Register android native functions with the VM.*/
/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
{/** This hook causes all future threads created in this process to be* attached to the JavaVM.  (This needs to go away in favor of JNI* Attach calls.)*/androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);ALOGV("--- registering native functions ---\n");/** Every "register" function calls one or more things that return* a local reference (e.g. FindClass).  Because we haven't really* started the VM yet, they're all getting stored in the base frame* and never released.  Use Push/Pop to manage the storage.*/env->PushLocalFrame(200);if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {env->PopLocalFrame(NULL);return -1;}env->PopLocalFrame(NULL);//createJavaThread("fubar", quickTest, (void*) "hello");return 0;
}

start这个方法里面注册jni,register_jni_procs这个方法会注册binder的jni,只有注册了jni之后,我们的上层Java方法才能够调用到Jni中的方法,进而调用到Native层的方法。

// frameworks\base\core\jni\AndroidRuntime.cppstatic int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{for (size_t i = 0; i < count; i++) {if (array[i].mProc(env) < 0) {
#ifndef NDEBUGALOGD("----------!!! %s failed to load\n", array[i].mName);
#endifreturn -1;}}return 0;
}static const RegJNIRec gRegJNI[] = {REG_JNI(register_com_android_internal_os_RuntimeInit),REG_JNI(register_android_os_SystemClock),REG_JNI(register_android_util_EventLog),REG_JNI(register_android_util_Log),REG_JNI(register_android_content_AssetManager),REG_JNI(register_android_content_StringBlock),REG_JNI(register_android_content_XmlBlock),REG_JNI(register_android_emoji_EmojiFactory),REG_JNI(register_android_text_AndroidCharacter),REG_JNI(register_android_text_StaticLayout),REG_JNI(register_android_text_AndroidBidi),REG_JNI(register_android_view_InputDevice),REG_JNI(register_android_view_KeyCharacterMap),REG_JNI(register_android_os_Process),REG_JNI(register_android_os_SystemProperties),REG_JNI(register_android_os_Binder),// 注册binder的jni// 省略很多代码.....
}

这里面就会执行register_android_os_Binder函数:

\\ frameworks\base\core\jni\android_util_Binder.cppint register_android_os_Binder(JNIEnv* env)
{if (int_register_android_os_Binder(env) < 0)return -1;if (int_register_android_os_BinderInternal(env) < 0)return -1;if (int_register_android_os_BinderProxy(env) < 0)return -1;jclass clazz = FindClassOrDie(env, "android/util/Log");gLogOffsets.mClass = MakeGlobalRefOrDie(env, clazz);gLogOffsets.mLogE = GetStaticMethodIDOrDie(env, clazz, "e","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I");clazz = FindClassOrDie(env, "android/os/ParcelFileDescriptor");gParcelFileDescriptorOffsets.mClass = MakeGlobalRefOrDie(env, clazz);gParcelFileDescriptorOffsets.mConstructor = GetMethodIDOrDie(env, clazz, "<init>","(Ljava/io/FileDescriptor;)V");clazz = FindClassOrDie(env, "android/os/StrictMode");gStrictModeCallbackOffsets.mClass = MakeGlobalRefOrDie(env, clazz);gStrictModeCallbackOffsets.mCallback = GetStaticMethodIDOrDie(env, clazz,"onBinderStrictModePolicyChange", "(I)V");return 0;
}

这个方法中有三个注册,那我们看一下其中一个即可int_register_android_os_Binder:

// frameworks\base\core\jni\android_util_Binder.cppstatic const JNINativeMethod gBinderMethods[] = {/* name, signature, funcPtr */{ "getCallingPid", "()I", (void*)android_os_Binder_getCallingPid },{ "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid },{ "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity },{ "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity },{ "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy },{ "getThreadStrictModePolicy", "()I", (void*)android_os_Binder_getThreadStrictModePolicy },{ "flushPendingCommands", "()V", (void*)android_os_Binder_flushPendingCommands },{ "init", "()V", (void*)android_os_Binder_init },{ "destroy", "()V", (void*)android_os_Binder_destroy },{ "blockUntilThreadAvailable", "()V", (void*)android_os_Binder_blockUntilThreadAvailable }
};const char* const kBinderPathName = "android/os/Binder";static int int_register_android_os_Binder(JNIEnv* env)
{jclass clazz = FindClassOrDie(env, kBinderPathName);gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz);gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z");gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");return RegisterMethodsOrDie(env, kBinderPathName,gBinderMethods, NELEM(gBinderMethods));
}

这个方法主要就是通过反射手段保存了框架层的类的一些信息到gBinderOffsets中。从而便于后期Native层调用Java层的代码。最后一个RegisterMethodsOrDie方法中,会携带一个参数gBinderMethods,gBinderMethods中会有框架层的方法与Native层的方法的一个映射关系。方便后续Java层调用Native层的方法。到此时,是不是大家都理解了,其实Binder的JNI层就是将框架层与Native层的函数的映射关系注册到JNI中,从而形成一个互相调用的调用链。

到这里我们大概明白了,在系统启动的时候,就会启动Zygote,Zygote在启动过程中就会将JNI的映射关系注册,从而为后续Binder的调用做好基础。

2 Binder中的service_manager服务

service_manager是什么呢?总的来说service_manager是一个大管家。都知道系统中有很多的服务,比如AMS、PMS等等,那么想要跨进程的调用服务中的功能,就需要获取到该服务实现的IBinder对象,系统中有很多很多的跨进程的服务,开发者不可能记住所有服务实现的IBinder对象,甚至即时知道了每一个服务的实现IBinder对象也不允许直接去获取,因为这样也不安全。那么为了解决既方便获取又安全获取的需求,所以就产生了一个服务叫service_manager,service_manager有一个特点就是handler==0,那么开发者只需要记住service_manager一个就可以了。service_manager本身也是一个服务,所以获取service_manager对象时,也是通过跨进程实现的。那想要获取AMS的IBinder实现对象,就需要先获取到service_manager对象,然后通过service_manager返回AMS的IBinder对象给开发者。这样是不是就方便多了?其实这里要提一点,service_manager是怎么拿到类似AMS的IBinder对象的呢?其实这与AMS的创建过程有关系,在service_manager创建的过程中,就会创建AMS服务,在AMS的创建过程中就会将自己添加到service_manager管理队列中,这样就相当于AMS将自己托管给了service_manager。来个简单的图:

就是service_manager本身也是服务,所以客户端要获取某一个服务之前先获取到的都是service_manager的IBinder对象,然后通过service_manager的IBinder对象在获取到对应的某一个服务的IBinder的对象。这就体会到这个service_manager大管家的地位了吧。

2.1 如何启动service_manager服务

ServiceManager是由init进程通过解析init.rc文件而创建的,其所对应的可执行程序servicemanager, 所对应的源文件是service_manager.c,进程名为servicemanager。

// system/core/rootdir/init.rcservice servicemanager /system/bin/servicemanagerclass coreuser systemgroup systemcriticalonrestart restart healthdonrestart restart zygoteonrestart restart mediaonrestart restart surfaceflingeronrestart restart drm

了解rc文件可以知道启动ServiceManager的入口函数是 service_manager.c 中的main()方法:

// frameworks/native/cmds/servicemanager/service_manager.cint main(int argc, char **argv)
{struct binder_state *bs;// 打开 binder驱动,申请 128k字节大小的内存空间bs = binder_open(128*1024);if (!bs) {ALOGE("failed to open binder driver\n");return -1;}// 设为守护进程,成为 binder大管理者if (binder_become_context_manager(bs)) {ALOGE("cannot become context manager (%s)\n", strerror(errno));return -1;}selinux_enabled = is_selinux_enabled();sehandle = selinux_android_service_context_handle();selinux_status_open(true);if (selinux_enabled > 0) {if (sehandle == NULL) {ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");abort();}if (getcon(&service_manager_context) != 0) {ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");abort();}}union selinux_callback cb;cb.func_audit = audit_callback;selinux_set_callback(SELINUX_CB_AUDIT, cb);cb.func_log = selinux_log_callback;selinux_set_callback(SELINUX_CB_LOG, cb);// 进入无限循环,处理client端发来的请求binder_loop(bs, svcmgr_handler);return 0;
}

main函数一共做了3件事:

  1. 打开驱动,内存映射(设置大小 128K)
  2. 设置 SM 为大管家 --- sm  作用  为了管理系统服务
  3. BC_ENTER_LOOPER 命令(进入循环读取的一个状态)

接下来我们看一下这3件事具体做了什么。

2.1.1 打开驱动,内存映射(设置大小 128K):

// frameworks/native/cmds/servicemanager/binder.cstruct binder_state *binder_open(size_t mapsize)
{// 这个结构体记录了 service_manager 中有关于 binder 的所有信息struct binder_state *bs;struct binder_version vers;bs = malloc(sizeof(*bs));if (!bs) {errno = ENOMEM;return NULL;}// 打开 binder驱动,得到文件描述符bs->fd = open("/dev/binder", O_RDWR);if (bs->fd < 0) {fprintf(stderr,"binder: cannot open device (%s)\n",strerror(errno));goto fail_open;}if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||(vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {fprintf(stderr,"binder: kernel driver version (%d) differs from user space version (%d)\n",vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION);goto fail_open;}bs->mapsize = mapsize;// service_manager自己设置的,大小为 128kb/*通过系统调用,mmap内存映射,mmap必须是 page的整数倍(即 4kb的整数倍)*/bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);if (bs->mapped == MAP_FAILED) {fprintf(stderr,"binder: cannot map device (%s)\n",strerror(errno));goto fail_map;}return bs;fail_map:close(bs->fd);
fail_open:free(bs);return NULL;
}


2.1.2 设置 SM 为大管家 --- sm的作用是为了管理系统服务

// frameworks/native/cmds/servicemanager/binder.cint binder_become_context_manager(struct binder_state *bs)
{// 调用ioctl然后传入BINDER_SET_CONTEXT_MGR指令,从这里就会进入到kernel的ioctl函数中return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}

进入kernel的驱动的binder_ioctl函数中,我们重点关注BINDER_SET_CONTEXT_MGR消息的处理:

// kernel/drivers/staging/android/binder.cstatic 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;unsigned int size = _IOC_SIZE(cmd);void __user *ubuf = (void __user *)arg;/*pr_info("binder_ioctl: %d:%d %x %lx\n",proc->pid, current->pid, cmd, arg);*/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);if (thread == NULL) {ret = -ENOMEM;goto err;}switch (cmd) {case BINDER_WRITE_READ:ret = binder_ioctl_write_read(filp, cmd, arg, thread);if (ret)goto err;break;case BINDER_SET_MAX_THREADS:if (copy_from_user(&proc->max_threads, ubuf, sizeof(proc->max_threads))) {ret = -EINVAL;goto err;}break;case BINDER_SET_CONTEXT_MGR:ret = binder_ioctl_set_ctx_mgr(filp);if (ret)goto err;break;case BINDER_THREAD_EXIT:binder_debug(BINDER_DEBUG_THREADS, "%d:%d exit\n",proc->pid, thread->pid);binder_free_thread(proc, thread);thread = NULL;break;case BINDER_VERSION: {struct binder_version __user *ver = ubuf;if (size != sizeof(struct binder_version)) {ret = -EINVAL;goto err;}if (put_user(BINDER_CURRENT_PROTOCOL_VERSION,&ver->protocol_version)) {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)pr_info("%d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
err_unlocked:trace_binder_ioctl_done(ret);return ret;
}

调用到binder_ioctl_set_ctx_mgr函数:

// kernel/drivers/staging/android/binder.cstatic int binder_ioctl_set_ctx_mgr(struct file *filp)
{int ret = 0;struct binder_proc *proc = filp->private_data;struct binder_context *context = proc->context;kuid_t curr_euid = current_euid();// 保证只创建一次 mgr_node对象,不为 null就直接返回if (context->binder_context_mgr_node) {pr_err("BINDER_SET_CONTEXT_MGR already set\n");ret = -EBUSY;goto out;}ret = security_binder_set_context_mgr(proc->tsk);if (ret < 0)goto out;/* uid是否有效,当前是无效的 */if (uid_valid(context->binder_context_mgr_uid)) {if (!uid_eq(context->binder_context_mgr_uid, curr_euid)) {pr_err("BINDER_SET_CONTEXT_MGR bad uid %d != %d\n",from_kuid(&init_user_ns, curr_euid),from_kuid(&init_user_ns,context->binder_context_mgr_uid));ret = -EPERM;goto out;}} else {/* 设置当前线程 euid作为 service_manager的 uid */context->binder_context_mgr_uid = curr_euid;}// 创建 service_manager实体context->binder_context_mgr_node = binder_new_node(proc, 0, 0);if (!context->binder_context_mgr_node) {ret = -ENOMEM;goto out;}// 将 binder_context_mgr_node的强弱引用各加 1context->binder_context_mgr_node->local_weak_refs++;context->binder_context_mgr_node->local_strong_refs++;context->binder_context_mgr_node->has_strong_ref = 1;context->binder_context_mgr_node->has_weak_ref = 1;
out:return ret;
}

  binder_ioctl_set_ctx_mgr函数的作用就是保证一个进程只创建一个ServiceManager的实体对象:binder_node。binder_node会通过binder_new_node函数来创建:

// kernel/drivers/staging/android/binder.cstatic struct binder_node *binder_new_node(struct binder_proc *proc,binder_uintptr_t ptr,binder_uintptr_t cookie)
{struct rb_node **p = &proc->nodes.rb_node;struct rb_node *parent = NULL;struct binder_node *node;// 首次进来为空while (*p) {parent = *p;node = rb_entry(parent, struct binder_node, rb_node);if (ptr < node->ptr)p = &(*p)->rb_left;else if (ptr > node->ptr)p = &(*p)->rb_right;elsereturn NULL;}// 给新创建的binder_node 分配内核空间node = kzalloc(sizeof(*node), GFP_KERNEL);if (node == NULL)return NULL;binder_stats_created(BINDER_STAT_NODE);// 将新创建的 node对象添加到 proc红黑树rb_link_node(&node->rb_node, parent, p);rb_insert_color(&node->rb_node, &proc->nodes);node->debug_id = ++binder_last_id;// 初始化 binder_nodenode->proc = proc;node->ptr = ptr;node->cookie = cookie;node->work.type = BINDER_WORK_NODE;// 创建work和todo队列INIT_LIST_HEAD(&node->work.entry);INIT_LIST_HEAD(&node->async_todo);binder_debug(BINDER_DEBUG_INTERNAL_REFS,"%d:%d node %d u%016llx c%016llx created\n",proc->pid, current->pid, node->debug_id,(u64)node->ptr, (u64)node->cookie);return node;
}

binder_node结构体: 

struct binder_node {int debug_id; // 节点创建时分配,具有全局唯一性,用于调试使用struct binder_work work;union {struct rb_node rb_node; // binder节点正常使用,unionstruct hlist_node dead_node; // binder节点已销毁,union};struct binder_proc *proc; // binder所在的进程,见后面小节struct hlist_head refs; // 所有指向该节点的 binder引用队列int internal_strong_refs;int local_weak_refs;int local_strong_refs;binder_uintptr_t ptr; // 指向用户空间 binder_node的指针,对应于 
flat_binder_object.binderbinder_uintptr_t cookie; // 指向用户空间 binder_node的指针,附件数据,对应于 
flat_binder_object.cookieunsigned has_strong_ref:1; // 占位 1bitunsigned pending_strong_ref:1; // 占位 1bitunsigned has_weak_ref:1; // 占位 1bitunsigned pending_weak_ref:1; // 占位 1bitunsigned has_async_transaction:1; // 占位 1bitunsigned accept_fds:1; // 占位 1bitunsigned min_priority:8; // 占位 8bit,最小优先级struct list_head async_todo; // 异步todo队列};

到这里大概就清楚了service_manager的实体就是一个结构体:binder_node。binder_node的创建是在binder_new_node函数中实现,binder_new_node主要做了如下的几件事情:

  1. 创建 binder_node 结构体对象
  2. 将proc指向binder_node结构体
  3. 创建  work  和 todo 类似 handler的messageQueue队列,用于存储客户端和服务端的消息的队列,由于sm是客户端和服务端2边所以需要2个队列进行消息存储。

介绍完SM变成大管家后,继续回到service_manager的main方法中,看一下binder_loop:

2.1.3 BC_ENTER_LOOPER 命令

// frameworks/native/cmds/servicemanager/binder.cvoid binder_loop(struct binder_state *bs, binder_handler func)
{int res;struct binder_write_read bwr;uint32_t readbuf[32];bwr.write_size = 0; // 初始化为 0bwr.write_consumed = 0;bwr.write_buffer = 0;readbuf[0] = BC_ENTER_LOOPER; // 读写要处理的命令binder_write(bs, readbuf, sizeof(uint32_t)); // 设置线程的 looper状态为循环状态for (;;) {bwr.read_size = sizeof(readbuf);bwr.read_consumed = 0;bwr.read_buffer = (uintptr_t) readbuf;/* 不断地 binder读数据,没有数据会进入休眠状态 */res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);if (res < 0) {ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));break;}res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);if (res == 0) {ALOGE("binder_loop: unexpected reply?!\n");break;}if (res < 0) {ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));break;}}
}

binder_loop主要作用就是轮询处理数据。主要有以下2个操作:

  1. 写入状态Loop
  2. 去读数据:binder_thread_read:ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread)); 进入等待
2.1.3.1 写入状态Loop

首先会通过函数binder_write写一个状态值,状态值表示当前已进入轮询状态,在介绍binder_write之前,先介绍一个结构体:
 

// kernel/drivers/staging/android/binder.h/** On 64-bit platforms where user code may run in 32-bits the driver must* translate the buffer (and local binder) addresses appropriately.*/struct binder_write_read {// 写数据binder_size_t		write_size;	/* bytes to write */binder_size_t		write_consumed;	/* bytes consumed by driver */binder_uintptr_t	write_buffer;// 读数据binder_size_t		read_size;	/* bytes to read */binder_size_t		read_consumed;	/* bytes consumed by driver */binder_uintptr_t	read_buffer;
};
// frameworks/native/cmds/servicemanager/binder.cint binder_write(struct binder_state *bs, void *data, size_t len)
{struct binder_write_read bwr;int res;bwr.write_size = len;// 大于 0,进入 binder_thread_write(下面ioctl中会调用)bwr.write_consumed = 0;bwr.write_buffer = (uintptr_t) data;// 此处 data为 BC_ENTER_LOOPER// read 状态全部设置为0,所以read不会进入binder_thread_read(下面ioctl中会调用)函数bwr.read_size = 0; bwr.read_consumed = 0;bwr.read_buffer = 0;/* 设置线程的 looper状态为循环状态 */res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);if (res < 0) {fprintf(stderr,"binder_write: ioctl failed (%s)\n",strerror(errno));}return res;
}

binder_write的操作比较简单,就是这是了write和read的变量值,然后ioctl会根据当前设置的write和read的值去调用对应的逻辑,那接着分析一下ioctl(也就是kernel中的binder_ioctrl,上一章节也介绍过该函数),ioctl携带的命令是BINDER_WRITE_READ,那看一下binder_ioctrl中switch该指令的实现:

// kernel/drivers/staging/android/binder.cstatic 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;unsigned int size = _IOC_SIZE(cmd);void __user *ubuf = (void __user *)arg;/*pr_info("binder_ioctl: %d:%d %x %lx\n",proc->pid, current->pid, cmd, arg);*/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);if (thread == NULL) {ret = -ENOMEM;goto err;}switch (cmd) {case BINDER_WRITE_READ:ret = binder_ioctl_write_read(filp, cmd, arg, thread);if (ret)goto err;break;// 省略代码......
}

BINDER_WRITE_READ处理时,会调用binder_ioctl_write_read函数,并且携带着相关的参数:

// kernel/drivers/staging/android/binder.cstatic int binder_ioctl_write_read(struct file *filp,unsigned int cmd, unsigned long arg,struct binder_thread *thread)
{int ret = 0;struct binder_proc *proc = filp->private_data;unsigned int size = _IOC_SIZE(cmd);void __user *ubuf = (void __user *)arg;struct binder_write_read bwr;if (size != sizeof(struct binder_write_read)) {ret = -EINVAL;goto out;}// 将刚才用户空间设置的数据,拷贝到内核空间if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {ret = -EFAULT;goto out;}binder_debug(BINDER_DEBUG_READ_WRITE,"%d:%d write %lld at %016llx, read %lld at %016llx\n",proc->pid, thread->pid,(u64)bwr.write_size, (u64)bwr.write_buffer,(u64)bwr.read_size, (u64)bwr.read_buffer);// 如果当前write有数据,则调用binder_thread_write函数if (bwr.write_size > 0) {ret = binder_thread_write(proc, thread,bwr.write_buffer,bwr.write_size,&bwr.write_consumed);trace_binder_write_done(ret);if (ret < 0) {bwr.read_consumed = 0;if (copy_to_user(ubuf, &bwr, sizeof(bwr)))ret = -EFAULT;goto out;}}// 如果当前read有数据,那就调用binder_thread_read函数if (bwr.read_size > 0) {ret = binder_thread_read(proc, thread, bwr.read_buffer,bwr.read_size,&bwr.read_consumed,filp->f_flags & O_NONBLOCK);trace_binder_read_done(ret);if (!list_empty(&proc->todo))wake_up_interruptible(&proc->wait);if (ret < 0) {if (copy_to_user(ubuf, &bwr, sizeof(bwr)))ret = -EFAULT;goto out;}}binder_debug(BINDER_DEBUG_READ_WRITE,"%d:%d wrote %lld of %lld, read return %lld of %lld\n",proc->pid, thread->pid,(u64)bwr.write_consumed, (u64)bwr.write_size,(u64)bwr.read_consumed, (u64)bwr.read_size);if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {ret = -EFAULT;goto out;}
out:return ret;
}

binder_ioctl_write_read函数的逻辑比较清晰,首先会将刚才用户空间设置的数据通过copy_from_user函数拷贝到内核空间。这次拷贝并不是我们上面介绍的1次拷贝的操作,而是用户数据的命令头,其实前面我们讲的1次拷贝是有一个前提得,就是对数据进行一次拷贝操作,但实际上还有一些其他的拷贝操作,这里我们解释一下哈,1次拷贝并不是说只能拷贝一次,而是指数据只拷贝1次。然后根据调用者传入的参数,判定执行binder_thread_write和binder_thread_read函数,前面我们也分析,binder_write中已经设置了write的结构体数据,那此处逻辑走的是binder_thread_write函数:

// kernel/drivers/staging/android/binder.cstatic int binder_thread_write(struct binder_proc *proc,struct binder_thread *thread,binder_uintptr_t binder_buffer, size_t size,binder_size_t *consumed)
{uint32_t cmd;struct binder_context *context = proc->context;void __user *buffer = (void __user *)(uintptr_t)binder_buffer;void __user *ptr = buffer + *consumed;void __user *end = buffer + size;while (ptr < end && thread->return_error == BR_OK) {// 获取命令,即 BC_ENTER_LOOPERif (get_user(cmd, (uint32_t __user *)ptr))return -EFAULT;ptr += sizeof(uint32_t);trace_binder_command(cmd);if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.bc)) {binder_stats.bc[_IOC_NR(cmd)]++;proc->stats.bc[_IOC_NR(cmd)]++;thread->stats.bc[_IOC_NR(cmd)]++;}switch (cmd) {// 省略代码......// 处理BC_ENTER_LOOPER指令case BC_ENTER_LOOPER:binder_debug(BINDER_DEBUG_THREADS,"%d:%d BC_ENTER_LOOPER\n",proc->pid, thread->pid);if (thread->looper & BINDER_LOOPER_STATE_REGISTERED) {thread->looper |= BINDER_LOOPER_STATE_INVALID;binder_user_error("%d:%d ERROR: BC_ENTER_LOOPER called after BC_REGISTER_LOOPER\n",proc->pid, thread->pid);}// 设置该线程的 looper状态thread->looper |= BINDER_LOOPER_STATE_ENTERED;break;}// 省略代码......}// 省略代码......
}

 binder_thread_write比较长,只展示跟逻辑相关的代码,BC_ENTER_LOOPER逻辑处理也比较简单,就是将我们当前线程的循环状态设置为BINDER_LOOPER_STATE_ENTERED状态。到此binder_loop函数的binder_write函数写Loop状态已经完成。那接下里继续分析binder_loop中的for循环,也就是去读数据:binder_thread_read:ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread)); 进入等待。

2.1.3.2 进入等待

去读数据:binder_thread_read:ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread)); 进入等待。binder_loop中的for循环:

// frameworks/native/cmds/servicemanager/binder.cvoid binder_loop(struct binder_state *bs, binder_handler func)
{int res;struct binder_write_read bwr;uint32_t readbuf[32];bwr.write_size = 0; // 初始化为 0bwr.write_consumed = 0;bwr.write_buffer = 0;readbuf[0] = BC_ENTER_LOOPER; // 读写要处理的命令binder_write(bs, readbuf, sizeof(uint32_t)); // 设置线程的 looper状态为循环状态for (;;) {bwr.read_size = sizeof(readbuf);bwr.read_consumed = 0;bwr.read_buffer = (uintptr_t) readbuf;/* 不断地 binder读数据,没有数据会进入休眠状态 */res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);if (res < 0) {ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));break;}res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);if (res == 0) {ALOGE("binder_loop: unexpected reply?!\n");break;}if (res < 0) {ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));break;}}
}

发现没,for循环中就是将结构体read的参数设置为非空,然后调用ioctl(也就是kernel中的binder_ioctl)携带着BINDER_WRITE_READ指令,处理BINDER_WRITE_READ指令时,接下来调用binder_ioctl_write_read函数,在binder_ioctl_write_read函数中由于这次read参数部位空,所以调用binder_thread_read函数,接下来再分析一下binder_thread_read函数:

// kernel/drivers/staging/android/binder.cstatic int binder_thread_read(struct binder_proc *proc,struct binder_thread *thread,binder_uintptr_t binder_buffer, size_t size,binder_size_t *consumed, int non_block)
{void __user *buffer = (void __user *)(uintptr_t)binder_buffer;void __user *ptr = buffer + *consumed;void __user *end = buffer + size;int ret = 0;int wait_for_proc_work;// 设置命令为 BR_NOOPif (*consumed == 0) {// 这个ptr并不是只能存放一个指令,而是一个队列,可以存放很多指令,遵循先进先出的操作if (put_user(BR_NOOP, (uint32_t __user *)ptr))return -EFAULT;ptr += sizeof(uint32_t);}retry:// wait_for_proc_work 为 truewait_for_proc_work = thread->transaction_stack == NULL &&list_empty(&thread->todo);if (thread->return_error != BR_OK && ptr < end) {if (thread->return_error2 != BR_OK) {if (put_user(thread->return_error2, (uint32_t __user *)ptr))return -EFAULT;ptr += sizeof(uint32_t);binder_stat_br(proc, thread, thread->return_error2);if (ptr == end)goto done;thread->return_error2 = BR_OK;}if (put_user(thread->return_error, (uint32_t __user *)ptr))return -EFAULT;ptr += sizeof(uint32_t);binder_stat_br(proc, thread, thread->return_error);thread->return_error = BR_OK;goto done;}// 准备就绪的线程个数加 1thread->looper |= BINDER_LOOPER_STATE_WAITING;if (wait_for_proc_work)proc->ready_threads++;binder_unlock(__func__);trace_binder_wait_for_work(wait_for_proc_work,!!thread->transaction_stack,!list_empty(&thread->todo));if (wait_for_proc_work) {if (!(thread->looper & (BINDER_LOOPER_STATE_REGISTERED |BINDER_LOOPER_STATE_ENTERED))) {binder_user_error("%d:%d ERROR: Thread waiting for process work before calling BC_REGISTER_LOOPER or BC_ENTER_LOOPER (state %x)\n",proc->pid, thread->pid, thread->looper);wait_event_interruptible(binder_user_error_wait,binder_stop_on_user_error < 2);}binder_set_nice(proc->default_priority);if (non_block) {// 非阻塞操作,service_manager是阻塞的,所以 if不命中if (!binder_has_proc_work(proc, thread))ret = -EAGAIN;} else // 进入 else,开始等待ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));} else {if (non_block) {if (!binder_has_thread_work(thread))ret = -EAGAIN;} elseret = wait_event_freezable(thread->wait, binder_has_thread_work(thread));}// 省略代码......
}

 执行wait_event_freezable_exclusive后,最终会进入等待状态。也就是说到此时SM已经准备就绪等待客户端的调用。

整个启动SM的代码流程总结一下:

2.2 如何获取service_manager服务

获取Service Manager是通过defaultServiceManager()方法来完成。

// frameworks/native/libs/binder/IServiceManager.cppsp<IServiceManager> defaultServiceManager()
{/* 单例模式,如果不为空直接返回 */if (gDefaultServiceManager != NULL) return gDefaultServiceManager;{AutoMutex _l(gDefaultServiceManagerLock);/* 创建或者获取 SM时,SM可能未准备就绪,这时通过 sleep 1秒后,循环尝试获取直到成功*/while (gDefaultServiceManager == NULL) {/* 分为三块分析 */gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL));if (gDefaultServiceManager == NULL)sleep(1);}}return gDefaultServiceManager;
}

首先该方法中会有一个单例的判定,如果没有获取过,就会通过循环获取的方式获取到对应的SM实例。那么继续分析这个gDefaultServiceManager是如何获取的,主要分为2个操作

  1. ProcessState::self()->getContextObject(NULL)
  2. interface_cast

2.2.1 ProcessState::self()->getContextObject(NULL)

对于这个函数操作,我们可以先分开来看,先看ProcessState::self()这一部分,然后再看getContextObject(NULL)另一部分。

2.2.1.1 ProcessState::self()
// frameworks/native/libs/binder/ProcessState.cpp#define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))sp<ProcessState> ProcessState::self()
{Mutex::Autolock _l(gProcessMutex);/* 单例模式 */if (gProcess != NULL) {return gProcess;}gProcess = new ProcessState;// 实例化 ProcessStatereturn gProcess;
}ProcessState::ProcessState(): mDriverFD(open_driver()), mVMStart(MAP_FAILED), mThreadCountLock(PTHREAD_MUTEX_INITIALIZER), mThreadCountDecrement(PTHREAD_COND_INITIALIZER), mExecutingThreadsCount(0), mMaxThreads(DEFAULT_MAX_BINDER_THREADS), mManagesContexts(false), mBinderContextCheckFunc(NULL), mBinderContextUserData(NULL), mThreadPoolStarted(false), mThreadPoolSeq(1)
{if (mDriverFD >= 0) {// XXX Ideally, there should be a specific define for whether we// have mmap (or whether we could possibly have the kernel module// availabla).
#if !defined(HAVE_WIN32_IPC)// mmap the binder, providing a chunk of virtual address space to receive transactions.// 采用内存映射函数 mmap,给 binder分配一块大小为 (1M-8K)的虚拟地址空间,用来接收事务mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);if (mVMStart == MAP_FAILED) {// *sigh*ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");close(mDriverFD);mDriverFD = -1;}
#elsemDriverFD = -1;
#endif}LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened.  Terminating.");
}

ProcessState在初始化的时候首先会调用open_driver,去打开驱动。

2.2.1.1.1 open_driver
// frameworks/native/libs/binder/ProcessState.cpp#define DEFAULT_MAX_BINDER_THREADS 15 // Binder线程池最大线程数15个static int open_driver()
{// 打开 /dev/binder设备,建立与内核的 Binder驱动的交互通道int fd = open("/dev/binder", O_RDWR);if (fd >= 0) {fcntl(fd, F_SETFD, FD_CLOEXEC);int vers = 0;status_t result = ioctl(fd, BINDER_VERSION, &vers);if (result == -1) {ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));close(fd);fd = -1;}if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {ALOGE("Binder driver protocol does not match user space protocol!");close(fd);fd = -1;}// 通过 ioctl设置 binder驱动,能支持的最大线程数size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);if (result == -1) {ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));}} else {ALOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));}return fd;
}

打开驱动主要做了2件事,打开binder驱动,然后设置binder线程池的最大线程数为15个。打开驱动完成之后,再回到ProcessState中,在ProcessState中通过mmap设置共享内存,共享内存的大小为1M-8K(普通服务的大小)。到这里ProcessState::self()就完成了。再看一下getContextObject的操作

2.2.1.1.2 getContextObject
// frameworks/native/libs/binder/ProcessState.cppsp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{// 参数为0,获取service_manager服务return getStrongProxyForHandle(0);
}sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{sp<IBinder> result;AutoMutex _l(mLock);// 查找 handle对应的资源项handle_entry* e = lookupHandleLocked(handle);if (e != NULL) {// We need to create a new BpBinder if there isn't currently one, OR we// are unable to acquire a weak reference on this current one.  See comment// in getWeakProxyForHandle() for more info about this.IBinder* b = e->binder;// 当handle值所对应的IBinder不存在或弱引用无效时if (b == NULL || !e->refs->attemptIncWeak(this)) {if (handle == 0) {// Special case for context manager...// The context manager is the only object for which we create// a BpBinder proxy without already holding a reference.// Perform a dummy transaction to ensure the context manager// is registered before we create the first local reference// to it (which will occur when creating the BpBinder).// If a local reference is created for the BpBinder when the// context manager is not present, the driver will fail to// provide a reference to the context manager, but the// driver API does not return status.//// Note that this is not race-free if the context manager// dies while this code runs.//// TODO: add a driver API to wait for context manager, or// stop special casing handle 0 for context manager and add// a driver API to get a handle to the context manager with// proper reference counting.Parcel data;// 通过ping操作测试binder是否准备就绪status_t status = IPCThreadState::self()->transact(0, IBinder::PING_TRANSACTION, data, NULL, 0);if (status == DEAD_OBJECT)return NULL;}// 创建BpBinder对象b = new BpBinder(handle); e->binder = b;if (b) e->refs = b->getWeakRefs();result = b;} else {// This little bit of nastyness is to allow us to add a primary// reference to the remote proxy when this team doesn't have one// but another team is sending the handle to us.result.force_set(b);e->refs->decWeak(this);}}return result;
}

这个函数最重要的就是通过handle创建了BpBinder对象。这个BpBinder对于整个Binder来说都是灵魂般的存在,客户端获取Binder拿到的最终都是这个BpBinder的对象。简单看一下BpBinder的实现:

// frameworks/native/libs/binder/BpBinder.cppBpBinder::BpBinder(int32_t handle): mHandle(handle), mAlive(1), mObitsSent(0), mObituaries(NULL)
{ALOGV("Creating BpBinder %p handle %d\n", this, mHandle);/* 支持强弱引用计数,OBJECT_LIFETIME_WEAK表示目标对象的生命周期受弱指针控制 */extendObjectLifetime(OBJECT_LIFETIME_WEAK);/* handle所对应的 bindle弱引用 + 1 */IPCThreadState::self()->incWeakHandle(handle);
}

到此处我们就清楚了,ProcessState::self()->getContextObject(NULL)最终就是获取到了BpBinder的对象。

题外话:BpBinder其实就SM Binder的代理,无论是Java层还是Native层想要跨进程通信,最终都是通过BpBinder实现的,简单介绍一下获取SM的方式的区别:

各层的对应类:

这里就是题外话的插一嘴,言归正传。

回归到流程上来,将BpBinder的对象传递给了interface_cast函数,那自然接下里就分析interface_cast函数:

2.2.2 interface_cast

// frameworks/native/include/binder/IInterface.htemplate<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{// 等价于:IServiceManager::asInterfacereturn INTERFACE::asInterface(obj);
}
2.2.2.1 IServiceManager::asInterface

对于asInterface()函数,通过搜索代码,你会发现根本找不到这个方法是在哪里定义这个函数的, 其实是 通过模板函数来定义的。

// frameworks/native/include/binder/IInterface.h#define DECLARE_META_INTERFACE(INTERFACE)                               \static const android::String16 descriptor;                          \static android::sp<I##INTERFACE> asInterface(                       \const android::sp<android::IBinder>& obj);                  \virtual const android::String16& getInterfaceDescriptor() const;    \I##INTERFACE();                                                     \virtual ~I##INTERFACE();                                            \#define 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 != NULL) {                                              \intr = static_cast<I##INTERFACE*>(                          \obj->queryLocalInterface(                               \I##INTERFACE::descriptor).get());               \if (intr == NULL) {                                         \intr = new Bp##INTERFACE(obj);                          \}                                                           \}                                                               \return intr;                                                    \}                                                                   \I##INTERFACE::I##INTERFACE() { }                                    \I##INTERFACE::~I##INTERFACE() { }                                   \

这个宏定义巨不好阅读,需要将宏定义替换回去,将上面2个宏替换后然后展开看一下具体的实现:

2.2.2.1.1 DECLARE_META_INTERFACE
// frameworks/native/include/binder/IServiceManager.hDECLARE_META_INTERFACE(ServiceManager)static const android::String16 descriptor;
static android::sp< IServiceManager > asInterface(const 
android::sp<android::IBinder>& obj)
virtual const android::String16& getInterfaceDescriptor() const;
IServiceManager ();
virtual ~IServiceManager();

该过程主要是声明asInterface(),getInterfaceDescriptor()方法。没什么实际意义。接着看下面的实现:

2.2.2.1.2 IMPLEMENT_META_INTERFACE
// frameworks/native/libs/binder/IServiceManager.cpp// 185
IMPLEMENT_META_INTERFACE(ServiceManager,"android.os.IServiceManager")const android::String16 IServiceManager::descriptor(“android.os.IServiceManager”);
const android::String16& IServiceManager::getInterfaceDescriptor() const
{return IServiceManager::descriptor;
}android::sp<IServiceManager> IServiceManager::asInterface(const android::sp<android::IBinder>& obj)
{android::sp<IServiceManager> intr;if(obj != NULL) {intr = static_cast<IServiceManager *>(obj->queryLocalInterface(IServiceManager::descriptor).get());if (intr == NULL) {// 等价于 new BpServiceManager(BpBinder)intr = new BpServiceManager(obj);}}return intr;
}
IServiceManager::IServiceManager () { }
IServiceManager::~ IServiceManager() { }

到这里我们就清楚了,转了这么一大圈,合着到最后interface_cast返回的就是BpServiceManager的对象,这个BpServiceManager中持有了BpBinder的引用。到这里我们就清楚了interface_cast就是创建了BpServiceManager对象,并且在BpServiceManager中使用了BpBinder的对象。再继续深耕一点,看一下BpBinder是如何在BpServiceManager被使用的:

2.2.2.2 BpServiceManager
// frameworks/native/libs/binder/IServiceManager.cppclass BpServiceManager : public BpInterface<IServiceManager>
{
public:BpServiceManager(const sp<IBinder>& impl): BpInterface<IServiceManager>(impl){}// 省略代码......
}

BpServiceManager 是一个内部类,这里的参数impl就是上面创建的BpBinder对象,那接下里看一下BpInterface中如何调用BpBinder:

// frameworks/native/include/binder/IInterface.htemplate<typename INTERFACE>
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote): BpRefBase(remote)
{
}

继续看BpRefBase中如何使用remote,也就是BpBinder。

// frameworks/native/libs/binder/Binder.cpp// mRemote指向 new BpBinder(0),从而 BpServiceManager能够利用 Binder进行通过通信
BpRefBase::BpRefBase(const sp<IBinder>& o): mRemote(o.get()), mRefs(NULL), mState(0)
{extendObjectLifetime(OBJECT_LIFETIME_WEAK);if (mRemote) {mRemote->incStrong(this);           // Removed on first IncStrong().mRefs = mRemote->createWeak(this);  // Held for our entire lifetime.}
}

到这里我们就清楚了,其实mRemote最终还是调用BpBinder的transact函数。

总结:

1. ProcessState::self()->getContextObject(NULL)
   1. ProcessState::self()
      1. 打开驱动:binder
      2. 设置线程最大数目:15个
      3. mmap  -- 设置共享内存大小 --- (1M-8K) 普通服务的大小
   2. getContextObject
      1. 创建一个BpBinder --- 客户端的对象
2. interface_cast
   1. new BpServiceManager(new BpBinder) ==》 new Proxy(binder==BinderProxy)
   2. remote.transact -->远程调用  
   3. remote == BpBinder

补充:
3. java 层 --- ServiceManager.addService
   1. new ServiceManagerProxy(new BinderProxy)
   2. mRemote == BinderProxy
   3. BinderProxy.mObject == BpBinder
   4. mRemote.transact == BpBinder.transact

2.3 详解AIDL生成Java

上面我们分析了Binder的实现,说到底Binder就是一套通信机制,如果想要使用Binder,那么就需要符合他这套机制,那AIDL就是帮助我们去适配这套机制的。说起来很空洞,直接上代码:

要使用Binder那肯定就是C/S结构的,也就是所说的客户端和服务端2侧:

先定义一个Person 数据类

public class Person implements Parcelable {private String name;private int grade;public Person(String name, int grade) {this.name = name;this.grade = grade;}protected Person(Parcel in) {this.name = in.readString();this.grade = in.readInt();}public static final Creator<Person> CREATOR = new Creator<Person>() {@Overridepublic Person createFromParcel(Parcel in) {return new Person(in);}@Overridepublic Person[] newArray(int size) {return new Person[size];}};@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeString(name);dest.writeInt(grade);}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", grade=" + grade +'}';}
}

客户端:

public class ClientActivity extends AppCompatActivity {private IPersonManager iPersonManager;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Intent intent = new Intent(this, RemoteService.class);intent.setAction("com.enjoy.binder");// bindService的流程最终会创建binderProxy对象,通过ServiceConnection的onServiceConnected 的参数IBinder service返回,然后将service封装进SMProxybindService(intent, connection, Context.BIND_AUTO_CREATE);findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {try {Log.e(TAG, "------------onClick:" + Thread.currentThread());iPersonManager.addPerson(new Person(TAG, 3));List<Person> persons = iPersonManager.getPersonList();Log.e(TAG, persons.toString() + "," + Thread.currentThread());} catch (RemoteException e) {e.printStackTrace();}}});}private ServiceConnection connection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {Log.e(TAG, "onServiceConnected: success");iPersonManager = Stub.asInterface(service);// proxy}@Overridepublic void onServiceDisconnected(ComponentName name) {Log.e(TAG, "onServiceDisconnected: success");iPersonManager = null;}};
}

服务端:

public class RemoteService extends Service {private ArrayList<Person> persons;@Nullable@Overridepublic IBinder onBind(Intent intent) {persons = new ArrayList<>();Log.e(TAG, "success onBind");return iBinder;}private IBinder iBinder = new Stub() {@Overridepublic void addPerson(Person person) throws RemoteException {persons.add(person);}@Overridepublic List<Person> getPersonList() throws RemoteException {return persons;}};
}

AIDL的实现类:

public interface IPersonManager extends IInterface {void addPerson(Person person) throws RemoteException;List<Person> getPersonList() throws RemoteException;
}
public class Proxy implements IPersonManager {private static final String DESCRIPTOR = "com.enjoy.binder.common.IPersonManager";private IBinder mRemote;public Proxy(IBinder remote) {mRemote = remote;}@Overridepublic void addPerson(Person person) throws RemoteException {Parcel data = Parcel.obtain();Parcel reply = Parcel.obtain();try {data.writeInterfaceToken(DESCRIPTOR);if ((person != null)) {data.writeInt(1);person.writeToParcel(data, 0);} else {data.writeInt(0);}Log.e(TAG, "Proxy,addPerson: " + Thread.currentThread());mRemote.transact(Stub.TRANSACTION_addPerson, data, reply, 0);reply.readException();} finally {reply.recycle();data.recycle();}}@Overridepublic List<Person> getPersonList() throws RemoteException {Parcel data = Parcel.obtain();Parcel reply = Parcel.obtain();List<Person> result;try {data.writeInterfaceToken(DESCRIPTOR);mRemote.transact(Stub.TRANSACTION_getPersonList, data, reply, 0);reply.readException();result = reply.createTypedArrayList(Person.CREATOR);} finally {reply.recycle();data.recycle();}return result;}@Overridepublic IBinder asBinder() {return mRemote;}
}
public abstract class Stub extends Binder implements IPersonManager {private static final String DESCRIPTOR = "com.enjoy.binder.common.IPersonManager";public Stub() {this.attachInterface(this, DESCRIPTOR);}public static IPersonManager asInterface(IBinder binder) {if ((binder == null)) {return null;}IInterface iin = binder.queryLocalInterface(DESCRIPTOR);if ((iin != null) && (iin instanceof IPersonManager)) {return (IPersonManager) iin;}return new Proxy(binder);}@Overridepublic IBinder asBinder() {return this;}@Overrideprotected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {switch (code) {case INTERFACE_TRANSACTION:reply.writeString(DESCRIPTOR);return true;case TRANSACTION_addPerson:Log.e(TAG, "Stub,TRANSACTION_addPerson: " + Thread.currentThread());data.enforceInterface(DESCRIPTOR);Person arg0 = null;if ((0 != data.readInt())) {arg0 = Person.CREATOR.createFromParcel(data);}this.addPerson(arg0);reply.writeNoException();return true;case TRANSACTION_getPersonList:data.enforceInterface(DESCRIPTOR);List<Person> result = this.getPersonList();reply.writeNoException();reply.writeTypedList(result);return true;}return super.onTransact(code, data, reply, flags);}static final int TRANSACTION_addPerson = IBinder.FIRST_CALL_TRANSACTION;static final int TRANSACTION_getPersonList = IBinder.FIRST_CALL_TRANSACTION + 1;
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.enjoy.binder"><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme"><activity android:name=".client.ClientActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><serviceandroid:name=".server.RemoteService"android:exported="true"android:process=":remote"><intent-filter><action android:name="com.enjoy.binder" /><category android:name="android.intent.category.DEFAULT" /></intent-filter></service></application></manifest>

代码罗列到这里,是不是感觉跟我们平时使用AIDL不一样啊,是的,没错,这里手动实现了AIDL要帮我们做的一些事情。

在AndroidManifest.xml文件中定义了服务端和客户端在不同的进程中:android:process=":remote"。所以客户端要访问服务端,就是跨进程的。

那么如何实现客户端和服务端的跨进程通信呢?类比一下我们普通的类与类之间的调用,比较规范的话一般都要先定义接口,那么我们也先定一个接口类:IPersonManager 继承了IInterface接口。

上面的stub类就可以理解为AMS,一个Binder类,其中asInterface函数的作用:

// public abstract class Stub extends Binder implements IPersonManagerpublic static IPersonManager asInterface(IBinder binder) {if ((binder == null)) {return null;}IInterface iin = binder.queryLocalInterface(DESCRIPTOR);if ((iin != null) && (iin instanceof IPersonManager)) {return (IPersonManager) iin;}return new Proxy(binder);
}

就是区别客户端与服务端是否在一个进程。如果是同进程的话,就不需要使用binderProxy了。从源码中分析:

// android/os/Binder.java#BinderProxyfinal class BinderProxy implements IBinder {public native boolean pingBinder();public native boolean isBinderAlive();// 如果是跨进程的BinderProxy,那么queryLocalInterface返回为nullpublic IInterface queryLocalInterface(String descriptor) {return null;}// 省略代码....
}

所以如果是跨进程的BinderProxy,那么queryLocalInterface返回为null,那么asInterface返回的就是new Proxy(binder)。new Proxy(binder)就可以理解为ServiceManagerProxy。那就有疑问了,

// public class ClientActivity extends AppCompatActivityprivate ServiceConnection connection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {Log.e(TAG, "onServiceConnected: success");iPersonManager = Stub.asInterface(service);// proxy}@Overridepublic void onServiceDisconnected(ComponentName name) {Log.e(TAG, "onServiceDisconnected: success");iPersonManager = null;}
};

ServiceConnection中的回调方法的onServiceConnected参数IBinder service(也就是BinderProxy)是谁传过来的呢?其实答案很简单就是bindService(详细的可以参考bindService的流程)成功后传入进来的,也就是说bindService的回调结果最重要的就是这个IBinder。

那拿到了new Proxy(binder)(也就是ServiceManagerProxy)的对象之后,调用对应的方法,可以分析出,最终调用的就是BinderProxy的transact(调用transact调用后,当前线程就会挂起):

说穿了AIDL其实很简单,AIDL就是客户端的一层封装,为了调用服务对外的接口,所以才需要AIDL的封装,因为BinderProxy的对象中是不包含用户想要的接口的。但是AIDL最终跨进程还是通过BinderProxy实现。AIDL就是一个自助工具,帮助自动实现对应的stub和proxy等类,也就是说他按照binder需要的流程,自动生成了Client环节中需要的所有类,然后使用者使用这些类机械的调用即可。

调用了transact之后,就会调用到Stub中的onTransact函数,这个函数中就会根据proxy传过来的方法标识数调用对应的方法:

从此就进入了我们的service中的方法,也就完成了跨进程的调用。

总结:AIDL-类似黄牛,中介
1.asInterface封装BinderProxy
2.data与reply封装
3.transact-挂起
4.onTransact-调用服务实现方法
 

3 服务的注册与获取(从Java层开始)

将以AMS为例,分析如何将服务注册到SM中。先简答看一下AMS的创建过程:

// frameworks/base/services/java/com/android/server/SystemServer.java/*** The main entry point from zygote.*/
public static void main(String[] args) {new SystemServer().run();
}private void run() {// 省略代码......// Start services.try {// 启动引导服务,将会创建AMS服务startBootstrapServices();startCoreServices();startOtherServices();} catch (Throwable ex) {Slog.e("System", "******************************************");Slog.e("System", "************ Failure starting system services", ex);throw ex;}// 省略代码......
}private void startBootstrapServices() {// 省略代码......// Activity manager runs the show. // 创建AMSmActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService();// 省略代码......// Set up the Application instance for the system process and get started.mActivityManagerService.setSystemProcess();// 省略代码......
}
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.
javapublic void setSystemProcess() {try {// 将AMS添加到SMServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);ServiceManager.addService("meminfo", new MemBinder(this));ServiceManager.addService("gfxinfo", new GraphicsBinder(this));ServiceManager.addService("dbinfo", new DbBinder(this));if (MONITOR_CPU_USAGE) {ServiceManager.addService("cpuinfo", new CpuBinder(this));}ServiceManager.addService("permission", new PermissionController(this));ServiceManager.addService("processinfo", new ProcessInfoService(this));ApplicationInfo info = mContext.getPackageManager().getApplicationInfo("android", STOCK_PM_FLAGS);mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());synchronized (this) {ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);app.persistent = true;app.pid = MY_PID;app.maxAdj = ProcessList.SYSTEM_ADJ;app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);synchronized (mPidsSelfLocked) {mPidsSelfLocked.put(app.pid, app);}updateLruProcessLocked(app, false, null);updateOomAdjLocked();}} catch (PackageManager.NameNotFoundException e) {throw new RuntimeException("Unable to find android system package", e);}
}

通过上面的流程,AMS服务在setSystemProcess中添加到了SM中,那就重点看一下这个addService是如何添加服务到SM中。

3.1 addService流程

先来一张整体流程图:

// frameworks/base/core/java/android/os/ServiceManager.java/*** Place a new @a service called @a name into the service* manager.* * @param name the name of the new service* @param service the service object* @param allowIsolated set to true to allow isolated sandboxed processes* to access this service*/
public static void addService(String name, IBinder service, boolean allowIsolated) {try {getIServiceManager().addService(name, service, allowIsolated);} catch (RemoteException e) {Log.e(TAG, "error in addService", e);}
}

这里主要有2个部分,第一个部分就是getIServiceManager(),第二个部分就是addService。要特别留意的是参数IBinder service就是AMS,这里先记住,接下来分别看一下这2个部分:

3.1.1 getIServiceManager()获取携带了BinderProxy的ServiceManagerProxy对象

// frameworks/base/core/java/android/os/ServiceManager.javaprivate static IServiceManager getIServiceManager() {/* 采用单例形式返回 ServiceManagerProxy对象 */if (sServiceManager != null) {return sServiceManager;}// 相当于 new ServiceManagerProxy(new BinderProxy); ---见后面小节(分别分析 asInterface和 getContextObject)// Find the service managersServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());return sServiceManager;
}

这个代码实现很简单,首先就是一个单例控制。如果没有初始化过sServiceManager,那么在此处将会初始化sServiceManager 对象。初始化sServiceManager 又分为2个部分,第一个部分参数:BinderInternal.getContextObject(),第二个部分ServiceManagerNative.asInterface。那就具体看一下这2个部分:

3.1.1.1 BinderInternal.getContextObject()获取BinderProxy对象
// frameworks/base/core/java/com/android/internal/os/BinderInternal.java/*** Return the global "context object" of the system.  This is usually* an implementation of IServiceManager, which you can use to find* other services.*/
public static final native IBinder getContextObject();

直接看Native中的代码:

// frameworks/base/core/jni/android_util_Binder.cppstatic jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{/* 打开 binder驱动(ProcessState是单例的),创建 BpBinder(handle) 对象,并返回 */sp<IBinder> b = ProcessState::self()->getContextObject(NULL);return javaObjectForIBinder(env, b);
}

ProcessState::self()->getContextObject(NULL);这个的实现上面已经介绍过了,就是创建了BpBinder的对象。

// frameworks/base/core/jni/android_util_Binder.cppjobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{if (val == NULL) return NULL;if (val->checkSubclass(&gBinderOffsets)) {// One of our own!jobject object = static_cast<JavaBBinder*>(val.get())->object();LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);return object;}// For the rest of the function we will hold this lock, to serialize// looking/creation of Java proxies for native Binder proxies.AutoMutex _l(mProxyLock);// 从 BpBinder中查找 BinderProxy对象,第一次为 null// Someone else's...  do we know about it?jobject object = (jobject)val->findObject(&gBinderProxyOffsets);if (object != NULL) {jobject res = jniGetReferent(env, object);if (res != NULL) {ALOGV("objectForBinder %p: found existing %p!\n", val.get(), res);return res;}LOGDEATH("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get());android_atomic_dec(&gNumProxyRefs);val->detachObject(&gBinderProxyOffsets);env->DeleteGlobalRef(object);}// 创建 BinderProxy对象object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);if (object != NULL) {LOGDEATH("objectForBinder %p: created new proxy %p !\n", val.get(), object);// BinderProxy.mObject成员变量记录 BpBinder对象// The proxy holds a reference to the native object.env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());val->incStrong((void*)javaObjectForIBinder);// The native object needs to hold a weak reference back to the// proxy, so we can retrieve the same proxy if it is still active.jobject refObject = env->NewGlobalRef(env->GetObjectField(object, gBinderProxyOffsets.mSelf));// 将 BinderProxy对象信息添加到 BpBinder的成员变量 mObjects中val->attachObject(&gBinderProxyOffsets, refObject,jnienv_to_javavm(env), proxy_cleanup);// Also remember the death recipients registered on this proxysp<DeathRecipientList> drl = new DeathRecipientList;drl->incStrong((void*)javaObjectForIBinder);// BinderProxy.mOrgue成员变量记录死亡通知对象env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get()));// Note that a new object reference has been created.android_atomic_inc(&gNumProxyRefs);incRefsCreated(env);}return object;
}

javaObjectForIBinder首先就是创建BinderProxy对象,然后就是将BpBinder与BinderProxy进行一个互相绑定,并且返回BinderProxy对象。到这里BinderProxy与BpBinder就是你中有我我中有你,相互的绑定。

那也就是说BinderInternal.getContextObject()的目的就是获取BinderProxy对象。并且将BinderProxy作为参数传递给ServiceManagerNative.asInterface。继续分析ServiceManagerNative.asInterface。

3.1.1.2 ServiceManagerNative.asInterface创建ServiceManagerProxy(BinderProxy)对象
// frameworks/base/core/java/android/os/ServiceManagerNative.java/*** Cast a Binder object into a service manager interface, generating* a proxy if needed.*/
static public IServiceManager asInterface(IBinder obj)
{if (obj == null) {return null;}// 因为 obj为 BinderProxy,默认返回 null(具体逻辑前面章节也已经分析过)IServiceManager in =(IServiceManager)obj.queryLocalInterface(descriptor);if (in != null) {return in;}// 创建ServiceManagerProxy对象,并且将BinderProxy作为参数传递进去。return new ServiceManagerProxy(obj);
}

ServiceManagerNative.asInterface就是创建ServiceManagerProxy对象,并且使用ServiceManagerProxy对象并且内部携带了BinderProxy对象。

// frameworks/base/core/java/android/os/ServiceManagerNative.java$ServiceManagerProxy.javaclass ServiceManagerProxy implements IServiceManager {// mRemote为 BinderProxy对象public ServiceManagerProxy(IBinder remote) {mRemote = remote;}public IBinder asBinder() {return mRemote;}// 省略代码......
}

到这里就清楚getIServiceManager()就是获取携带了BinderProxy的ServiceManagerProxy对象。接下来就是分析addService()。

总结:

3.1.2 addService(ServiceManagerProxy.addService())

// frameworks/base/core/java/android/os/ServiceManagerNative.java$ServiceManagerProxy.javaclass ServiceManagerProxy implements IServiceManager {public ServiceManagerProxy(IBinder remote) {mRemote = remote;}public IBinder asBinder() {return mRemote;}// 省略代码......public void addService(String name, IBinder service, boolean allowIsolated)throws RemoteException {Parcel data = Parcel.obtain();Parcel reply = Parcel.obtain();data.writeInterfaceToken(IServiceManager.descriptor);data.writeString(name);// 此处 service == AMSdata.writeStrongBinder(service);data.writeInt(allowIsolated ? 1 : 0);mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);reply.recycle();data.recycle();}// 省略代码......
}

addService中有2各部分比较重要,一个是data.writeStrongBinder(service),这里的service就是AMS。另一个就是mRemote.transact,跨进程调用的实现。

3.1.2.1 data.writeStrongBinder(service)将服务(例如AMS)写到Parcel data中
// frameworks/base/core/java/android/os/Parcel.java/*** Write an object into the parcel at the current dataPosition(),* growing dataCapacity() if needed.*/
public final void writeStrongBinder(IBinder val) {// val就是AMSnativeWriteStrongBinder(mNativePtr, val);
}private static native void nativeWriteStrongBinder(long nativePtr, IBinder val);
// frameworks/base/core/jni/android_os_Parcel.cpp{"nativeWriteStrongBinder",   "(JLandroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder},static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
{// 将java层 Parcel转换为 native层 ParcelParcel* parcel = reinterpret_cast<Parcel*>(nativePtr);if (parcel != NULL) {// ---见后面小节(分别分析 ibinderForJavaObject和 writeStrongBinder)const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));if (err != NO_ERROR) {signalExceptionForError(env, clazz, err);}}
}

很明显,此处又是一个分叉,第一个分叉ibinderForJavaObject(env, object),第二个分叉writeStrongBinder,先看参数ibinderForJavaObject(env, object)。

3.1.2.1.1 ibinderForJavaObject(env, object)获取JavaBBinder对象
// frameworks/base/core/jni/android_util_Binder.cppsp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{if (obj == NULL) return NULL;if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {// 是否是 Java层的 Binder对象,此处是 AMS,if命中JavaBBinderHolder* jbh = (JavaBBinderHolder*)env->GetLongField(obj, gBinderOffsets.mObject);return jbh != NULL ? jbh->get(env, obj) : NULL; // 返回 JavaBBinder对象}if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {return (IBinder*)env->GetLongField(obj, gBinderProxyOffsets.mObject);}ALOGW("ibinderForJavaObject: %p is not a Binder object", obj);return NULL;
}

分析一下返回值JavaBBinderHolder.get

// frameworks/base/core/jni/android_util_Binder.cpp$JavaBBinderHolder.cppclass JavaBBinderHolder : public RefBase
{
public:sp<JavaBBinder> get(JNIEnv* env, jobject obj){AutoMutex _l(mLock);sp<JavaBBinder> b = mBinder.promote();// 将弱指针升级为强指针,首次进来返回空指针if (b == NULL) {b = new JavaBBinder(env, obj); // 创建一个 JavaBBinder 对象并返回mBinder = b;ALOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%" PRId32 "\n",b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount());}return b;}sp<JavaBBinder> getExisting(){AutoMutex _l(mLock);return mBinder.promote();}private:Mutex           mLock;wp<JavaBBinder> mBinder;
};

也就是说ibinderForJavaObject返回的是BBinder。也就是说writeStrongBinder的参数是 JavaBBinder对象。

记住:writeStrongBinder的参数是 JavaBBinder对象。

3.1.2.1.2 writeStrongBinder
// frameworks/native/libs/binder/Parcel.cppstatus_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{return flatten_binder(ProcessState::self(), val, this);
}

这没有什么可分析的直接分析flatten_binder:

// frameworks/native/libs/binder/Parcel.cppstatus_t flatten_binder(const sp<ProcessState>& /*proc*/,const sp<IBinder>& binder, Parcel* out)
{flat_binder_object obj;obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;if (binder != NULL) {// 当前进程有 Binder,所以本地 Binder不为空IBinder *local = binder->localBinder();if (!local) {BpBinder *proxy = binder->remoteBinder();if (proxy == NULL) {ALOGE("null proxy");}const int32_t handle = proxy ? proxy->handle() : 0;// Binder对象扁平化,转换成 flat_binder_object对象obj.type = BINDER_TYPE_HANDLE;obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */obj.handle = handle;obj.cookie = 0;} else {obj.type = BINDER_TYPE_BINDER;obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());obj.cookie = reinterpret_cast<uintptr_t>(local);}} else {obj.type = BINDER_TYPE_BINDER;obj.binder = 0;obj.cookie = 0;}return finish_flatten_binder(binder, obj, out);
}

继续跟踪流程finish_flatten_binder函数

// frameworks/native/libs/binder/Parcel.cppinline static status_t finish_flatten_binder(const sp<IBinder>& /*binder*/, const flat_binder_object& flat, Parcel* out)
{// 将 flat_binder_object写入 outreturn out->writeObject(flat, false);
}

结果很清晰也很简单就是将服务(例如AMS)写到Parcel data中。继续分析addService的第二个部分transact函数

3.1.2.2 mRemote.transact
// frameworks/base/core/java/android/os/ServiceManagerNative.java$ServiceManagerProxy.javapublic void addService(String name, IBinder service, boolean allowIsolated)throws RemoteException {Parcel data = Parcel.obtain();Parcel reply = Parcel.obtain();data.writeInterfaceToken(IServiceManager.descriptor);data.writeString(name);data.writeStrongBinder(service);data.writeInt(allowIsolated ? 1 : 0);// mRemote为 BinderProxy对象mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);reply.recycle();data.recycle();
}

上面也介绍了mRemote为 BinderProxy对象。

// frameworks/base/core/java/android/os/Binder.java$BinderProxy.javapublic boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");return transactNative(code, data, reply, flags);
}public native boolean transactNative(int code, Parcel data, Parcel reply, int flags) throws RemoteException;{"transactNative",      "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},

老样子进入Native层:

// frameworks/base/core/jni/android_util_Binder.cppstatic jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{if (dataObj == NULL) {jniThrowNullPointerException(env, NULL);return JNI_FALSE;}// 获取 data对象Parcel* data = parcelForJavaObject(env, dataObj);if (data == NULL) {return JNI_FALSE;}// 获取 reply对象Parcel* reply = parcelForJavaObject(env, replyObj);if (reply == NULL && replyObj != NULL) {return JNI_FALSE;}// 获取 BpBinder 对象IBinder* target = (IBinder*)env->GetLongField(obj, gBinderProxyOffsets.mObject);if (target == NULL) {jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");return JNI_FALSE;}ALOGV("Java code calling transact on %p in Java object %p with code %" PRId32 "\n",target, obj, code);bool time_binder_calls;int64_t start_millis;if (kEnableBinderSample) {// Only log the binder call duration for things on the Java-level main thread.// But if we don'ttime_binder_calls = should_time_binder_calls();if (time_binder_calls) {start_millis = uptimeMillis();}}//printf("Transact from Java code to %p sending: ", target); data->print();// 调用BpBinder transactstatus_t err = target->transact(code, *data, reply, flags);//if (reply) printf("Transact from Java code to %p received: ", target); reply->print();if (kEnableBinderSample) {if (time_binder_calls) {conditionally_log_binder_call(start_millis, target, code);}}if (err == NO_ERROR) {return JNI_TRUE;} else if (err == UNKNOWN_TRANSACTION) {return JNI_FALSE;}signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/, data->dataSize());return JNI_FALSE;
}
// frameworks/native/libs/binder/BpBinder.cppstatus_t BpBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{// Once a binder has died, it will never come back to life.if (mAlive) {status_t status = IPCThreadState::self()->transact(mHandle, code, data, reply, flags);if (status == DEAD_OBJECT) mAlive = 0;return status;}return DEAD_OBJECT;
}
// frameworks/native/libs/binder/IPCThreadState.cppstatus_t IPCThreadState::transact(int32_t handle,uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags)
{// 数据错误检查status_t err = data.errorCheck();flags |= TF_ACCEPT_FDS;// TF_ACCEPT_FDS = 0x10:允许回复中包含文件描述符// TF_ONE_WAY:当前业务是异步的,不需要等待// TF_ROOT_OBJECT:所包含的内容是根对象// TF_STATUS_CODE:所包含的内容是 32-bit 的状态值IF_LOG_TRANSACTIONS() {TextOutput::Bundle _b(alog);alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand "<< handle << " / code " << TypeCode(code) << ": "<< indent << data << dedent << endl;}if (err == NO_ERROR) {LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),(flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");// 整理数据,并把结果存入 mOut 中。(在 talkWithDriver方法中才会将命令真正发送给 Binder驱动)err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);}if (err != NO_ERROR) {if (reply) reply->setError(err);return (mLastError = err);}if ((flags & TF_ONE_WAY) == 0) { // 不是异步,if命中#if 0if (code == 4) { // relayoutALOGI(">>>>>> CALLING transaction 4");} else {ALOGI(">>>>>> CALLING transaction %d", code);}#endifif (reply) { // 不为空err = waitForResponse(reply); // 等待回应事件} else {Parcel fakeReply;err = waitForResponse(&fakeReply);}#if 0if (code == 4) { // relayoutALOGI("<<<<<< RETURNING transaction 4");} else {ALOGI("<<<<<< RETURNING transaction %d", code);}#endifIF_LOG_TRANSACTIONS() {TextOutput::Bundle _b(alog);alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand "<< handle << ": ";if (reply) alog << indent << *reply << dedent << endl;else alog << "(none requested)" << endl;}} else {err = waitForResponse(NULL, NULL);}return err;
}

这又分2个部分进行分析,第一个部分writeTransactionData,第二个部分就是waitForResponse。

3.1.2.2.1 writeTransactionData 
// frameworks/native/libs/binder/IPCThreadState.cppstatus_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{binder_transaction_data tr;tr.target.ptr = 0; /* Don't pass uninitialized stack data to a remote process */tr.target.handle = handle;tr.code = code;tr.flags = binderFlags;tr.cookie = 0;tr.sender_pid = 0;tr.sender_euid = 0;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);tr.data.ptr.offsets = data.ipcObjects();} 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_TRANSACTIONmOut.write(&tr, sizeof(tr)); // 写入 binder_transaction_data数据return NO_ERROR;
}
3.1.2.2.2 IPCThreadState::waitForResponse-1(代码非常长,只截取重要的一部分)
// frameworks/native/libs/binder/IPCThreadState.cppstatus_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) {// 717(行号) 循环等待结果while (1) {if ((err=talkWithDriver()) < NO_ERROR) break;
}
// frameworks/native/libs/binder/IPCThreadState.cpp// 803
status_t IPCThreadState::talkWithDriver(bool doReceive) {// 812 读的 buffer是否为空。现在读为 nullconst bool needRead = mIn.dataPosition() >= mIn.dataSize();// 817 const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0; // 读的时候不能写 mOutbwr.write_size = outAvail;bwr.write_buffer = (uintptr_t)mOut.data(); // 在 bwr中填写需要 write的大小和内容if (doReceive && needRead) {bwr.read_size = mIn.dataCapacity();bwr.read_buffer = (uintptr_t)mIn.data();} else { // needRead为 null,走 elsebwr.read_size = 0;bwr.read_buffer = 0;}// 851do { // while循环条件不会成立,只执行一次/* 856 写入命令 BC_TRANSACTION */if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)} while (err == -EINTR);
}

调用binder_ioctl_write_read

// kernel/drivers/staging/android/binder.c// 3136
static int binder_ioctl_write_read(struct file *filp,unsigned int cmd, unsigned long arg,struct binder_thread *thread) {// 3161 通过这个函数写入用户的数据ret = binder_thread_write(proc, thread,bwr.write_buffer,bwr.write_size,&bwr.write_consumed);}
// kernel/drivers/staging/android/binder.c// 2250
static int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, binder_uintptr_t binder_buffer, size_t size, binder_size_t *consumed) {// 2442case BC_TRANSACTION:binder_transaction(proc, thread, &tr,cmd == BC_REPLY, 0); // 此处 cmd == BC_TRANSACTION,第四个参数为 false}
// kernel/drivers/staging/android/binder.c// 1829
static void binder_transaction(struct binder_proc *proc,struct binder_thread *thread,struct binder_transaction_data *tr, int reply,binder_size_t extra_buffers_size) {// 1861 此处 reply为 false(cmd == BC_TRANSACTION)if (reply) {} else {if (tr->target.handle) { // 不命中 if,handle不为 0,才会命中 if } else { // 此处走 else/* 获取目标对象的 target_node,目标是 service_manager,所以可以直接使用全局变量 binder_context_mgr_node */target_node = context->binder_context_mgr_node;}/* 1919 target_proc为 service_manager进程 */target_proc = target_node->proc;}// 1954 找到 service_manager进程的 todo队列target_list = &target_proc->todo;target_wait = &target_proc->wait;// 1960 生成一个 binder_transaction 变量(即变量 t),用于描述本次要进行的transaction(最后将其加入 target_thread->todo)。// 这样当目标对象被唤醒时,它就可以从这个队列中取出需要做的工作。t = kzalloc(sizeof(*t), GFP_KERNEL);// 1967 生成一个binder_work变量(即变量 tcomplete),用于说明当前调用者线程有一宗未完成的 transaction(它最后会被添加到本线程的 todo队列中)tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);// 1996 给 transaction结构体赋值,即变量 tif (!reply && !(tr->flags & TF_ONE_WAY)) // 非 oneway的通信方式,把当前 thread保存到transaction的 from字段t->from = thread;elset->from = NULL;t->sender_euid = task_euid(proc->tsk);t->to_proc = target_proc; // 此次通信目标进程为 service_manager进程t->to_thread = target_thread;t->code = tr->code; // 此次通信 code = ADD_SERVICE_TRANSACTIONt->flags = tr->flags; // 此次通信 flags = 0t->priority = task_nice(current);// 2009 从 service_manager进程中分配 buffer(为完成本条 transaction申请内存,从binder_mmap开辟的空间中申请内存)t->buffer = binder_alloc_buf(target_proc, tr->data_size,tr->offsets_size, extra_buffers_size,!reply && (t->flags & TF_ONE_WAY));// 2028 分别拷贝用户空间的 binder_transaction_data中 ptr.buffer和 ptr.offsets到内核if (copy_from_user(t->buffer->data, (const void __user *)(uintptr_t)tr->data.ptr.buffer, tr->data_size)) {}if (copy_from_user(offp, (const void __user *)(uintptr_t)tr->data.ptr.offsets, tr->offsets_size)) {}// 2059 for (; offp < off_end; offp++) {// 2075case BINDER_TYPE_BINDER:case BINDER_TYPE_WEAK_BINDER: {struct flat_binder_object *fp;3-5-2-2-1.binder_translate_binder 3-5-2.binder_ioctl_write_read--2--service_manager已被唤醒 fp = to_flat_binder_object(hdr);/* 创建 binder_ref,service_manager的 binder引用对象---见后面小节 */ret = binder_translate_binder(fp, t, thread);if (ret < 0) {return_error = BR_FAILED_REPLY;goto err_translate_failed;}} break;}// 2187 } else if (!(t->flags & TF_ONE_WAY)) {// 2191thread->transaction_stack = t; // 记录本次 transaction,以备后期查询(service_manager通过这个知道是谁调用的,从而返回数据)}// 2201t->work.type = BINDER_WORK_TRANSACTION; // 设置 t的类型为 BINDER_WORK_TRANSACTIONlist_add_tail(&t->work.entry, target_list); // 将 t加入目标的处理队列中tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE; // 设置 binder_work的类型为 BINDER_WORK_TRANSACTION_COMPLETElist_add_tail(&tcomplete->entry, &thread->todo); // 当前线程有一个未完成的操作if (target_wait)wake_up_interruptible(target_wait);// 唤醒目标,即 service_manager
}
// kernel/drivers/staging/android/binder.c// 1564
static int binder_translate_binder(struct flat_binder_object *fp, struct binder_transaction *t, struct binder_thread *thread) {// 1592 创建一个 binder_refref = binder_get_ref_for_node(target_proc, node);// 1596 改变类型为 BINDER_TYPE_HANDLEif (fp->hdr.type == BINDER_TYPE_BINDER)fp->hdr.type = BINDER_TYPE_HANDLE;}
// kernel/drivers/staging/android/binder.c// 3136
static int binder_ioctl_write_read(struct file *filp, unsigned int cmd, unsigned long arg, struct binder_thread *thread) {// 3174ret = binder_thread_read(proc, thread, bwr.read_buffer,bwr.read_size,&bwr.read_consumed,filp->f_flags & O_NONBLOCK);
}
kernel/drivers/staging/android/binder.c// 2652
static int binder_thread_read(struct binder_proc *proc,struct binder_thread *thread,binder_uintptr_t binder_buffer, size_t size,binder_size_t *consumed, int non_block) {// 2664 如果 consumed==0,则写入一个 BR_NOOPif (*consumed == 0) {if (put_user(BR_NOOP, (uint32_t __user *)ptr))// 2739 前面把一个 binder_work添加到 thread->todo队列中,所以 w不为空,类型为 BINDER_WORK_TRANSACTION_COMPLETEif (!list_empty(&thread->todo)) {w = list_first_entry(&thread->todo, struct binder_work,entry);// 2760 写入命令 BR_TRANSACTION_COMPLETEcase BINDER_WORK_TRANSACTION_COMPLETE: {cmd = BR_TRANSACTION_COMPLETE;if (put_user(cmd, (uint32_t __user *)ptr))}
3.1.2.2.3 IPCThreadState::waitForResponse--2
// frameworks/native/libs/binder/IPCThreadState.cpp// 712 
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) {// 786 处理 BR_NOOP命令,什么也没干default:err = executeCommand(cmd);// 718 while循环,继续执行 talkWithDriver方法if ((err=talkWithDriver()) < NO_ERROR) break;// 812 因为 mIn中有数据,所以 needRead为 false,导致 bwr.write_size和 bwr.read_size都为0,直接返回3.1.2.2.4 binder_thread_read--Client线程进入等待 3.1.2.2.5 binder_thread_read--service_manager开始处理消息 3.1.2.2.6 binder_loop const bool needRead = mIn.dataPosition() >= mIn.dataSize();// 731 处理 BR_TRANSACTION_COMPLETE命令case BR_TRANSACTION_COMPLETE:if (!reply && !acquireResult) goto finish; // 当前为同步,不会进入 if,继续 while循环// 718 再次执行 talkWithDriver方法,这个时候 bwr.write_size==0,bwr.read_size还是大于0,所以直接执行驱动中 binder_thread_readif ((err=talkWithDriver()) < NO_ERROR) break;
}
3.1.2.2.4 binder_thread_read--Client线程进入等待 
// kernel/drivers/staging/android/binder.c// 2652
static int binder_thread_read(struct binder_proc *proc,struct binder_thread *thread,binder_uintptr_t binder_buffer, size_t size,binder_size_t *consumed, int non_block) {// 2664 放入 BR_NOOP命令if (*consumed == 0) {if (put_user(BR_NOOP, (uint32_t __user *)ptr))// 2671 此时 wait_for_proc_work为falsewait_for_proc_work = thread->transaction_stack == NULL && list_empty(&thread->todo);// 2717 if (non_block) { // 是阻塞模式的,所以 if不会命中} else // 进入等待,直到 service_manager 来唤醒ret = wait_event_freezable(thread->wait, binder_has_thread_work(thread));
}
3.1.2.2.5 binder_thread_read--service_manager开始处理消息
// kernel/drivers/staging/android/binder.c// 2652
static int binder_thread_read(struct binder_proc *proc,struct binder_thread *thread,binder_uintptr_t binder_buffer, size_t size,binder_size_t *consumed, int non_block) {// 2757 主要是把用户的请求复制到 service_manager中并对各种队列进行调整case BINDER_WORK_TRANSACTION: {t = container_of(w, struct binder_transaction, work);// 2898 设置命令为 BR_TRANSACTIONcmd = BR_TRANSACTION;
}
3.1.2.2.6 binder_loop
// frameworks/native/cmds/servicemanager/binder.c// 372
void binder_loop(struct binder_state *bs, binder_handler func) {// 397 对 getService请求进行解析res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
}
// frameworks/native/cmds/servicemanager/binder.c// 204
int binder_parse(struct binder_state *bs, struct binder_io *bio, uintptr_t ptr, size_t size, binder_handler func) {// 230 case BR_TRANSACTION: {// 237if (func) {// 243 为 reply初始化bio_init(&reply, rdata, sizeof(rdata), 4);// 245res = func(bs, txn, &msg, &reply); // 由 svcmgr_handler 处理请求binder_send_reply(bs, &reply, txn->data.ptr.buffer, res); // 将 reply发给binder驱动}}
// frameworks/native/cmds/servicemanager/service_manager.c// 251
int svcmgr_handler(struct binder_state *bs, struct binder_transaction_data *txn, struct binder_io *msg, struct binder_io *reply) {// 309case SVC_MGR_ADD_SERVICE:// 316 注册指定服务if (do_add_service(bs, s, len, handle, txn->sender_euid,allow_isolated, txn->sender_pid))}
// frameworks/native/cmds/servicemanager/service_manager.c// 201
int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len,binder_send_reply uint32_t handle, uid_t uid, int allow_isolated, pid_t spid)// 214 if (!svc_can_register(s, len, spid, uid)) {// 220si = find_svc(s, len);if (si) {if (si->handle) {svcinfo_death(bs, si); // 服务已注册时,释放相应的服务}si->handle = handle; // 重新放入新的} else {si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));if (!si) { // 内存不足,无法分配足够内存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->next = svclist; // svclist保存所有已注册的服务svclist = si;}/* 以 BC_ACQUIRE命令,handle为目标的信息,通过 ioctl发送给 binder驱动,binder_ref强引用加 1操作 */binder_acquire(bs, handle); /* 以 BC_REQUEST_DEATH_NOTIFICATION命令的信息,通过 ioctl发送给 binder驱动,主要用于清理内存等收尾工作 */binder_link_to_death(bs, handle, &si->death);}
// kernel/drivers/staging/android/binder.c// 2250 
static int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, binder_uintptr_t binder_buffer, size_t size, binder_size_t *consumed) {binder_transaction(proc, thread, &tr, cmd == BC_REPLY, 0);
}

3.1.3 总结:

4 线程池管理

  • 主线程 -- 不会退出,非主线程
  • 线程最大数 --- 15个 --- 非主线程
  • 主线程有一个 -- 不算这在线程最大数
  • 线程真正最大数 : 15 + 1 + 其他线程

待更新....

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词