ProcessState以及IPCThreadState

ProcessState是负责打开Binder节点并做mmap映射,IPCThreadState是负责与Binder驱动进行具体的命令交互。

ProcessState

  1. 实现ProcessState的主要关键点有以下几个:
  • 保证同一进程只有一个ProcessState实例,且只有在ProcessState对象建立时才打开Binder设备以及做内存映射
  • 向上层提供IPc服务
  • 与IPCThreadState分工
  1. 首先分析第一个点:
    源码位置:/frameworks/native/libs/binder/ProcessState.cpp  http://androidxref.com/6.0.1_r10/xref/frameworks/native/libs/binder/ProcessState.cpp
sp<ProcessState> ProcessState::self()
{
if (gProcess != NULL) return gProcess; AutoMutex _l(gProcessMutex);
if (gProcess == NULL) gProcess = new ProcessState;
return gProcess;
}

可以看到,在这里也是先检查是否存在一个已经实例化的prosessstate,否则创建一个,所以获取ProcessState对象,需要通过这个self方法。
接下来需要一步步的观察这个新建的过程当中实现的原理。

  1. 分析构造函数:
ProcessState::ProcessState()
: mDriverFD(open_driver())
, mVMStart(MAP_FAILED)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
, mThreadPoolStarted(false)
, mThreadPoolSeq()
{
if (mDriverFD >= ) {
mVMStart = mmap(, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, );
if (mVMStart == MAP_FAILED) {
// *sigh*
LOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
close(mDriverFD);
mDriverFD = -;
}
#else
mDriverFD = -;
#endif
}
if (mDriverFD < ) {
// Need to run without the driver, starting our own thread pool.
}
}

可以看到有两个之前学习的时候了解到了,与Binder驱动紧密相关的方法:
一个是open_driver(),另一个是下面的mmap(),也就是最终打开了Binder结点以及进行了内存块的映射。

  1. 接下来分析在之前用到的获取IBinder的对象时的一个方法:getContextObject
    在这个方法中,传入了一个handel,最终得到了一个BpBinder,而这个BpBinder是Binder在Native层的代理。
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
return getStrongProxyForHandle();
}
ProcessState::getStrongProxyForHandle
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result; AutoMutex _l(mLock); handle_entry* e = lookupHandleLocked(handle); if (e != NULL) {
......
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
if (handle == ) {
......
Parcel data;
status_t status = IPCThreadState::self()->transact(
, IBinder::PING_TRANSACTION, data, NULL, );
if (status == DEAD_OBJECT)
return NULL;
} 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;
}

ProcessState::lookupHandleLocked

ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)
{
const size_t N=mHandleToObject.size();
if (N <= (size_t)handle) {
handle_entry e;
e.binder = NULL;
e.refs = NULL;
status_t err = mHandleToObject.insertAt(e, N, handle+-N);
if (err < NO_ERROR) return NULL;
}
return &mHandleToObject.editItemAt(handle);
}

从这儿看,先调用lookupHandleLocked方法,由于是第一次调用,因此新建一个handle_entry,并返回,而且其binder和refs为NULL
那么getStrongProxyForHandle方法接着往下走,由于binder为NULL,mHandle传入的是0,因此进入判断条件中,最后new BpBinder,且参数为0

因此,返回的是new BpBinder(0)

sp<IBinder> b = ProcessState::self()->getContextObject(NULL);

IPCThreadState

代码位置:/frameworks/native/libs/binder/IPCThreadState.cpp

http://androidxref.com/6.0.1_r10/xref/frameworks/native/libs/binder/IPCThreadState.cpp

  1. 单实例构造函数:
IPCThreadState* IPCThreadState::self()
{
if (gHaveTLS) {
//当执行完第一次之后,再次运行的时候就已经有IPCThreadState实例,只需要获取就可以使用
restart:
const pthread_key_t k = gTLS;
IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
if (st) return st;
return new IPCThreadState;
} if (gShutdown) {
ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n");
return NULL;
} pthread_mutex_lock(&gTLSMutex);
if (!gHaveTLS) {
//初始的gHaveTLS的值false,所以第一次调用的时候,会执行这里的代码
//随后将gHaveTLS设置为true
int key_create_value = pthread_key_create(&gTLS, threadDestructor);
if (key_create_value != ) {
pthread_mutex_unlock(&gTLSMutex);
ALOGW("IPCThreadState::self() unable to create TLS key, expect a crash: %s\n",
strerror(key_create_value));
return NULL;
}
gHaveTLS = true;
}
pthread_mutex_unlock(&gTLSMutex);
goto restart;
}

通过上面的方法,就能保证“线程单实例”的目的

  1. 现有的调用分析顺序是:
    getService@ServiceManagerProxy-->transact@BinderProxy-->transact@BpBinder-->transact@IPCThreadState
  2. 不管是读取还是写入,Binder驱动都只是发挥中间人的作用,真正处理请求的还是Binder Client以及Binder Server双方。
  3. 真正与Binder打交道的地方时talkWithDriver中的ioctl()

Binder进程与线程ProcessState以及IPCThreadState的更多相关文章

  1. 一篇文章了解相见恨晚的 Android Binder 进程间通讯机制【转】

    本文转载自:https://blog.csdn.net/freekiteyu/article/details/70082302 Android-Binder进程间通讯机制 概述 最近在学习Binder ...

  2. Android Binder 进程间通讯机制梳理

    什么是 Binder ? Binder是Android系统中进程间通讯(IPC)的一种方式,也是Android系统中最重要的特性之一.Binder的设计采用了面向对象的思想,在Binder通信模型的四 ...

  3. [置顶] Android开发之ProcessState和IPCThreadState类分析

    在Android中ProcessState是客户端和服务端公共的部分,作为Binder通信的基础,ProcessState是一个singleton类,每个 进程只有一个对象,这个对象负责打开Binde ...

  4. android 进程和线程管理

    进程和线程的概念: 进程:程序的运行实例. 线程:cpu调度基本单位. Activity启动的时候,启动一个主线程,两个binder线程. 主线程实如何产生的?ZygoteInit启动,经由一系列调用 ...

  5. 关于Java中进程和线程的详解

    一.进程:是程序的一次动态执行,它对应着从代码加载,执行至执行完毕的一个完整的过程,是一个动态的实体,它有自己的生命 周期.它因创建而产生,因调度而运行,因等待资源或事件而被处于等待状态,因完成任务而 ...

  6. Java中的进程和线程

     Java中的进程与线程 一:进程与线程 概述:几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进程运行时,内部可能包括多个顺序执行流,每个顺序执行流就是 ...

  7. Java中的进程与线程(总结篇)

    详细文档: Java中的进程与线程.rar 474KB 1/7/2017 6:21:15 PM 概述: 几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进 ...

  8. C# - 多线程 之 进程与线程

    并行~并发 并发 Concurrency,逻辑上的同时发生,一个处理器(在不同时刻或者说在同一时间间隔内)"同时"处理多个任务.宏观上是并发的,微观上是按排队等待.唤醒.执行的步骤 ...

  9. Android 的进程和线程

    进程和线程 如果某个应用程序组件是第一次被启动,且这时应用程序也没有其他组件在运行,则android系统会为应用程序创建一个包含单个线程的linux进程.默认情况下,同一个应用程序的所有组件都运行在同 ...

随机推荐

  1. 吴恩达深度学习:2.1Logistic Regression逻辑回归及其损失函数

    1.Logistic Regression是一个二元分类问题 (1)已知输入的特征向量x可能是一张图,你希望把它识别出来,这是不是猫图,你需要一个算法,可以给出预测值,更正式的y是一个概率,当输入特征 ...

  2. C# 同比缩放图片

    /** * 无损缩放图片 * bitmap 需要缩放的图片 * w 需要缩放的宽度 * h 需要缩放的高度 * */ public static System.Drawing.Bitmap TBSca ...

  3. Vue组件化和路由

    组件化 组件化是vue的核心思想,它能提高开发效率,方便重复使用,简化调试步骤,提升整个项目的可维护性,便于多人协同开发 组件通信 父组件 => 子组件: 属性props 特性$attrs 引用 ...

  4. 编程的智慧(王垠)(http://www.cocoachina.com/programmer/20151125/14410.html)

    编程是一件创造性的工作,是一门艺术.精通任何一门艺术,都需要很多的练习和领悟,所以这里提出的“智慧”,并不是号称三天瘦二十斤的减肥药,它并不能代替你自己的勤奋.然而我希望它能给迷惑中的人们指出一些正确 ...

  5. Nginx设置上传文件大小限制

    就是nginx对上传的图片大小有了限制嘛,所以更改nginx的配置文件就好了 client_max_body_size 1000m; 参考:https://blog.csdn.net/TitanSee ...

  6. H5微信授权登录

    这里介绍H5微信授权登录,采用了微信公众号授权原理,是oauth2的登录授权方式,简单的来讲,就是用户通过手机微信确认登录之后,微信方会返回一个授权码code给回第三方(接入方),这个授权码code一 ...

  7. 内置time模块和random模块

    #time模块#time模块中有三种时间表达方式#时间戳(timestamp):指从1970年1月1号0:0:0开始按秒计算的时间偏移量#元组形式的结构化时间(strut_time):含有9个元素(t ...

  8. 4--面试总结-promise

    promise异步原理: 定义:promise是异步编程的解决方案,可以解决异步回调地狱的问题: 原理:三种状态两种结果的一个状态机:三种状态(pending,fulfilled,rejected)两 ...

  9. Python之常用模块一(主要RE和collections)

    一.认识模块  什么是模块:一个模块就是一个包含了python定义和声明的文件,文件名就是加上.py的后缀,但其实import加载的模块分为四个通用类别 : 1.使用python编写的代码(.py文件 ...

  10. Git版本控制工具初识

    Git使用教程 0 Git下载安装 下载网址:https://www.git-scm.com/download/ 安装时,一路next就可以了,如果遇到下载很慢时,可以选择换个浏览器试试,实在不行就找 ...